diff --git a/stm32/bootloader/releases/1.0.1.txt b/stm32/bootloader/releases/1.0.1.txt new file mode 100644 index 00000000..00939b23 --- /dev/null +++ b/stm32/bootloader/releases/1.0.1.txt @@ -0,0 +1,17 @@ +8c6e991355d465139ab7a361b215711fa0cf71afaa233fb82ed2359308397d0b bootloader.dfu +069828758f3c8e7208e35f56db9c92788c4b70e0259b961cb83f1d6a9248e57d bootloader.bin +6a374397614279a387a1fbd026e8dcc7350347003a14de04a29dc46e072dcea4 bootloader.lss +1.0.1 time=20180807.112012 git=master@6e7f044 + +Expect to see: + + 1.0.1 + 50def122 + +on versions screen. + + [bootloader/releases] cat zz 1.0.1/bootloader.bin | sha256 + 3bbd550fd9b8bfa07a3803eb2ae608c494a58ec59d376372d18990a850def122 - + + + diff --git a/stm32/bootloader/releases/1.0.1/bootloader.bin b/stm32/bootloader/releases/1.0.1/bootloader.bin new file mode 100644 index 00000000..d6a78660 Binary files /dev/null and b/stm32/bootloader/releases/1.0.1/bootloader.bin differ diff --git a/stm32/bootloader/releases/1.0.1/bootloader.dfu b/stm32/bootloader/releases/1.0.1/bootloader.dfu new file mode 100644 index 00000000..8c189014 Binary files /dev/null and b/stm32/bootloader/releases/1.0.1/bootloader.dfu differ diff --git a/stm32/bootloader/releases/1.0.1/bootloader.lss b/stm32/bootloader/releases/1.0.1/bootloader.lss new file mode 100644 index 00000000..55ce42f2 --- /dev/null +++ b/stm32/bootloader/releases/1.0.1/bootloader.lss @@ -0,0 +1,24676 @@ + +bootloader.elf: file format elf32-littlearm + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00007568 08000000 08000000 00010000 2**8 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .relocate 0000024c 10006000 08007568 00026000 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 2 .bss 00000104 1000624c 080077b4 0002624c 2**2 + ALLOC + 3 .stack 00000400 10006350 080078b8 0002624c 2**0 + ALLOC + 4 .debug_info 0001370a 00000000 00000000 0002624c 2**0 + CONTENTS, READONLY, DEBUGGING + 5 .debug_abbrev 00003116 00000000 00000000 00039956 2**0 + CONTENTS, READONLY, DEBUGGING + 6 .debug_loc 000079cb 00000000 00000000 0003ca6c 2**0 + CONTENTS, READONLY, DEBUGGING + 7 .debug_aranges 000008b0 00000000 00000000 00044437 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_ranges 00000d28 00000000 00000000 00044ce7 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .debug_macro 00029b07 00000000 00000000 00045a0f 2**0 + CONTENTS, READONLY, DEBUGGING + 10 .debug_line 0000a86e 00000000 00000000 0006f516 2**0 + CONTENTS, READONLY, DEBUGGING + 11 .debug_str 000edc35 00000000 00000000 00079d84 2**0 + CONTENTS, READONLY, DEBUGGING + 12 .comment 0000006e 00000000 00000000 001679b9 2**0 + CONTENTS, READONLY + 13 .ARM.attributes 00000037 00000000 00000000 00167a27 2**0 + CONTENTS, READONLY + 14 .debug_frame 00001a04 00000000 00000000 00167a60 2**2 + CONTENTS, READONLY, DEBUGGING + +Disassembly of section .text: + +08000000 <_sfixed>: + 8000000: 10007c00 .word 0x10007c00 + 8000004: 080000b1 .word 0x080000b1 + 8000008: 0800001d .word 0x0800001d + 800000c: 0800001f .word 0x0800001f + 8000010: 08000021 .word 0x08000021 + 8000014: 08000023 .word 0x08000023 + 8000018: 08000025 .word 0x08000025 + +0800001c : + 800001c: be01 bkpt 0x0001 + +0800001e : + 800001e: be02 bkpt 0x0002 + +08000020 : + 8000020: be03 bkpt 0x0003 + +08000022 : + 8000022: be04 bkpt 0x0004 + +08000024 : + 8000024: be05 bkpt 0x0005 + 8000026: e7fe b.n 8000026 + +08000028 : + ... + 8000040: 08000305 .word 0x08000305 + +08000044 : + 8000044: 00000100 .word 0x00000100 + ... + 8000060: 20296328 .word 0x20296328 + 8000064: 79706f43 .word 0x79706f43 + 8000068: 68676972 .word 0x68676972 + 800006c: 30322074 .word 0x30322074 + 8000070: 62203831 .word 0x62203831 + 8000074: 6f432079 .word 0x6f432079 + 8000078: 696b6e69 .word 0x696b6e69 + 800007c: 49206574 .word 0x49206574 + 8000080: 202e636e .word 0x202e636e + 8000084: 540a200a .word 0x540a200a + 8000088: 20736968 .word 0x20736968 + 800008c: 63617073 .word 0x63617073 + 8000090: 6f662065 .word 0x6f662065 + 8000094: 65722072 .word 0x65722072 + 8000098: 202e746e .word 0x202e746e + 800009c: 7473754a .word 0x7473754a + 80000a0: 54423120 .word 0x54423120 + 80000a4: 65792f43 .word 0x65792f43 + 80000a8: 202e7261 .word 0x202e7261 + 80000ac: 000a200a .word 0x000a200a + +080000b0 : + 80000b0: f000 f816 bl 80000e0 + 80000b4: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff + 80000b8: f04f 0100 mov.w r1, #0 + 80000bc: f04f 0200 mov.w r2, #0 + 80000c0: f04f 0300 mov.w r3, #0 + 80000c4: f000 f91e bl 8000304 + 80000c8: f248 0108 movw r1, #32776 ; 0x8008 + 80000cc: ea4f 3101 mov.w r1, r1, lsl #12 + 80000d0: 6808 ldr r0, [r1, #0] + 80000d2: 4685 mov sp, r0 + 80000d4: f04f 0001 mov.w r0, #1 + 80000d8: f8d1 e004 ldr.w lr, [r1, #4] + 80000dc: 4770 bx lr + ... + +080000e0 : + 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(); + 80000e0: 4b1c ldr r3, [pc, #112] ; (8000154 ) +// It's best if this is outside the firewall. After we return, we'll +// jump into setup code contained inside the firewall. +// + void +firewall_setup(void) +{ + 80000e2: b500 push {lr} + // 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: 6e1a ldr r2, [r3, #96] ; 0x60 + 80000e6: f042 0201 orr.w r2, r2, #1 + 80000ea: 661a str r2, [r3, #96] ; 0x60 + 80000ec: 6e1b ldr r3, [r3, #96] ; 0x60 +// It's best if this is outside the firewall. After we return, we'll +// jump into setup code contained inside the firewall. +// + void +firewall_setup(void) +{ + 80000ee: b08b sub sp, #44 ; 0x2c + // 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(); + 80000f0: f003 0301 and.w r3, r3, #1 + 80000f4: 9300 str r3, [sp, #0] + 80000f6: 9b00 ldr r3, [sp, #0] + + if(__HAL_FIREWALL_IS_ENABLED()) { + 80000f8: 4b17 ldr r3, [pc, #92] ; (8000158 ) + 80000fa: 685b ldr r3, [r3, #4] + 80000fc: 07db lsls r3, r3, #31 + 80000fe: d525 bpl.n 800014c + // REMINDERS: + // - cannot debug anything in boot loader w/ firewall enabled (no readback, no bkpt) + // - with 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(rom_secrets->bag_number, sizeof(rom_secrets->bag_number))) { + 8000100: 2120 movs r1, #32 + 8000102: 4816 ldr r0, [pc, #88] ; (800015c ) + 8000104: f001 fea2 bl 8001e4c + 8000108: bb00 cbnz r0, 800014c + // ok. still virgin unit -- run w/o security + return; + } + + extern int firewall_starts; // see startup.S ... aligned@256 (0x08000300) + uint32_t start = (uint32_t)&firewall_starts; + 800010a: 4b15 ldr r3, [pc, #84] ; (8000160 ) + // but sensitive stuff is still there (which would allow bypass) + // - so it's important to enable option bytes to set write-protect on entire bootloader + // - to disable debug and complete protection, must enable write-protect "level 2" + // + + FIREWALL_InitTypeDef init = { + 800010c: 9302 str r3, [sp, #8] + 800010e: f1c3 6300 rsb r3, r3, #134217728 ; 0x8000000 + 8000112: f503 43f0 add.w r3, r3, #30720 ; 0x7800 + 8000116: 9303 str r3, [sp, #12] + 8000118: 4b12 ldr r3, [pc, #72] ; (8000164 ) + 800011a: 9304 str r3, [sp, #16] + 800011c: 9006 str r0, [sp, #24] + 800011e: f44f 6300 mov.w r3, #2048 ; 0x800 + 8000122: 9007 str r0, [sp, #28] + 8000124: 9008 str r0, [sp, #32] + 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 + // but sensitive stuff is still there (which would allow bypass) + // - so it's important to enable option bytes to set write-protect on entire bootloader + // - to disable debug and complete protection, must enable write-protect "level 2" + // + + FIREWALL_InitTypeDef init = { + 800012a: 9305 str r3, [sp, #20] + .VDataSegmentLength = 0, + .VolatileDataExecution = 0, + .VolatileDataShared = 0, + }; + + int rv = HAL_FIREWALL_Config((FIREWALL_InitTypeDef *)&init); + 800012c: f000 f81e bl 800016c + if(rv) { + 8000130: b100 cbz r0, 8000134 + BREAKPOINT; + 8000132: be00 bkpt 0x0000 + } + + __HAL_FIREWALL_PREARM_DISABLE(); + 8000134: 4b0c ldr r3, [pc, #48] ; (8000168 ) + 8000136: 6a1a ldr r2, [r3, #32] + 8000138: f022 0201 bic.w r2, r2, #1 + 800013c: 621a str r2, [r3, #32] + 800013e: 6a1b ldr r3, [r3, #32] + 8000140: f003 0301 and.w r3, r3, #1 + 8000144: 9301 str r3, [sp, #4] + 8000146: 9b01 ldr r3, [sp, #4] + HAL_FIREWALL_EnableFirewall(); + 8000148: f000 f88c bl 8000264 +} + 800014c: b00b add sp, #44 ; 0x2c + 800014e: f85d fb04 ldr.w pc, [sp], #4 + 8000152: bf00 nop + 8000154: 40021000 .word 0x40021000 + 8000158: 40010000 .word 0x40010000 + 800015c: 08007850 .word 0x08007850 + 8000160: 08000300 .word 0x08000300 + 8000164: 08007800 .word 0x08007800 + 8000168: 40011c00 .word 0x40011c00 + +0800016c : + * @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) +{ + 800016c: b513 push {r0, r1, r4, lr} + /* Check the Firewall initialization structure allocation */ + if(fw_init == NULL) + 800016e: b908 cbnz r0, 8000174 + { + return HAL_ERROR; + 8000170: 2001 movs r0, #1 + 8000172: e033 b.n 80001dc + } + + /* Enable Firewall clock */ + __HAL_RCC_FIREWALL_CLK_ENABLE(); + 8000174: 4b1a ldr r3, [pc, #104] ; (80001e0 ) + 8000176: 6e1a ldr r2, [r3, #96] ; 0x60 + 8000178: f042 0280 orr.w r2, r2, #128 ; 0x80 + 800017c: 661a str r2, [r3, #96] ; 0x60 + 800017e: 6e1b ldr r3, [r3, #96] ; 0x60 + 8000180: f003 0380 and.w r3, r3, #128 ; 0x80 + 8000184: 9301 str r3, [sp, #4] + 8000186: 9b01 ldr r3, [sp, #4] + + /* Make sure that Firewall is not enabled already */ + if (__HAL_FIREWALL_IS_ENABLED() != RESET) + 8000188: 4b16 ldr r3, [pc, #88] ; (80001e4 ) + 800018a: 685b ldr r3, [r3, #4] + 800018c: 07db lsls r3, r3, #31 + 800018e: d5ef bpl.n 8000170 + assert_param(IS_FIREWALL_VOLATILEDATA_SHARE(fw_init->VolatileDataShared)); + + /* Configuration */ + + /* Protected code segment start address configuration */ + WRITE_REG(FIREWALL->CSSA, (FW_CSSA_ADD & fw_init->CodeSegmentStartAddress)); + 8000190: 6802 ldr r2, [r0, #0] + 8000192: 4b15 ldr r3, [pc, #84] ; (80001e8 ) + 8000194: f022 427f bic.w r2, r2, #4278190080 ; 0xff000000 + 8000198: f022 02ff bic.w r2, r2, #255 ; 0xff + 800019c: 601a str r2, [r3, #0] + /* Protected code segment length configuration */ + WRITE_REG(FIREWALL->CSL, (FW_CSL_LENG & fw_init->CodeSegmentLength)); + 800019e: 6841 ldr r1, [r0, #4] + 80001a0: 4a12 ldr r2, [pc, #72] ; (80001ec ) + 80001a2: 400a ands r2, r1 + 80001a4: 605a str r2, [r3, #4] + + /* Protected non volatile data segment start address configuration */ + WRITE_REG(FIREWALL->NVDSSA, (FW_NVDSSA_ADD & fw_init->NonVDataSegmentStartAddress)); + 80001a6: 6882 ldr r2, [r0, #8] + 80001a8: f022 427f bic.w r2, r2, #4278190080 ; 0xff000000 + 80001ac: f022 02ff bic.w r2, r2, #255 ; 0xff + 80001b0: 609a str r2, [r3, #8] + /* Protected non volatile data segment length configuration */ + WRITE_REG(FIREWALL->NVDSL, (FW_NVDSL_LENG & fw_init->NonVDataSegmentLength)); + 80001b2: 68c1 ldr r1, [r0, #12] + 80001b4: 4a0d ldr r2, [pc, #52] ; (80001ec ) + 80001b6: 400a ands r2, r1 + 80001b8: 60da str r2, [r3, #12] + + /* Protected volatile data segment start address configuration */ + WRITE_REG(FIREWALL->VDSSA, (FW_VDSSA_ADD & fw_init->VDataSegmentStartAddress)); + 80001ba: 6901 ldr r1, [r0, #16] + 80001bc: 4a0c ldr r2, [pc, #48] ; (80001f0 ) + 80001be: 400a ands r2, r1 + 80001c0: 611a str r2, [r3, #16] + /* Protected volatile data segment length configuration */ + WRITE_REG(FIREWALL->VDSL, (FW_VDSL_LENG & fw_init->VDataSegmentLength)); + 80001c2: 6941 ldr r1, [r0, #20] + 80001c4: 4a0a ldr r2, [pc, #40] ; (80001f0 ) + 80001c6: 400a ands r2, r1 + 80001c8: 615a str r2, [r3, #20] + + /* 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); + 80001ca: 6984 ldr r4, [r0, #24] + 80001cc: 69c1 ldr r1, [r0, #28] + 80001ce: 6a1a ldr r2, [r3, #32] + 80001d0: 4321 orrs r1, r4 + 80001d2: f022 0206 bic.w r2, r2, #6 + 80001d6: 430a orrs r2, r1 + 80001d8: 621a str r2, [r3, #32] + + return HAL_OK; + 80001da: 2000 movs r0, #0 +} + 80001dc: b002 add sp, #8 + 80001de: bd10 pop {r4, pc} + 80001e0: 40021000 .word 0x40021000 + 80001e4: 40010000 .word 0x40010000 + 80001e8: 40011c00 .word 0x40011c00 + 80001ec: 003fff00 .word 0x003fff00 + 80001f0: 0001ffc0 .word 0x0001ffc0 + +080001f4 : +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(); + 80001f4: 4b17 ldr r3, [pc, #92] ; (8000254 ) + + /* Retrieve code segment protection setting */ + fw_config->CodeSegmentStartAddress = (READ_REG(FIREWALL->CSSA) & FW_CSSA_ADD); + fw_config->CodeSegmentLength = (READ_REG(FIREWALL->CSL) & FW_CSL_LENG); + 80001f6: 4918 ldr r1, [pc, #96] ; (8000258 ) +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: 6e1a ldr r2, [r3, #96] ; 0x60 + 80001fa: f042 0280 orr.w r2, r2, #128 ; 0x80 + 80001fe: 661a str r2, [r3, #96] ; 0x60 + 8000200: 6e1b ldr r3, [r3, #96] ; 0x60 + * is defined, this API can't be executed when the Firewall is enabled. + * @note User should resort to __HAL_FIREWALL_GET_PREARM() macro to retrieve FPA bit status + * @retval None + */ +void HAL_FIREWALL_GetConfig(FIREWALL_InitTypeDef * fw_config) +{ + 8000202: b082 sub sp, #8 + + /* Enable Firewall clock, in case no Firewall configuration has been carried + out up to this point */ + __HAL_RCC_FIREWALL_CLK_ENABLE(); + 8000204: f003 0380 and.w r3, r3, #128 ; 0x80 + 8000208: 9301 str r3, [sp, #4] + 800020a: 9b01 ldr r3, [sp, #4] + + /* Retrieve code segment protection setting */ + fw_config->CodeSegmentStartAddress = (READ_REG(FIREWALL->CSSA) & FW_CSSA_ADD); + 800020c: 4b13 ldr r3, [pc, #76] ; (800025c ) + 800020e: 681a ldr r2, [r3, #0] + 8000210: f022 427f bic.w r2, r2, #4278190080 ; 0xff000000 + 8000214: f022 02ff bic.w r2, r2, #255 ; 0xff + 8000218: 6002 str r2, [r0, #0] + fw_config->CodeSegmentLength = (READ_REG(FIREWALL->CSL) & FW_CSL_LENG); + 800021a: 685a ldr r2, [r3, #4] + 800021c: 400a ands r2, r1 + 800021e: 6042 str r2, [r0, #4] + + /* Retrieve non volatile data segment protection setting */ + fw_config->NonVDataSegmentStartAddress = (READ_REG(FIREWALL->NVDSSA) & FW_NVDSSA_ADD); + 8000220: 689a ldr r2, [r3, #8] + 8000222: f022 427f bic.w r2, r2, #4278190080 ; 0xff000000 + 8000226: f022 02ff bic.w r2, r2, #255 ; 0xff + 800022a: 6082 str r2, [r0, #8] + fw_config->NonVDataSegmentLength = (READ_REG(FIREWALL->NVDSL) & FW_NVDSL_LENG); + 800022c: 68da ldr r2, [r3, #12] + 800022e: 4011 ands r1, r2 + 8000230: 60c1 str r1, [r0, #12] + + /* Retrieve volatile data segment protection setting */ + fw_config->VDataSegmentStartAddress = (READ_REG(FIREWALL->VDSSA) & FW_VDSSA_ADD); + 8000232: 6919 ldr r1, [r3, #16] + 8000234: 4a0a ldr r2, [pc, #40] ; (8000260 ) + 8000236: 4011 ands r1, r2 + 8000238: 6101 str r1, [r0, #16] + fw_config->VDataSegmentLength = (READ_REG(FIREWALL->VDSL) & FW_VDSL_LENG); + 800023a: 6959 ldr r1, [r3, #20] + 800023c: 400a ands r2, r1 + 800023e: 6142 str r2, [r0, #20] + + /* Retrieve volatile data execution setting */ + fw_config->VolatileDataExecution = (READ_REG(FIREWALL->CR) & FW_CR_VDE); + 8000240: 6a1a ldr r2, [r3, #32] + 8000242: f002 0204 and.w r2, r2, #4 + 8000246: 6182 str r2, [r0, #24] + + /* Retrieve volatile data shared setting */ + fw_config->VolatileDataShared = (READ_REG(FIREWALL->CR) & FW_CR_VDS); + 8000248: 6a1b ldr r3, [r3, #32] + 800024a: f003 0302 and.w r3, r3, #2 + 800024e: 61c3 str r3, [r0, #28] + + return; +} + 8000250: b002 add sp, #8 + 8000252: 4770 bx lr + 8000254: 40021000 .word 0x40021000 + 8000258: 003fff00 .word 0x003fff00 + 800025c: 40011c00 .word 0x40011c00 + 8000260: 0001ffc0 .word 0x0001ffc0 + +08000264 : + * @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 ) + 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 : + * @retval None + */ +void HAL_FIREWALL_EnablePreArmFlag(void) +{ + /* Set FPA bit */ + SET_BIT(FIREWALL->CR, FW_CR_FPA); + 8000274: 4a02 ldr r2, [pc, #8] ; (8000280 ) + 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 : + * @retval None + */ +void HAL_FIREWALL_DisablePreArmFlag(void) +{ + /* Clear FPA bit */ + CLEAR_BIT(FIREWALL->CR, FW_CR_FPA); + 8000284: 4a02 ldr r2, [pc, #8] ; (8000290 ) + 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 : + 8000304: f246 0900 movw r9, #24576 ; 0x6000 + 8000308: f2c1 0900 movt r9, #4096 ; 0x1000 + 800030c: f44f 5ae0 mov.w sl, #7168 ; 0x1c00 + 8000310: 44ca add sl, r9 + +08000312 : + 8000312: f849 ab04 str.w sl, [r9], #4 + 8000316: 45d1 cmp r9, sl + 8000318: d1fb bne.n 8000312 + 800031a: 46cd mov sp, r9 + 800031c: b500 push {lr} + +0800031e : + 800031e: f000 f957 bl 80005d0 + 8000322: f85d eb04 ldr.w lr, [sp], #4 + 8000326: f246 0900 movw r9, #24576 ; 0x6000 + 800032a: f2c1 0900 movt r9, #4096 ; 0x1000 + 800032e: f44f 5ae0 mov.w sl, #7168 ; 0x1c00 + 8000332: 44ca add sl, r9 + +08000334 : + 8000334: f849 0b04 str.w r0, [r9], #4 + 8000338: 45d1 cmp r9, sl + 800033a: d1fb bne.n 8000334 + 800033c: 4770 bx lr + ... + +08000340 : + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); + 8000340: f3bf 8f4f dsb sy +__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) | + 8000344: 4905 ldr r1, [pc, #20] ; (800035c ) + */ +__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) | + 8000346: 4b06 ldr r3, [pc, #24] ; (8000360 ) + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + 8000348: 68ca ldr r2, [r1, #12] + */ +__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) | + 800034a: f402 62e0 and.w r2, r2, #1792 ; 0x700 + 800034e: 4313 orrs r3, r2 + 8000350: 60cb str r3, [r1, #12] + 8000352: f3bf 8f4f dsb sy + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); + 8000356: bf00 nop + 8000358: e7fd b.n 8000356 + 800035a: bf00 nop + 800035c: e000ed00 .word 0xe000ed00 + 8000360: 05fa0004 .word 0x05fa0004 + +08000364 : + static int +good_addr(const uint8_t *b, int minlen, int len, bool readonly) +{ + uint32_t x = (uint32_t)b; + + if(minlen) { + 8000364: b111 cbz r1, 800036c + if(!b) return EFAULT; // gave no buffer + 8000366: b188 cbz r0, 800038c + if(len < minlen) return ERANGE; // too small + 8000368: 4291 cmp r1, r2 + 800036a: dc11 bgt.n 8000390 + } + + + if((x >= SRAM1_BASE) && ((x-SRAM1_BASE) < SRAM1_SIZE_MAX)) { + 800036c: f100 4260 add.w r2, r0, #3758096384 ; 0xe0000000 + 8000370: f5b2 3fc0 cmp.w r2, #98304 ; 0x18000 + 8000374: d30e bcc.n 8000394 + // inside SRAM1, okay + return 0; + } + + if(!readonly) { + 8000376: b17b cbz r3, 8000398 + return EPERM; + } + + if((x >= FIRMWARE_START) && (x - FIRMWARE_START) < FW_MAX_LENGTH) { + 8000378: f100 4078 add.w r0, r0, #4160749568 ; 0xf8000000 + 800037c: f5a0 4000 sub.w r0, r0, #32768 ; 0x8000 + // inside flash of main firmware (happens for QSTR's) + return 0; + } + + return EACCES; + 8000380: f5b0 2f78 cmp.w r0, #1015808 ; 0xf8000 + 8000384: bf34 ite cc + 8000386: 2000 movcc r0, #0 + 8000388: 200d movcs r0, #13 + 800038a: 4770 bx lr +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 + 800038c: 200e movs r0, #14 + 800038e: 4770 bx lr + if(len < minlen) return ERANGE; // too small + 8000390: 2022 movs r0, #34 ; 0x22 + 8000392: 4770 bx lr + } + + + if((x >= SRAM1_BASE) && ((x-SRAM1_BASE) < SRAM1_SIZE_MAX)) { + // inside SRAM1, okay + return 0; + 8000394: 2000 movs r0, #0 + 8000396: 4770 bx lr + } + + if(!readonly) { + return EPERM; + 8000398: 2001 movs r0, #1 + // inside flash of main firmware (happens for QSTR's) + return 0; + } + + return EACCES; +} + 800039a: 4770 bx lr + +0800039c : +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + *dest = value; + 800039c: 4808 ldr r0, [pc, #32] ; (80003c0 ) +// memset4() +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + 800039e: 4a09 ldr r2, [pc, #36] ; (80003c4 ) + +// wipe_all_sram() +// + static void +wipe_all_sram(void) +{ + 80003a0: f04f 5300 mov.w r3, #536870912 ; 0x20000000 +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + *dest = value; + 80003a4: f843 0b04 str.w r0, [r3], #4 +// memset4() +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + 80003a8: 4293 cmp r3, r2 + 80003aa: 4905 ldr r1, [pc, #20] ; (80003c0 ) + 80003ac: d1fa bne.n 80003a4 + 80003ae: 4a06 ldr r2, [pc, #24] ; (80003c8 ) + 80003b0: f04f 5380 mov.w r3, #268435456 ; 0x10000000 + *dest = value; + 80003b4: f843 1b04 str.w r1, [r3], #4 +// memset4() +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + 80003b8: 4293 cmp r3, r2 + 80003ba: d1fb bne.n 80003b4 + const uint32_t noise = 0xdeadbeef; + + // wipe all of SRAM (except our own memory, which was already wiped) + memset4((void *)SRAM1_BASE, noise, SRAM1_SIZE_MAX); + memset4((void *)SRAM2_BASE, noise, SRAM2_SIZE - BL_SRAM_SIZE); +} + 80003bc: 4770 bx lr + 80003be: bf00 nop + 80003c0: deadbeef .word 0xdeadbeef + 80003c4: 20018000 .word 0x20018000 + 80003c8: 10006400 .word 0x10006400 + +080003cc : + +// fatal_error(const char *msg) +// + void +fatal_error(const char *msgvoid) +{ + 80003cc: b508 push {r3, lr} + oled_setup(); + 80003ce: f000 fb8f bl 8000af0 + oled_show(screen_fatal); + 80003d2: 4802 ldr r0, [pc, #8] ; (80003dc ) + 80003d4: f000 fc30 bl 8000c38 + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); + 80003d8: bf30 wfi + 80003da: e7fd b.n 80003d8 + 80003dc: 08006c39 .word 0x08006c39 + +080003e0 : + uint8_t *reboot_seed = &reboot_seed_base[0]; // 32 bytes + coldcardFirmwareHeader_t *hdr_copy = (void *)&reboot_seed_base[32]; + uint32_t *boot_flags = (uint32_t *)RAM_BOOT_FLAGS; + + // can only do this once, and might be done already + if(SYSCFG->SWPR != (1<<31)) { + 80003e0: 4b18 ldr r3, [pc, #96] ; (8000444 ) + 80003e2: 6a1b ldr r3, [r3, #32] + 80003e4: f1b3 4f00 cmp.w r3, #2147483648 ; 0x80000000 +// We need to know when we are rebooted, so write some noise +// into SRAM and lock it's value. Not secrets. One page = 1k bytes here. +// + void +reboot_seed_setup(void) +{ + 80003e8: b510 push {r4, lr} + uint8_t *reboot_seed = &reboot_seed_base[0]; // 32 bytes + coldcardFirmwareHeader_t *hdr_copy = (void *)&reboot_seed_base[32]; + uint32_t *boot_flags = (uint32_t *)RAM_BOOT_FLAGS; + + // can only do this once, and might be done already + if(SYSCFG->SWPR != (1<<31)) { + 80003ea: d02a beq.n 8000442 + ASSERT(((uint32_t)reboot_seed) == 0x10007c00); + 80003ec: 4c16 ldr r4, [pc, #88] ; (8000448 ) + 80003ee: 4b17 ldr r3, [pc, #92] ; (800044c ) + 80003f0: 429c cmp r4, r3 + 80003f2: d002 beq.n 80003fa + 80003f4: 4816 ldr r0, [pc, #88] ; (8000450 ) + 80003f6: f7ff ffe9 bl 80003cc + ASSERT(((uint32_t)hdr_copy) == RAM_HEADER_BASE); + + // populate seed w/ noise + memset(reboot_seed, 0x55, 1024); + 80003fa: f44f 6280 mov.w r2, #1024 ; 0x400 + 80003fe: 2155 movs r1, #85 ; 0x55 + 8000400: 4620 mov r0, r4 + 8000402: f006 fa65 bl 80068d0 + rng_buffer(reboot_seed, 32); + 8000406: 2120 movs r1, #32 + 8000408: 4620 mov r0, r4 + 800040a: f001 fd87 bl 8001f1c + + // preserve a copy of the verified FW header + memcpy(hdr_copy, FW_HDR, sizeof(coldcardFirmwareHeader_t)); + 800040e: 2280 movs r2, #128 ; 0x80 + 8000410: 4910 ldr r1, [pc, #64] ; (8000454 ) + 8000412: f104 0020 add.w r0, r4, #32 + 8000416: f006 fa35 bl 8006884 +// 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) { + return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC); + 800041a: 4b0f ldr r3, [pc, #60] ; (8000458 ) + // document how we booted. + uint32_t fl = 0; + if(!flash_is_security_level2()) { + fl |= RBF_FACTORY_MODE; + } + if(sf_completed_upgrade == SF_COMPLETED_UPGRADE) { + 800041c: 4a0f ldr r2, [pc, #60] ; (800045c ) + 800041e: 6a1b ldr r3, [r3, #32] + 8000420: 6811 ldr r1, [r2, #0] + 8000422: 4a0f ldr r2, [pc, #60] ; (8000460 ) + // preserve a copy of the verified FW header + memcpy(hdr_copy, FW_HDR, sizeof(coldcardFirmwareHeader_t)); + + // document how we booted. + uint32_t fl = 0; + if(!flash_is_security_level2()) { + 8000424: b2db uxtb r3, r3 + fl |= RBF_FACTORY_MODE; + 8000426: 2bcc cmp r3, #204 ; 0xcc + 8000428: bf0c ite eq + 800042a: 2300 moveq r3, #0 + 800042c: 2302 movne r3, #2 + } + if(sf_completed_upgrade == SF_COMPLETED_UPGRADE) { + 800042e: 4291 cmp r1, r2 + fl |= RBF_FRESH_VERSION; + } + *boot_flags = fl; + 8000430: 4a0c ldr r2, [pc, #48] ; (8000464 ) + uint32_t fl = 0; + if(!flash_is_security_level2()) { + fl |= RBF_FACTORY_MODE; + } + if(sf_completed_upgrade == SF_COMPLETED_UPGRADE) { + fl |= RBF_FRESH_VERSION; + 8000432: bf08 it eq + 8000434: f043 0301 orreq.w r3, r3, #1 + } + *boot_flags = fl; + 8000438: 6013 str r3, [r2, #0] + + // lock it (top most page = 1k bytes) + SYSCFG->SWPR = (1<<31); + 800043a: 4b02 ldr r3, [pc, #8] ; (8000444 ) + 800043c: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + 8000440: 621a str r2, [r3, #32] + 8000442: bd10 pop {r4, pc} + 8000444: 40010000 .word 0x40010000 + 8000448: 10007c00 .word 0x10007c00 + 800044c: 10007c00 .word 0x10007c00 + 8000450: 08006940 .word 0x08006940 + 8000454: 0800bf80 .word 0x0800bf80 + 8000458: 40022000 .word 0x40022000 + 800045c: 1000634c .word 0x1000634c + 8000460: b50d5c24 .word 0xb50d5c24 + 8000464: 10007ca0 .word 0x10007ca0 + +08000468 : + +// enter_dfu() +// + void __attribute__((noreturn)) +enter_dfu(void) +{ + 8000468: b507 push {r0, r1, r2, lr} + const uint32_t noise = 0xDeadBeef; + + // clear the green light, if set + ae_setup(); + 800046a: f001 fe9b bl 80021a4 + ae_set_gpio(0); + 800046e: 2000 movs r0, #0 + 8000470: f002 fbbd bl 8002bee + + // Reset huge parts of the chip + __HAL_RCC_APB1_FORCE_RESET(); + 8000474: 4b1e ldr r3, [pc, #120] ; (80004f0 ) +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + *dest = value; + 8000476: 481f ldr r0, [pc, #124] ; (80004f4 ) + ae_setup(); + ae_set_gpio(0); + + // Reset huge parts of the chip + __HAL_RCC_APB1_FORCE_RESET(); + __HAL_RCC_APB1_RELEASE_RESET(); + 8000478: 2200 movs r2, #0 + // clear the green light, if set + ae_setup(); + ae_set_gpio(0); + + // Reset huge parts of the chip + __HAL_RCC_APB1_FORCE_RESET(); + 800047a: f04f 31ff mov.w r1, #4294967295 ; 0xffffffff + 800047e: 6399 str r1, [r3, #56] ; 0x38 + __HAL_RCC_APB1_RELEASE_RESET(); + 8000480: 639a str r2, [r3, #56] ; 0x38 + + __HAL_RCC_APB2_FORCE_RESET(); + 8000482: 6419 str r1, [r3, #64] ; 0x40 + __HAL_RCC_APB2_RELEASE_RESET(); + 8000484: 641a str r2, [r3, #64] ; 0x40 + + __HAL_RCC_AHB1_FORCE_RESET(); + 8000486: 6299 str r1, [r3, #40] ; 0x28 + __HAL_RCC_AHB1_RELEASE_RESET(); + 8000488: 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(); + 800048a: 6319 str r1, [r3, #48] ; 0x30 + __HAL_RCC_AHB3_RELEASE_RESET(); + 800048c: 631a str r2, [r3, #48] ; 0x30 + + __HAL_FIREWALL_PREARM_ENABLE(); + 800048e: f5a3 4374 sub.w r3, r3, #62464 ; 0xf400 + 8000492: 6a1a ldr r2, [r3, #32] + 8000494: f042 0201 orr.w r2, r2, #1 + 8000498: 621a str r2, [r3, #32] + 800049a: 6a1b ldr r3, [r3, #32] +// memset4() +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + 800049c: 4a16 ldr r2, [pc, #88] ; (80004f8 ) +#endif + + __HAL_RCC_AHB3_FORCE_RESET(); + __HAL_RCC_AHB3_RELEASE_RESET(); + + __HAL_FIREWALL_PREARM_ENABLE(); + 800049e: f003 0301 and.w r3, r3, #1 + 80004a2: 9301 str r3, [sp, #4] + 80004a4: 9b01 ldr r3, [sp, #4] + 80004a6: f04f 5300 mov.w r3, #536870912 ; 0x20000000 +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + *dest = value; + 80004aa: f843 0b04 str.w r0, [r3], #4 +// memset4() +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + 80004ae: 4293 cmp r3, r2 + 80004b0: 4910 ldr r1, [pc, #64] ; (80004f4 ) + 80004b2: d1fa bne.n 80004aa + 80004b4: 4a11 ldr r2, [pc, #68] ; (80004fc ) + 80004b6: f04f 5380 mov.w r3, #268435456 ; 0x10000000 + *dest = value; + 80004ba: f843 1b04 str.w r1, [r3], #4 +// memset4() +// + static inline void +memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) +{ + for(; byte_len; byte_len-=4, dest++) { + 80004be: 4293 cmp r3, r2 + 80004c0: d1fb bne.n 80004ba + 80004c2: 4b0f ldr r3, [pc, #60] ; (8000500 ) + 80004c4: 6a1b ldr r3, [r3, #32] + // there is some way to trick us into DFU + // after sensitive content in place. + memset4((void *)SRAM1_BASE, noise, SRAM1_SIZE_MAX); + memset4((void *)SRAM2_BASE, noise, SRAM2_SIZE - 1024); // avoid seed area + + if(flash_is_security_level2()) { + 80004c6: b2db uxtb r3, r3 + 80004c8: 2bcc cmp r3, #204 ; 0xcc + 80004ca: d101 bne.n 80004d0 + 80004cc: bf30 wfi + 80004ce: e7fd b.n 80004cc + // cannot do DFU in RDP=2, so just die. Helps to preserve screen + LOCKUP_FOREVER(); + } + + // Reset clocks. + HAL_RCC_DeInit(); + 80004d0: f003 fc96 bl 8003e00 + + // move system ROM into 0x0 + __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); + 80004d4: 4a0b ldr r2, [pc, #44] ; (8000504 ) + 80004d6: 6813 ldr r3, [r2, #0] + 80004d8: f023 0307 bic.w r3, r3, #7 + 80004dc: f043 0301 orr.w r3, r3, #1 + 80004e0: 6013 str r3, [r2, #0] + + // simulate a reset vector + __ASM volatile ("movs r0, #0\n" + 80004e2: 2000 movs r0, #0 + 80004e4: 6803 ldr r3, [r0, #0] + 80004e6: f383 8808 msr MSP, r3 + 80004ea: 6843 ldr r3, [r0, #4] + 80004ec: 4798 blx r3 + 80004ee: bf00 nop + 80004f0: 40021000 .word 0x40021000 + 80004f4: deadbeef .word 0xdeadbeef + 80004f8: 20018000 .word 0x20018000 + 80004fc: 10007c00 .word 0x10007c00 + 8000500: 40022000 .word 0x40022000 + 8000504: 40010000 .word 0x40010000 + +08000508 : + +// dfu_by_request() +// + void +dfu_by_request(void) +{ + 8000508: b508 push {r3, lr} + 800050a: 4b05 ldr r3, [pc, #20] ; (8000520 ) + 800050c: 6a1b ldr r3, [r3, #32] + if(flash_is_security_level2()) { + 800050e: b2db uxtb r3, r3 + 8000510: 2bcc cmp r3, #204 ; 0xcc + 8000512: d004 beq.n 800051e + // cannot get into DFU when secure + // so do nothing + return; + } + + oled_show(screen_dfu); + 8000514: 4803 ldr r0, [pc, #12] ; (8000524 ) + 8000516: f000 fb8f bl 8000c38 + enter_dfu(); + 800051a: f7ff ffa5 bl 8000468 + 800051e: bd08 pop {r3, pc} + 8000520: 40022000 .word 0x40022000 + 8000524: 08006ca3 .word 0x08006ca3 + +08000528 : +// +// Called only on system boot. +// + void +system_startup(void) +{ + 8000528: b510 push {r4, lr} + // configure clocks first + clocks_setup(); + 800052a: f001 f9e9 bl 8001900 + +#if RELEASE + // security check: should we be in protected mode? Was there some UV-C bitrot perhaps? + if(!check_all_ones(rom_secrets->bag_number, sizeof(rom_secrets->bag_number)) + 800052e: 2120 movs r1, #32 + 8000530: 4821 ldr r0, [pc, #132] ; (80005b8 ) + 8000532: f001 fc8b bl 8001e4c + 8000536: b938 cbnz r0, 8000548 + 8000538: 4b20 ldr r3, [pc, #128] ; (80005bc ) + 800053a: 6a1b ldr r3, [r3, #32] + && !flash_is_security_level2() + 800053c: b2db uxtb r3, r3 + 800053e: 2bcc cmp r3, #204 ; 0xcc + 8000540: d002 beq.n 8000548 + ) { + // yikes. recovery: do lockdown... we should be/(thought we were) locked already + flash_lockdown_hard(OB_RDP_LEVEL_2); + 8000542: 20cc movs r0, #204 ; 0xcc + 8000544: f001 fc0c bl 8001d60 + } +#endif + + // workaround to get into DFU from micropython + // LATER: none of this is useful with RDP=2 + if(memcmp(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic)) == 0) { + 8000548: 4c1d ldr r4, [pc, #116] ; (80005c0 ) + 800054a: 491e ldr r1, [pc, #120] ; (80005c4 ) + 800054c: 2208 movs r2, #8 + 800054e: 4620 mov r0, r4 + 8000550: f006 f989 bl 8006866 + 8000554: b938 cbnz r0, 8000566 + dfu_flag->magic[0] = 0; + 8000556: 7020 strb r0, [r4, #0] + + // still see a flash here, but that's proof it works. + oled_setup(); + 8000558: f000 faca bl 8000af0 + oled_show(dfu_flag->screen); + 800055c: 68a0 ldr r0, [r4, #8] + 800055e: f000 fb6b bl 8000c38 + + enter_dfu(); + 8000562: f7ff ff81 bl 8000468 + // NOT-REACHED + } + + // clear and setup OLED display + oled_setup(); + 8000566: f000 fac3 bl 8000af0 + oled_show_progress(screen_verify, 0); + 800056a: 2100 movs r1, #0 + 800056c: 4816 ldr r0, [pc, #88] ; (80005c8 ) + 800056e: f000 fba3 bl 8000cb8 + + // won't always need it, but enable RNG anyway + rng_setup(); + 8000572: f001 fca7 bl 8001ec4 + + // wipe all of SRAM (except our own memory, which was already wiped) + wipe_all_sram(); + 8000576: f7ff ff11 bl 800039c + + // config pins + gpio_setup(); + 800057a: f002 fcfd bl 8002f78 + ae_setup(); + 800057e: f001 fe11 bl 80021a4 + ae_set_gpio(0); // not checking return on purpose + 8000582: 2000 movs r0, #0 + 8000584: f002 fb33 bl 8002bee + + // protect our flash, and/or check it's protected + // - and pick pairing secret if we don't already have one + // - may also do one-time setup of 508a + // - note: ae_setup must already be called, since it can talk to that + flash_setup(); + 8000588: f001 fb76 bl 8001c78 + + // escape into DFU + if(dfu_button_pressed()) dfu_by_request(); + 800058c: f002 fd28 bl 8002fe0 + 8000590: b108 cbz r0, 8000596 + 8000592: f7ff ffb9 bl 8000508 + + // maybe upgrade to a firmware image found in sflash + sf_firmware_upgrade(); + 8000596: f003 fb69 bl 8003c6c + + // SLOW part: check firmware is legit; else enter DFU + // - may die due to downgrade attack or unsigned/badly signed image + verify_firmware(); + 800059a: f001 f975 bl 8001888 + + // .. for slow people, check again; last chance + if(dfu_button_pressed()) dfu_by_request(); + 800059e: f002 fd1f bl 8002fe0 + 80005a2: b108 cbz r0, 80005a8 + 80005a4: f7ff ffb0 bl 8000508 + + // track reboots, capture firmware hdr used + // - must be near end of boot process, ie: here. + reboot_seed_setup(); + 80005a8: f7ff ff1a bl 80003e0 + + // load a blank-ish screen, so that + // if the firmware crashes, we are showing + // something reasonable + oled_show(screen_blank); + 80005ac: 4807 ldr r0, [pc, #28] ; (80005cc ) +} + 80005ae: e8bd 4010 ldmia.w sp!, {r4, lr} + reboot_seed_setup(); + + // load a blank-ish screen, so that + // if the firmware crashes, we are showing + // something reasonable + oled_show(screen_blank); + 80005b2: f000 bb41 b.w 8000c38 + 80005b6: bf00 nop + 80005b8: 08007850 .word 0x08007850 + 80005bc: 40022000 .word 0x40022000 + 80005c0: 20008000 .word 0x20008000 + 80005c4: 08006947 .word 0x08006947 + 80005c8: 08006ab6 .word 0x08006ab6 + 80005cc: 08006a89 .word 0x08006a89 + +080005d0 : +// + __attribute__ ((used)) + int +firewall_dispatch(int method_num, uint8_t *buf_io, int len_in, + uint32_t arg2, uint32_t incoming_lr) +{ + 80005d0: b570 push {r4, r5, r6, lr} + 80005d2: b0a8 sub sp, #160 ; 0xa0 + 80005d4: 4616 mov r6, r2 + 80005d6: 9301 str r3, [sp, #4] + __disable_irq(); +#endif + + // "1=any code executed outside the protected segment will close the Firewall" + // "0=.. will reset the processor" + __HAL_FIREWALL_PREARM_DISABLE(); + 80005d8: 4bb4 ldr r3, [pc, #720] ; (80008ac ) + 80005da: 6a1a ldr r2, [r3, #32] + 80005dc: f022 0201 bic.w r2, r2, #1 +// + __attribute__ ((used)) + int +firewall_dispatch(int method_num, uint8_t *buf_io, int len_in, + uint32_t arg2, uint32_t incoming_lr) +{ + 80005e0: 460d mov r5, r1 + 80005e2: 992c ldr r1, [sp, #176] ; 0xb0 + __disable_irq(); +#endif + + // "1=any code executed outside the protected segment will close the Firewall" + // "0=.. will reset the processor" + __HAL_FIREWALL_PREARM_DISABLE(); + 80005e4: 621a str r2, [r3, #32] + 80005e6: 6a1b ldr r3, [r3, #32] + 80005e8: f003 0301 and.w r3, r3, #1 + 80005ec: 9303 str r3, [sp, #12] + // 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 > 255) { + 80005ee: 2eff cmp r6, #255 ; 0xff + __disable_irq(); +#endif + + // "1=any code executed outside the protected segment will close the Firewall" + // "0=.. will reset the processor" + __HAL_FIREWALL_PREARM_DISABLE(); + 80005f0: 9b03 ldr r3, [sp, #12] + // 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 > 255) { + 80005f2: f300 81e2 bgt.w 80009ba + + // 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) { + 80005f6: 3001 adds r0, #1 + 80005f8: 2816 cmp r0, #22 + 80005fa: f200 81e2 bhi.w 80009c2 + 80005fe: e8df f010 tbh [pc, r0, lsl #1] + 8000602: 01d3 .short 0x01d3 + 8000604: 002f0017 .word 0x002f0017 + 8000608: 0076004e .word 0x0076004e + 800060c: 00a90089 .word 0x00a90089 + 8000610: 01e001e0 .word 0x01e001e0 + 8000614: 01e001e0 .word 0x01e001e0 + 8000618: 01e001e0 .word 0x01e001e0 + 800061c: 01e000b1 .word 0x01e000b1 + 8000620: 00c001e0 .word 0x00c001e0 + 8000624: 00f200de .word 0x00f200de + 8000628: 01310106 .word 0x01310106 + 800062c: 01920180 .word 0x01920180 + case 0: { + REQUIRE_OUT(64); + 8000630: 2300 movs r3, #0 + 8000632: 4632 mov r2, r6 + 8000634: 2140 movs r1, #64 ; 0x40 + 8000636: 4628 mov r0, r5 + 8000638: f7ff fe94 bl 8000364 + 800063c: 4604 mov r4, r0 + 800063e: 2800 cmp r0, #0 + 8000640: f040 81c4 bne.w 80009cc + + // Return my version string + memset(buf_io, 0, len_in); + 8000644: 4632 mov r2, r6 + 8000646: 4601 mov r1, r0 + 8000648: 4628 mov r0, r5 + 800064a: f006 f941 bl 80068d0 + strlcpy((char *)buf_io, version_string, len_in); + 800064e: 4632 mov r2, r6 + 8000650: 4997 ldr r1, [pc, #604] ; (80008b0 ) + 8000652: 4628 mov r0, r5 + 8000654: f006 f944 bl 80068e0 + + rv = strlen(version_string); + 8000658: 4895 ldr r0, [pc, #596] ; (80008b0 ) + 800065a: f006 f956 bl 800690a + 800065e: e180 b.n 8000962 + } + + case 1: { + // Perform SHA256 over ourselves, with 32-bits of salt, to imply we + // haven't stored valid responses. + REQUIRE_OUT(32); + 8000660: 2300 movs r3, #0 + 8000662: 4632 mov r2, r6 + 8000664: 2120 movs r1, #32 + 8000666: 4628 mov r0, r5 + 8000668: f7ff fe7c bl 8000364 + 800066c: 4604 mov r4, r0 + 800066e: 2800 cmp r0, #0 + 8000670: f040 81ac bne.w 80009cc + + SHA256_CTX ctx; + sha256_init(&ctx); + 8000674: a80c add r0, sp, #48 ; 0x30 + 8000676: f004 fe89 bl 800538c + sha256_update(&ctx, (void *)&arg2, 4); + 800067a: 2204 movs r2, #4 + 800067c: eb0d 0102 add.w r1, sp, r2 + 8000680: a80c add r0, sp, #48 ; 0x30 + 8000682: f004 fead bl 80053e0 + sha256_update(&ctx, (void *)BL_FLASH_BASE, BL_FLASH_SIZE); + 8000686: a80c add r0, sp, #48 ; 0x30 + 8000688: f44f 42f0 mov.w r2, #30720 ; 0x7800 + 800068c: f04f 6100 mov.w r1, #134217728 ; 0x8000000 + 8000690: f004 fea6 bl 80053e0 + sha256_final(&ctx, buf_io); + 8000694: 4629 mov r1, r5 + 8000696: a80c add r0, sp, #48 ; 0x30 + 8000698: f004 fec0 bl 800541c + 800069c: e196 b.n 80009cc + 800069e: 4b85 ldr r3, [pc, #532] ; (80008b4 ) + 80006a0: 6a1d ldr r5, [r3, #32] + bool secure = flash_is_security_level2(); + + // Go into DFU mode. It's a one-way trip. + // Also used to show some "fatal" screens w/ memory wipe. + + switch(arg2) { + 80006a2: 9b01 ldr r3, [sp, #4] + 80006a4: 2b02 cmp r3, #2 + 80006a6: b2ed uxtb r5, r5 + 80006a8: d004 beq.n 80006b4 + 80006aa: 2b03 cmp r3, #3 + 80006ac: d009 beq.n 80006c2 + 80006ae: 2b01 cmp r3, #1 + 80006b0: d102 bne.n 80006b8 + 80006b2: e008 b.n 80006c6 + case 1: + // in case some way for Micropython to detect it. + scr = screen_downgrade; + break; + case 2: + scr = screen_blank; + 80006b4: 4c80 ldr r4, [pc, #512] ; (80008b8 ) + 80006b6: e007 b.n 80006c8 + + switch(arg2) { + default: + case 0: + // enter DFU for firmware upgrades + if(secure) { + 80006b8: 2dcc cmp r5, #204 ; 0xcc + 80006ba: f000 8186 beq.w 80009ca + // we cannot support DFU in secure mode anymore + rv = EPERM; + goto fail; + } + scr = screen_dfu; + 80006be: 4c7f ldr r4, [pc, #508] ; (80008bc ) + 80006c0: e002 b.n 80006c8 + break; + case 2: + scr = screen_blank; + break; + case 3: + scr = screen_brick; + 80006c2: 4c7f ldr r4, [pc, #508] ; (80008c0 ) + break; + 80006c4: e000 b.n 80006c8 + } + scr = screen_dfu; + break; + case 1: + // in case some way for Micropython to detect it. + scr = screen_downgrade; + 80006c6: 4c7f ldr r4, [pc, #508] ; (80008c4 ) + case 3: + scr = screen_brick; + break; + } + + oled_setup(); + 80006c8: f000 fa12 bl 8000af0 + oled_show(scr); + 80006cc: 4620 mov r0, r4 + 80006ce: f000 fab3 bl 8000c38 + + wipe_all_sram(); + 80006d2: f7ff fe63 bl 800039c + + if(secure) { + 80006d6: 2dcc cmp r5, #204 ; 0xcc + 80006d8: d101 bne.n 80006de + 80006da: bf30 wfi + 80006dc: e7fd b.n 80006da + } else { + // Cannot just call enter_dfu() because it doesn't work well + // once Micropython has configured so much stuff in the chip. + + // Leave a reminder to ourselves + memcpy(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic)); + 80006de: 497a ldr r1, [pc, #488] ; (80008c8 ) + 80006e0: 4a7a ldr r2, [pc, #488] ; (80008cc ) + 80006e2: 6808 ldr r0, [r1, #0] + 80006e4: 6849 ldr r1, [r1, #4] + 80006e6: 4613 mov r3, r2 + 80006e8: c303 stmia r3!, {r0, r1} + dfu_flag->screen = scr; + 80006ea: 6094 str r4, [r2, #8] + 80006ec: e00e b.n 800070c + break; + } + + case 3: + // logout: wipe all of memory and lock up. Must powercycle to recover. + switch(arg2) { + 80006ee: 9b01 ldr r3, [sp, #4] + 80006f0: b10b cbz r3, 80006f6 + 80006f2: 2b02 cmp r3, #2 + 80006f4: d102 bne.n 80006fc + case 0: + case 2: + oled_show(screen_logout); + 80006f6: 4876 ldr r0, [pc, #472] ; (80008d0 ) + 80006f8: f000 fa9e bl 8000c38 + case 1: + // leave screen untouched + break; + } + + wipe_all_sram(); + 80006fc: f7ff fe4e bl 800039c + + if(arg2 == 2) { + 8000700: 9b01 ldr r3, [sp, #4] + 8000702: 2b02 cmp r3, #2 + 8000704: d104 bne.n 8000710 + // need some time to show OLED contents + delay_ms(100); + 8000706: 2064 movs r0, #100 ; 0x64 + 8000708: f002 fc0a bl 8002f20 + + // reboot so we can "login" again + NVIC_SystemReset(); + 800070c: f7ff fe18 bl 8000340 + 8000710: bf30 wfi + 8000712: e7fd b.n 8000710 + LOCKUP_FOREVER() + break; + + case 4: + // attempt to control the GPIO (won't work for 1) + ae_setup(); + 8000714: f001 fd46 bl 80021a4 + ae_keep_alive(); + 8000718: f001 fd80 bl 800221c + switch(arg2) { + 800071c: 9b01 ldr r3, [sp, #4] + 800071e: 2b02 cmp r3, #2 + 8000720: d008 beq.n 8000734 + 8000722: 2b03 cmp r3, #3 + 8000724: d00a beq.n 800073c + 8000726: 2b01 cmp r3, #1 + 8000728: d002 beq.n 8000730 + default: + case 0: // read state + rv = ae_get_gpio(); + 800072a: f002 fa88 bl 8002c3e + 800072e: e118 b.n 8000962 + break; + case 1: // clear it (can work anytime) + rv = ae_set_gpio(0); + 8000730: 2000 movs r0, #0 + 8000732: e000 b.n 8000736 + break; + case 2: // set it (will always fail) + rv = ae_set_gpio(1); + 8000734: 2001 movs r0, #1 + 8000736: f002 fa5a bl 8002bee + 800073a: e112 b.n 8000962 + + case 3: { // do a verify and see if it maybe goes green + uint8_t fw_digest[32], world_digest[32]; + + // takes time, shows progress bar + checksum_flash(fw_digest, world_digest); + 800073c: a90c add r1, sp, #48 ; 0x30 + 800073e: a804 add r0, sp, #16 + 8000740: f000 ff9e bl 8001680 + + rv = ae_set_gpio_secure(world_digest); + 8000744: a80c add r0, sp, #48 ; 0x30 + 8000746: f002 fa6d bl 8002c24 + 800074a: 4604 mov r4, r0 + + oled_show(screen_blank); + 800074c: 485a ldr r0, [pc, #360] ; (80008b8 ) + 800074e: f000 fa73 bl 8000c38 + 8000752: e13b b.n 80009cc + case 5: + // Are we a brick? + // if the pairing secret doesn't work anymore, that + // means we've been bricked. + // TODO: also report hardware issue, and non-configured states + ae_setup(); + 8000754: f001 fd26 bl 80021a4 + rv = (ae_pair_unlock() != 0); + 8000758: f001 ff7e bl 8002658 + 800075c: 1c04 adds r4, r0, #0 + 800075e: bf18 it ne + 8000760: 2401 movne r4, #1 + break; + 8000762: e133 b.n 80009cc + + case 12: + // read the DFU button (used for selftest at least) + REQUIRE_OUT(1); + 8000764: 2300 movs r3, #0 + 8000766: 4632 mov r2, r6 + 8000768: 2101 movs r1, #1 + 800076a: 4628 mov r0, r5 + 800076c: f7ff fdfa bl 8000364 + 8000770: 4604 mov r4, r0 + 8000772: 2800 cmp r0, #0 + 8000774: f040 812a bne.w 80009cc + gpio_setup(); + 8000778: f002 fbfe bl 8002f78 + buf_io[0] = dfu_button_pressed(); + 800077c: f002 fc30 bl 8002fe0 + 8000780: e0cf b.n 8000922 + break; + + case 15: { + // Read a dataslot directly. Will fail on + // encrypted slots. + if(len_in != 4 && len_in != 32 && len_in != 72) { + 8000782: 2e04 cmp r6, #4 + 8000784: d004 beq.n 8000790 + 8000786: 2e20 cmp r6, #32 + 8000788: d002 beq.n 8000790 + 800078a: 2e48 cmp r6, #72 ; 0x48 + 800078c: f040 8115 bne.w 80009ba + rv = ERANGE; + } else { + REQUIRE_OUT(4); + 8000790: 2300 movs r3, #0 + 8000792: 4632 mov r2, r6 + 8000794: 2104 movs r1, #4 + 8000796: 4628 mov r0, r5 + 8000798: f7ff fde4 bl 8000364 + 800079c: 4604 mov r4, r0 + 800079e: 2800 cmp r0, #0 + 80007a0: f040 8114 bne.w 80009cc + + ae_setup(); + 80007a4: f001 fcfe bl 80021a4 + if(ae_read_data_slot(arg2 & 0xf, buf_io, len_in)) { + 80007a8: 9801 ldr r0, [sp, #4] + 80007aa: 4632 mov r2, r6 + 80007ac: 4629 mov r1, r5 + 80007ae: f000 000f and.w r0, r0, #15 + 80007b2: f002 f98b bl 8002acc + 80007b6: 2800 cmp r0, #0 + 80007b8: f040 8101 bne.w 80009be + 80007bc: e09f b.n 80008fe + break; + } + + case 16: { + // Provide the 2 words for anti-phishing. + REQUIRE_OUT(MAX_PIN_LEN); + 80007be: 2300 movs r3, #0 + 80007c0: 4632 mov r2, r6 + 80007c2: 2120 movs r1, #32 + 80007c4: 4628 mov r0, r5 + 80007c6: f7ff fdcd bl 8000364 + 80007ca: 4604 mov r4, r0 + 80007cc: 2800 cmp r0, #0 + 80007ce: f040 80fd bne.w 80009cc + + // arg2: length of pin. + if((arg2 < 1) || (arg2 > MAX_PIN_LEN)) { + 80007d2: 9901 ldr r1, [sp, #4] + 80007d4: 1e4b subs r3, r1, #1 + 80007d6: 2b1f cmp r3, #31 + 80007d8: f200 80ef bhi.w 80009ba + rv = ERANGE; + } else { + if(pin_prefix_words((char *)buf_io, arg2, (uint32_t *)buf_io)) { + 80007dc: 462a mov r2, r5 + 80007de: 4628 mov r0, r5 + 80007e0: f002 fd46 bl 8003270 + 80007e4: e7e7 b.n 80007b6 + break; + } + + case 17: + // test rng + REQUIRE_OUT(32); + 80007e6: 2300 movs r3, #0 + 80007e8: 4632 mov r2, r6 + 80007ea: 2120 movs r1, #32 + 80007ec: 4628 mov r0, r5 + 80007ee: f7ff fdb9 bl 8000364 + 80007f2: 4604 mov r4, r0 + 80007f4: 2800 cmp r0, #0 + 80007f6: f040 80e9 bne.w 80009cc + memset(buf_io, 0x55, 32); // to help show errors + 80007fa: 2220 movs r2, #32 + 80007fc: 2155 movs r1, #85 ; 0x55 + 80007fe: 4628 mov r0, r5 + 8000800: f006 f866 bl 80068d0 + rng_buffer(buf_io, 32); + 8000804: 2120 movs r1, #32 + 8000806: 4628 mov r0, r5 + 8000808: f001 fb88 bl 8001f1c + break; + 800080c: e0de b.n 80009cc + + case 18: { + // Try login w/ PIN. + REQUIRE_OUT(sizeof(pinAttempt_t)); + 800080e: 2300 movs r3, #0 + 8000810: 4632 mov r2, r6 + 8000812: 21f8 movs r1, #248 ; 0xf8 + 8000814: 4628 mov r0, r5 + 8000816: f7ff fda5 bl 8000364 + 800081a: 4604 mov r4, r0 + 800081c: 2800 cmp r0, #0 + 800081e: f040 80d5 bne.w 80009cc + pinAttempt_t *args = (pinAttempt_t *)buf_io; + + switch(arg2) { + 8000822: 9b01 ldr r3, [sp, #4] + 8000824: 2b05 cmp r3, #5 + 8000826: f200 80cc bhi.w 80009c2 + 800082a: e8df f003 tbb [pc, r3] + 800082e: 0703 .short 0x0703 + 8000830: 17130f0b .word 0x17130f0b + case 0: + rv = pin_setup_attempt(args); + 8000834: 4628 mov r0, r5 + 8000836: f002 fd5d bl 80032f4 + 800083a: e092 b.n 8000962 + break; + case 1: + rv = pin_delay(args); + 800083c: 4628 mov r0, r5 + 800083e: f002 fddd bl 80033fc + 8000842: e08e b.n 8000962 + break; + case 2: + rv = pin_login_attempt(args); + 8000844: 4628 mov r0, r5 + 8000846: f002 fdef bl 8003428 + 800084a: e08a b.n 8000962 + break; + case 3: + rv = pin_change(args); + 800084c: 4628 mov r0, r5 + 800084e: f002 febd bl 80035cc + 8000852: e086 b.n 8000962 + break; + case 4: + rv = pin_fetch_secret(args); + 8000854: 4628 mov r0, r5 + 8000856: f002 ffc3 bl 80037e0 + 800085a: e082 b.n 8000962 + break; + + case 5: + rv = pin_firmware_greenlight(args); + 800085c: 4628 mov r0, r5 + 800085e: f003 f845 bl 80038ec + 8000862: e07e b.n 8000962 + break; + } + + + case 19: { // bag number stuff + switch(arg2) { + 8000864: 9b01 ldr r3, [sp, #4] + 8000866: 2b64 cmp r3, #100 ; 0x64 + 8000868: d044 beq.n 80008f4 + 800086a: d803 bhi.n 8000874 + 800086c: b14b cbz r3, 8000882 + 800086e: 2b01 cmp r3, #1 + 8000870: d034 beq.n 80008dc + 8000872: e0a6 b.n 80009c2 + 8000874: 2b65 cmp r3, #101 ; 0x65 + 8000876: d03f beq.n 80008f8 + 8000878: 2b66 cmp r3, #102 ; 0x66 + 800087a: f040 80a2 bne.w 80009c2 + case 101: + flash_lockdown_hard(OB_RDP_LEVEL_1); // Can only do 0->1 (experiments) + break; + case 102: + // production units will be: + flash_lockdown_hard(OB_RDP_LEVEL_2); // No change possible after this. + 800087e: 20cc movs r0, #204 ; 0xcc + 8000880: e03b b.n 80008fa + + case 19: { // bag number stuff + switch(arg2) { + case 0: + // read out number + REQUIRE_OUT(32); + 8000882: 4632 mov r2, r6 + 8000884: 2120 movs r1, #32 + 8000886: 4628 mov r0, r5 + 8000888: f7ff fd6c bl 8000364 + 800088c: 4604 mov r4, r0 + 800088e: 2800 cmp r0, #0 + 8000890: f040 809c bne.w 80009cc + memcpy(buf_io, rom_secrets->bag_number, 32); + 8000894: 4a0f ldr r2, [pc, #60] ; (80008d4 ) + 8000896: 4e10 ldr r6, [pc, #64] ; (80008d8 ) + 8000898: 4613 mov r3, r2 + 800089a: cb03 ldmia r3!, {r0, r1} + 800089c: 42b3 cmp r3, r6 + 800089e: 6028 str r0, [r5, #0] + 80008a0: 6069 str r1, [r5, #4] + 80008a2: 461a mov r2, r3 + 80008a4: f105 0508 add.w r5, r5, #8 + 80008a8: d1f6 bne.n 8000898 + 80008aa: e08f b.n 80009cc + 80008ac: 40011c00 .word 0x40011c00 + 80008b0: 08007370 .word 0x08007370 + 80008b4: 40022000 .word 0x40022000 + 80008b8: 08006a89 .word 0x08006a89 + 80008bc: 08006ca3 .word 0x08006ca3 + 80008c0: 08006d3b .word 0x08006d3b + 80008c4: 08006ef9 .word 0x08006ef9 + 80008c8: 08006947 .word 0x08006947 + 80008cc: 20008000 .word 0x20008000 + 80008d0: 080069cb .word 0x080069cb + 80008d4: 08007850 .word 0x08007850 + 80008d8: 08007870 .word 0x08007870 + break; + + case 1: + // set the bag number, and (should) do lock down + REQUIRE_IN_ONLY(32); + 80008dc: 4632 mov r2, r6 + 80008de: 2120 movs r1, #32 + 80008e0: 4628 mov r0, r5 + 80008e2: f7ff fd3f bl 8000364 + 80008e6: 4604 mov r4, r0 + 80008e8: 2800 cmp r0, #0 + 80008ea: d16f bne.n 80009cc + + flash_save_bag_number(buf_io); + 80008ec: 4628 mov r0, r5 + 80008ee: f001 f9a3 bl 8001c38 + break; + 80008f2: e06b b.n 80009cc + + case 100: + flash_lockdown_hard(OB_RDP_LEVEL_0); // wipes contents of flash (1->0) + 80008f4: 20aa movs r0, #170 ; 0xaa + 80008f6: e000 b.n 80008fa + break; + case 101: + flash_lockdown_hard(OB_RDP_LEVEL_1); // Can only do 0->1 (experiments) + 80008f8: 20bb movs r0, #187 ; 0xbb + break; + case 102: + // production units will be: + flash_lockdown_hard(OB_RDP_LEVEL_2); // No change possible after this. + 80008fa: f001 fa31 bl 8001d60 +{ + + // from linker, offset of firewall entry + extern uint32_t firewall_starts; + + int rv = 0; + 80008fe: 2400 movs r4, #0 + flash_lockdown_hard(OB_RDP_LEVEL_1); // Can only do 0->1 (experiments) + break; + case 102: + // production units will be: + flash_lockdown_hard(OB_RDP_LEVEL_2); // No change possible after this. + break; + 8000900: e064 b.n 80009cc + } + + + case 20: + // Read a single byte of config dataspace + REQUIRE_OUT(1); + 8000902: 2300 movs r3, #0 + 8000904: 4632 mov r2, r6 + 8000906: 2101 movs r1, #1 + 8000908: 4628 mov r0, r5 + 800090a: f7ff fd2b bl 8000364 + 800090e: 4604 mov r4, r0 + 8000910: 2800 cmp r0, #0 + 8000912: d15b bne.n 80009cc + + rv = ae_read_config_byte(arg2 & 0x7f); + 8000914: 9801 ldr r0, [sp, #4] + 8000916: f000 007f and.w r0, r0, #127 ; 0x7f + 800091a: f002 f9bb bl 8002c94 + if(rv == -1) { + 800091e: 1c43 adds r3, r0, #1 + 8000920: d04d beq.n 80009be + rv = EIO; + } else { + buf_io[0] = rv; + 8000922: 7028 strb r0, [r5, #0] + 8000924: e052 b.n 80009cc + } + break; + + case 21: + // read OTP / downgrade protection + switch(arg2) { + 8000926: 9b01 ldr r3, [sp, #4] + 8000928: 2b01 cmp r3, #1 + 800092a: d010 beq.n 800094e + 800092c: d302 bcc.n 8000934 + 800092e: 2b02 cmp r3, #2 + 8000930: d019 beq.n 8000966 + 8000932: e046 b.n 80009c2 + case 0: + REQUIRE_OUT(8); + 8000934: 2300 movs r3, #0 + 8000936: 4632 mov r2, r6 + 8000938: 2108 movs r1, #8 + 800093a: 4628 mov r0, r5 + 800093c: f7ff fd12 bl 8000364 + 8000940: 4604 mov r4, r0 + 8000942: 2800 cmp r0, #0 + 8000944: d142 bne.n 80009cc + get_min_version(buf_io); + 8000946: 4628 mov r0, r5 + 8000948: f000 ff2e bl 80017a8 + break; + 800094c: e03e b.n 80009cc + + case 1: + REQUIRE_IN_ONLY(8); + 800094e: 4632 mov r2, r6 + 8000950: 2108 movs r1, #8 + 8000952: 4628 mov r0, r5 + 8000954: f7ff fd06 bl 8000364 + 8000958: 4604 mov r4, r0 + 800095a: bbb8 cbnz r0, 80009cc + rv = check_is_downgrade(buf_io); + 800095c: 4628 mov r0, r5 + 800095e: f000 ff41 bl 80017e4 + 8000962: 4604 mov r4, r0 + break; + 8000964: e032 b.n 80009cc + + case 2: + REQUIRE_IN_ONLY(8); + 8000966: 2301 movs r3, #1 + 8000968: 4632 mov r2, r6 + 800096a: 2108 movs r1, #8 + 800096c: 4628 mov r0, r5 + 800096e: f7ff fcf9 bl 8000364 + 8000972: 4604 mov r4, r0 + 8000974: bb50 cbnz r0, 80009cc + + if(buf_io[0] < 0x10 || buf_io[0] >= 0x40) { + 8000976: 782b ldrb r3, [r5, #0] + 8000978: 3b10 subs r3, #16 + // bad data + rv = ERANGE; + 800097a: 2b2f cmp r3, #47 ; 0x2f + } if(check_is_downgrade(buf_io)) { + 800097c: 4628 mov r0, r5 + case 2: + REQUIRE_IN_ONLY(8); + + if(buf_io[0] < 0x10 || buf_io[0] >= 0x40) { + // bad data + rv = ERANGE; + 800097e: bf88 it hi + 8000980: 2422 movhi r4, #34 ; 0x22 + } if(check_is_downgrade(buf_io)) { + 8000982: f000 ff2f bl 80017e4 + 8000986: b9f0 cbnz r0, 80009c6 + // already at a higher version? + rv = EAGAIN; + } else { + uint8_t min[8]; + get_min_version(min); + 8000988: a80c add r0, sp, #48 ; 0x30 + 800098a: f000 ff0d bl 80017a8 + + if(memcmp(min, buf_io, 8) == 0) { + 800098e: 2208 movs r2, #8 + 8000990: 4629 mov r1, r5 + 8000992: a80c add r0, sp, #48 ; 0x30 + 8000994: f005 ff67 bl 8006866 + 8000998: b1a8 cbz r0, 80009c6 + // dupe + rv = EAGAIN; + } else { + // save it, but might be "full" already + if(record_highwater_version(buf_io)) { + 800099a: 4628 mov r0, r5 + 800099c: f001 fa24 bl 8001de8 + rv = ENOMEM; + 80009a0: 2800 cmp r0, #0 + 80009a2: bf18 it ne + 80009a4: 240c movne r4, #12 + 80009a6: e011 b.n 80009cc + break; + + case -1: + // System startup code. Cannot be reached by any code (that hopes to run + // again) except our reset stub. + if(incoming_lr <= BL_FLASH_BASE || incoming_lr >= (uint32_t)&firewall_starts) { + 80009a8: f1b1 6f00 cmp.w r1, #134217728 ; 0x8000000 + 80009ac: d90d bls.n 80009ca + 80009ae: 4b20 ldr r3, [pc, #128] ; (8000a30 ) + 80009b0: 4299 cmp r1, r3 + 80009b2: d20a bcs.n 80009ca + rv = EPERM; + } else { + system_startup(); + 80009b4: f7ff fdb8 bl 8000528 + 80009b8: e7a1 b.n 80008fe + // - 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 > 255) { + rv = ERANGE; + 80009ba: 2422 movs r4, #34 ; 0x22 + 80009bc: e006 b.n 80009cc + // Read a single byte of config dataspace + REQUIRE_OUT(1); + + rv = ae_read_config_byte(arg2 & 0x7f); + if(rv == -1) { + rv = EIO; + 80009be: 2405 movs r4, #5 + 80009c0: e004 b.n 80009cc + } + } + break; + + default: + rv = ENOENT; + 80009c2: 2402 movs r4, #2 + 80009c4: e002 b.n 80009cc + if(buf_io[0] < 0x10 || buf_io[0] >= 0x40) { + // bad data + rv = ERANGE; + } if(check_is_downgrade(buf_io)) { + // already at a higher version? + rv = EAGAIN; + 80009c6: 240b movs r4, #11 + 80009c8: e000 b.n 80009cc + + case -1: + // System startup code. Cannot be reached by any code (that hopes to run + // again) except our reset stub. + if(incoming_lr <= BL_FLASH_BASE || incoming_lr >= (uint32_t)&firewall_starts) { + rv = EPERM; + 80009ca: 2401 movs r4, #1 + +fail: + + // Precaution: we don't want to leave ATECC508A authorized for any specific keys, + // perhaps due to an error path we didn't see. Always reset the chip. + ae_reset_chip(); + 80009cc: f001 fbdc bl 8002188 + + // Unlikely it matters, but clear flash memory cache. + __HAL_FLASH_DATA_CACHE_DISABLE(); + 80009d0: 4b18 ldr r3, [pc, #96] ; (8000a34 ) + 80009d2: 681a ldr r2, [r3, #0] + 80009d4: f422 6280 bic.w r2, r2, #1024 ; 0x400 + 80009d8: 601a str r2, [r3, #0] + __HAL_FLASH_DATA_CACHE_RESET(); + 80009da: 681a ldr r2, [r3, #0] + 80009dc: f442 5280 orr.w r2, r2, #4096 ; 0x1000 + 80009e0: 601a str r2, [r3, #0] + 80009e2: 681a ldr r2, [r3, #0] + 80009e4: f422 5280 bic.w r2, r2, #4096 ; 0x1000 + 80009e8: 601a str r2, [r3, #0] + __HAL_FLASH_DATA_CACHE_ENABLE(); + 80009ea: 681a ldr r2, [r3, #0] + 80009ec: f442 6280 orr.w r2, r2, #1024 ; 0x400 + 80009f0: 601a str r2, [r3, #0] + + // .. and instruction memory (flash cache too?) + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + 80009f2: 681a ldr r2, [r3, #0] + 80009f4: f422 7200 bic.w r2, r2, #512 ; 0x200 + 80009f8: 601a str r2, [r3, #0] + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + 80009fa: 681a ldr r2, [r3, #0] + 80009fc: f442 6200 orr.w r2, r2, #2048 ; 0x800 + 8000a00: 601a str r2, [r3, #0] + 8000a02: 681a ldr r2, [r3, #0] + 8000a04: f422 6200 bic.w r2, r2, #2048 ; 0x800 + 8000a08: 601a str r2, [r3, #0] + __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); + 8000a0a: 681a ldr r2, [r3, #0] + 8000a0c: f442 7200 orr.w r2, r2, #512 ; 0x200 + 8000a10: 601a str r2, [r3, #0] + + + // authorize return from firewall into user's code + __HAL_FIREWALL_PREARM_ENABLE(); + 8000a12: f5a3 3382 sub.w r3, r3, #66560 ; 0x10400 + + return rv; +} + 8000a16: 4620 mov r0, r4 + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); + + + // authorize return from firewall into user's code + __HAL_FIREWALL_PREARM_ENABLE(); + 8000a18: 6a1a ldr r2, [r3, #32] + 8000a1a: f042 0201 orr.w r2, r2, #1 + 8000a1e: 621a str r2, [r3, #32] + 8000a20: 6a1b ldr r3, [r3, #32] + 8000a22: f003 0301 and.w r3, r3, #1 + 8000a26: 930c str r3, [sp, #48] ; 0x30 + 8000a28: 9b0c ldr r3, [sp, #48] ; 0x30 + + return rv; +} + 8000a2a: b028 add sp, #160 ; 0xa0 + 8000a2c: bd70 pop {r4, r5, r6, pc} + 8000a2e: bf00 nop + 8000a30: 08000300 .word 0x08000300 + 8000a34: 40022000 .word 0x40022000 + +08000a38 : +const uint32_t MSIRangeTable[12] = {100000, 200000, 400000, 800000, 1000000, 2000000, \ + 4000000, 8000000, 16000000, 24000000, 32000000, 48000000}; +uint32_t SystemCoreClock; + +// TODO: cleanup HAL stuff to not use this +uint32_t HAL_GetTick(void) { return 53; } + 8000a38: 2035 movs r0, #53 ; 0x35 + 8000a3a: 4770 bx lr + +08000a3c : +// + static inline void +write_bytes(int len, const uint8_t *buf) +{ + // send via SPI(1) + HAL_SPI_Transmit(&spi_port, (uint8_t *)buf, len, HAL_MAX_DELAY); + 8000a3c: b282 uxth r2, r0 + 8000a3e: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 8000a42: 4801 ldr r0, [pc, #4] ; (8000a48 ) + 8000a44: f000 bbc1 b.w 80011ca + 8000a48: 10006250 .word 0x10006250 + +08000a4c : + +// oled_write_cmd() +// + void +oled_write_cmd(uint8_t cmd) +{ + 8000a4c: b513 push {r0, r1, r4, lr} + 8000a4e: ac02 add r4, sp, #8 + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000a50: 2201 movs r2, #1 + +// oled_write_cmd() +// + void +oled_write_cmd(uint8_t cmd) +{ + 8000a52: f804 0d01 strb.w r0, [r4, #-1]! + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000a56: 2110 movs r1, #16 + 8000a58: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000a5c: f000 fb2a bl 80010b4 + HAL_GPIO_WritePin(GPIOA, DC_PIN, 0); + 8000a60: 2200 movs r2, #0 + 8000a62: f44f 7180 mov.w r1, #256 ; 0x100 + 8000a66: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000a6a: f000 fb23 bl 80010b4 + HAL_GPIO_WritePin(GPIOA, CS_PIN, 0); + 8000a6e: 2200 movs r2, #0 + 8000a70: 2110 movs r1, #16 + 8000a72: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000a76: f000 fb1d bl 80010b4 + + write_bytes(1, &cmd); + 8000a7a: 4621 mov r1, r4 + 8000a7c: 2001 movs r0, #1 + 8000a7e: f7ff ffdd bl 8000a3c + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000a82: 2201 movs r2, #1 + 8000a84: 2110 movs r1, #16 + 8000a86: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000a8a: f000 fb13 bl 80010b4 +} + 8000a8e: b002 add sp, #8 + 8000a90: bd10 pop {r4, pc} + +08000a92 : + +// oled_write_cmd_sequence() +// + void +oled_write_cmd_sequence(int len, const uint8_t *cmds) +{ + 8000a92: b570 push {r4, r5, r6, lr} + 8000a94: 4606 mov r6, r0 + 8000a96: 460d mov r5, r1 + for(int i=0; i + oled_write_cmd(cmds[i]); + 8000aa0: f814 0b01 ldrb.w r0, [r4], #1 + 8000aa4: f7ff ffd2 bl 8000a4c + 8000aa8: e7f7 b.n 8000a9a + } +} + 8000aaa: bd70 pop {r4, r5, r6, pc} + +08000aac : + +// oled_write_data() +// + void +oled_write_data(int len, const uint8_t *pixels) +{ + 8000aac: b538 push {r3, r4, r5, lr} + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000aae: 2201 movs r2, #1 + +// oled_write_data() +// + void +oled_write_data(int len, const uint8_t *pixels) +{ + 8000ab0: 4604 mov r4, r0 + 8000ab2: 460d mov r5, r1 + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000ab4: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000ab8: 2110 movs r1, #16 + 8000aba: f000 fafb bl 80010b4 + HAL_GPIO_WritePin(GPIOA, DC_PIN, 1); + 8000abe: 2201 movs r2, #1 + 8000ac0: f44f 7180 mov.w r1, #256 ; 0x100 + 8000ac4: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000ac8: f000 faf4 bl 80010b4 + HAL_GPIO_WritePin(GPIOA, CS_PIN, 0); + 8000acc: 2200 movs r2, #0 + 8000ace: 2110 movs r1, #16 + 8000ad0: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000ad4: f000 faee bl 80010b4 + + write_bytes(len, pixels); + 8000ad8: 4629 mov r1, r5 + 8000ada: 4620 mov r0, r4 + 8000adc: f7ff ffae bl 8000a3c + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000ae0: 2201 movs r2, #1 + 8000ae2: 2110 movs r1, #16 + 8000ae4: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 +} + 8000ae8: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} + HAL_GPIO_WritePin(GPIOA, DC_PIN, 1); + HAL_GPIO_WritePin(GPIOA, CS_PIN, 0); + + write_bytes(len, pixels); + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000aec: f000 bae2 b.w 80010b4 + +08000af0 : +// +// Ok to call this lots. +// + void +oled_setup(void) +{ + 8000af0: b530 push {r4, r5, lr} + static uint32_t inited; + + if(inited == 0x238a572F) { + 8000af2: 4b35 ldr r3, [pc, #212] ; (8000bc8 ) + 8000af4: 4a35 ldr r2, [pc, #212] ; (8000bcc ) + 8000af6: 6819 ldr r1, [r3, #0] + 8000af8: 4291 cmp r1, r2 +// +// Ok to call this lots. +// + void +oled_setup(void) +{ + 8000afa: b089 sub sp, #36 ; 0x24 + static uint32_t inited; + + if(inited == 0x238a572F) { + 8000afc: d062 beq.n 8000bc4 + return; + } + inited = 0x238a572F; + 8000afe: 601a str r2, [r3, #0] + + // enable some internal clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + 8000b00: 4b33 ldr r3, [pc, #204] ; (8000bd0 ) + __HAL_RCC_SPI1_CLK_ENABLE(); + + // simple pins + GPIO_InitTypeDef setup = { + 8000b02: 4d34 ldr r5, [pc, #208] ; (8000bd4 ) + return; + } + inited = 0x238a572F; + + // enable some internal clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + 8000b04: 6cda ldr r2, [r3, #76] ; 0x4c + 8000b06: f042 0201 orr.w r2, r2, #1 + 8000b0a: 64da str r2, [r3, #76] ; 0x4c + 8000b0c: 6cda ldr r2, [r3, #76] ; 0x4c + 8000b0e: f002 0201 and.w r2, r2, #1 + 8000b12: 9201 str r2, [sp, #4] + 8000b14: 9a01 ldr r2, [sp, #4] + __HAL_RCC_SPI1_CLK_ENABLE(); + 8000b16: 6e1a ldr r2, [r3, #96] ; 0x60 + 8000b18: f442 5280 orr.w r2, r2, #4096 ; 0x1000 + 8000b1c: 661a str r2, [r3, #96] ; 0x60 + 8000b1e: 6e1b ldr r3, [r3, #96] ; 0x60 + 8000b20: f403 5380 and.w r3, r3, #4096 ; 0x1000 + 8000b24: 9302 str r3, [sp, #8] + 8000b26: 9b02 ldr r3, [sp, #8] + + // simple pins + GPIO_InitTypeDef setup = { + 8000b28: cd0f ldmia r5!, {r0, r1, r2, r3} + 8000b2a: ac03 add r4, sp, #12 + 8000b2c: c40f stmia r4!, {r0, r1, r2, r3} + 8000b2e: 682b ldr r3, [r5, #0] + 8000b30: 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); + 8000b32: a903 add r1, sp, #12 + 8000b34: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000b38: f000 f93e bl 8000db8 + + // starting values + HAL_GPIO_WritePin(GPIOA, RESET_PIN | CS_PIN | DC_PIN, 1); + 8000b3c: 2201 movs r2, #1 + 8000b3e: f44f 71a8 mov.w r1, #336 ; 0x150 + 8000b42: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000b46: f000 fab5 bl 80010b4 + + // SPI pins + setup.Pin = SPI_SCK | SPI_MOSI; + 8000b4a: 23a0 movs r3, #160 ; 0xa0 + 8000b4c: 9303 str r3, [sp, #12] + setup.Mode = GPIO_MODE_AF_PP; + 8000b4e: 2302 movs r3, #2 + 8000b50: 9304 str r3, [sp, #16] + setup.Alternate = GPIO_AF5_SPI1; + HAL_GPIO_Init(GPIOA, &setup); + 8000b52: a903 add r1, sp, #12 + HAL_GPIO_WritePin(GPIOA, RESET_PIN | CS_PIN | DC_PIN, 1); + + // SPI pins + setup.Pin = SPI_SCK | SPI_MOSI; + setup.Mode = GPIO_MODE_AF_PP; + setup.Alternate = GPIO_AF5_SPI1; + 8000b54: 2305 movs r3, #5 + HAL_GPIO_Init(GPIOA, &setup); + 8000b56: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + HAL_GPIO_WritePin(GPIOA, RESET_PIN | CS_PIN | DC_PIN, 1); + + // SPI pins + setup.Pin = SPI_SCK | SPI_MOSI; + setup.Mode = GPIO_MODE_AF_PP; + setup.Alternate = GPIO_AF5_SPI1; + 8000b5a: 9307 str r3, [sp, #28] + HAL_GPIO_Init(GPIOA, &setup); + 8000b5c: f000 f92c bl 8000db8 + + // lock the RESET pin so that St's DFU code doesn't clear screen + // it might be trying to use it a MISO signal for SPI loading + HAL_GPIO_LockPin(GPIOA, RESET_PIN | CS_PIN | DC_PIN); + 8000b60: f44f 71a8 mov.w r1, #336 ; 0x150 + 8000b64: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000b68: f000 faad bl 80010c6 + + // 10ms low-going pulse on reset pin + delay_ms(1); + 8000b6c: 2001 movs r0, #1 + 8000b6e: f002 f9d7 bl 8002f20 + HAL_GPIO_WritePin(GPIOA, RESET_PIN, 0); + 8000b72: 2200 movs r2, #0 + 8000b74: 2140 movs r1, #64 ; 0x40 + 8000b76: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + delay_ms(10); + HAL_GPIO_WritePin(GPIOA, RESET_PIN, 1); + + memset(&spi_port, 0, sizeof(spi_port)); + 8000b7a: 4c17 ldr r4, [pc, #92] ; (8000bd8 ) + // it might be trying to use it a MISO signal for SPI loading + HAL_GPIO_LockPin(GPIOA, RESET_PIN | CS_PIN | DC_PIN); + + // 10ms low-going pulse on reset pin + delay_ms(1); + HAL_GPIO_WritePin(GPIOA, RESET_PIN, 0); + 8000b7c: f000 fa9a bl 80010b4 + delay_ms(10); + 8000b80: 200a movs r0, #10 + 8000b82: f002 f9cd bl 8002f20 + HAL_GPIO_WritePin(GPIOA, RESET_PIN, 1); + 8000b86: 2201 movs r2, #1 + 8000b88: 2140 movs r1, #64 ; 0x40 + 8000b8a: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000b8e: f000 fa91 bl 80010b4 + + memset(&spi_port, 0, sizeof(spi_port)); + 8000b92: 2100 movs r1, #0 + 8000b94: 2264 movs r2, #100 ; 0x64 + 8000b96: 4620 mov r0, r4 + 8000b98: f005 fe9a bl 80068d0 + + spi_port.Instance = SPI1; + + // see SPI_InitTypeDef + spi_port.Init.Mode = SPI_MODE_MASTER; + 8000b9c: 4a0f ldr r2, [pc, #60] ; (8000bdc ) + 8000b9e: f44f 7382 mov.w r3, #260 ; 0x104 + 8000ba2: e884 000c stmia.w r4, {r2, r3} + spi_port.Init.Direction = SPI_DIRECTION_2LINES; + spi_port.Init.DataSize = SPI_DATASIZE_8BIT; + 8000ba6: f44f 63e0 mov.w r3, #1792 ; 0x700 + 8000baa: 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; + 8000bac: f44f 7300 mov.w r3, #512 ; 0x200 + 8000bb0: 61a3 str r3, [r4, #24] + spi_port.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // conservative + 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); + 8000bb2: 4620 mov r0, r4 + spi_port.Init.Direction = SPI_DIRECTION_2LINES; + spi_port.Init.DataSize = SPI_DATASIZE_8BIT; + 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 + 8000bb4: 2318 movs r3, #24 + 8000bb6: 61e3 str r3, [r4, #28] + 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); + 8000bb8: f000 fac0 bl 800113c + // this code: + // '0x37c', '0x1700', '0x603' + //SPI1->CR1 = 0x354; + + // write a sequence to reset things + oled_write_cmd_sequence(sizeof(reset_commands), reset_commands); + 8000bbc: 4908 ldr r1, [pc, #32] ; (8000be0 ) + 8000bbe: 2019 movs r0, #25 + 8000bc0: f7ff ff67 bl 8000a92 +} + 8000bc4: b009 add sp, #36 ; 0x24 + 8000bc6: bd30 pop {r4, r5, pc} + 8000bc8: 1000624c .word 0x1000624c + 8000bcc: 238a572f .word 0x238a572f + 8000bd0: 40021000 .word 0x40021000 + 8000bd4: 08006998 .word 0x08006998 + 8000bd8: 10006250 .word 0x10006250 + 8000bdc: 40013000 .word 0x40013000 + 8000be0: 080069b2 .word 0x080069b2 + +08000be4 : +// +// No decompression. +// + void +oled_show_raw(uint32_t len, const uint8_t *pixels) +{ + 8000be4: b538 push {r3, r4, r5, lr} + 8000be6: 4604 mov r4, r0 + 8000be8: 460d mov r5, r1 + oled_setup(); + 8000bea: f7ff ff81 bl 8000af0 + + oled_write_cmd_sequence(sizeof(before_show), before_show); + 8000bee: 4911 ldr r1, [pc, #68] ; (8000c34 ) + 8000bf0: 2006 movs r0, #6 + 8000bf2: f7ff ff4e bl 8000a92 + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000bf6: 2201 movs r2, #1 + 8000bf8: 2110 movs r1, #16 + 8000bfa: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000bfe: f000 fa59 bl 80010b4 + HAL_GPIO_WritePin(GPIOA, DC_PIN, 1); + 8000c02: 2201 movs r2, #1 + 8000c04: f44f 7180 mov.w r1, #256 ; 0x100 + 8000c08: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000c0c: f000 fa52 bl 80010b4 + HAL_GPIO_WritePin(GPIOA, CS_PIN, 0); + 8000c10: 2200 movs r2, #0 + 8000c12: 2110 movs r1, #16 + 8000c14: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000c18: f000 fa4c bl 80010b4 + + write_bytes(len, pixels); + 8000c1c: 4629 mov r1, r5 + 8000c1e: 4620 mov r0, r4 + 8000c20: f7ff ff0c bl 8000a3c + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000c24: 2201 movs r2, #1 + 8000c26: 2110 movs r1, #16 + 8000c28: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 +} + 8000c2c: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} + HAL_GPIO_WritePin(GPIOA, DC_PIN, 1); + HAL_GPIO_WritePin(GPIOA, CS_PIN, 0); + + write_bytes(len, pixels); + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000c30: f000 ba40 b.w 80010b4 + 8000c34: 080069ac .word 0x080069ac + +08000c38 : +// +// Perform simple RLE decompression. +// + void +oled_show(const uint8_t *pixels) +{ + 8000c38: b530 push {r4, r5, lr} + 8000c3a: b0a1 sub sp, #132 ; 0x84 + 8000c3c: 4604 mov r4, r0 + oled_setup(); + 8000c3e: f7ff ff57 bl 8000af0 + + oled_write_cmd_sequence(sizeof(before_show), before_show); + 8000c42: 491c ldr r1, [pc, #112] ; (8000cb4 ) + 8000c44: 2006 movs r0, #6 + 8000c46: f7ff ff24 bl 8000a92 + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000c4a: 2201 movs r2, #1 + 8000c4c: 2110 movs r1, #16 + 8000c4e: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000c52: f000 fa2f bl 80010b4 + HAL_GPIO_WritePin(GPIOA, DC_PIN, 1); + 8000c56: 2201 movs r2, #1 + 8000c58: f44f 7180 mov.w r1, #256 ; 0x100 + 8000c5c: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000c60: f000 fa28 bl 80010b4 + HAL_GPIO_WritePin(GPIOA, CS_PIN, 0); + 8000c64: 2200 movs r2, #0 + 8000c66: 2110 movs r1, #16 + 8000c68: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000c6c: f000 fa22 bl 80010b4 + 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++); + 8000c70: 7823 ldrb r3, [r4, #0] + if(!hdr) break; + 8000c72: b1b3 cbz r3, 8000ca2 + + uint8_t len = hdr & 0x7f; + 8000c74: f003 057f and.w r5, r3, #127 ; 0x7f + if(hdr & 0x80) { + 8000c78: 061b lsls r3, r3, #24 + 8000c7a: d507 bpl.n 8000c8c + 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++); + 8000c7c: 3401 adds r4, #1 + if(!hdr) break; + + uint8_t len = hdr & 0x7f; + if(hdr & 0x80) { + // random bytes follow + memcpy(buf, p, len); + 8000c7e: 4621 mov r1, r4 + 8000c80: 462a mov r2, r5 + 8000c82: 4668 mov r0, sp + 8000c84: f005 fdfe bl 8006884 + p += len; + 8000c88: 442c add r4, r5 + 8000c8a: e005 b.n 8000c98 + } else { + // repeat same byte + memset(buf, *p, len); + 8000c8c: 7861 ldrb r1, [r4, #1] + 8000c8e: 462a mov r2, r5 + 8000c90: 4668 mov r0, sp + 8000c92: f005 fe1d bl 80068d0 + p++; + 8000c96: 3402 adds r4, #2 + } + + write_bytes(len, buf); + 8000c98: 4669 mov r1, sp + 8000c9a: 4628 mov r0, r5 + 8000c9c: f7ff fece bl 8000a3c + } + 8000ca0: e7e6 b.n 8000c70 + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000ca2: 2201 movs r2, #1 + 8000ca4: 2110 movs r1, #16 + 8000ca6: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000caa: f000 fa03 bl 80010b4 +} + 8000cae: b021 add sp, #132 ; 0x84 + 8000cb0: bd30 pop {r4, r5, pc} + 8000cb2: bf00 nop + 8000cb4: 080069ac .word 0x080069ac + +08000cb8 : +// +// Perform simple RLE decompression, and add a bar on final screen line. +// + void +oled_show_progress(const uint8_t *pixels, int progress) +{ + 8000cb8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 8000cbc: b0a0 sub sp, #128 ; 0x80 + 8000cbe: 460d mov r5, r1 + 8000cc0: 4607 mov r7, r0 + oled_setup(); + 8000cc2: f7ff ff15 bl 8000af0 + + oled_write_cmd_sequence(sizeof(before_show), before_show); + 8000cc6: 493b ldr r1, [pc, #236] ; (8000db4 ) + 8000cc8: 2006 movs r0, #6 + 8000cca: f7ff fee2 bl 8000a92 + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000cce: 2201 movs r2, #1 + 8000cd0: 2110 movs r1, #16 + 8000cd2: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000cd6: f000 f9ed bl 80010b4 + HAL_GPIO_WritePin(GPIOA, DC_PIN, 1); + 8000cda: 2201 movs r2, #1 + 8000cdc: f44f 7180 mov.w r1, #256 ; 0x100 + 8000ce0: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000ce4: f000 f9e6 bl 80010b4 + HAL_GPIO_WritePin(GPIOA, CS_PIN, 0); + 8000ce8: 2110 movs r1, #16 + 8000cea: 2200 movs r2, #0 + 8000cec: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000cf0: f000 f9e0 bl 80010b4 + + uint8_t buf[127]; + const uint8_t *p = pixels; + + const uint16_t p_start = 896; + uint32_t p_count = 1280 * progress / 1000; + 8000cf4: f44f 61a0 mov.w r1, #1280 ; 0x500 + 8000cf8: 4369 muls r1, r5 + 8000cfa: 2600 movs r6, #0 + 8000cfc: f44f 757a mov.w r5, #1000 ; 0x3e8 + 8000d00: fb91 f5f5 sdiv r5, r1, r5 + 8000d04: 2d80 cmp r5, #128 ; 0x80 + 8000d06: bf28 it cs + 8000d08: 2580 movcs r5, #128 ; 0x80 + 8000d0a: 46b0 mov r8, r6 + + bool last_line = false; + + uint16_t offset = 0; + while(1) { + uint8_t hdr = *(p++); + 8000d0c: 783b ldrb r3, [r7, #0] + if(hdr == 0) break; + 8000d0e: b3ab cbz r3, 8000d7c + + uint8_t len = hdr & 0x7f; + 8000d10: f003 047f and.w r4, r3, #127 ; 0x7f + if(hdr & 0x80) { + 8000d14: 061b lsls r3, r3, #24 + 8000d16: d507 bpl.n 8000d28 + + bool last_line = false; + + uint16_t offset = 0; + while(1) { + uint8_t hdr = *(p++); + 8000d18: 3701 adds r7, #1 + if(hdr == 0) break; + + uint8_t len = hdr & 0x7f; + if(hdr & 0x80) { + // random bytes follow + memcpy(buf, p, len); + 8000d1a: 4639 mov r1, r7 + 8000d1c: 4622 mov r2, r4 + 8000d1e: 4668 mov r0, sp + 8000d20: f005 fdb0 bl 8006884 + p += len; + 8000d24: 4427 add r7, r4 + 8000d26: e005 b.n 8000d34 + } else { + // repeat same byte + memset(buf, *p, len); + 8000d28: 7879 ldrb r1, [r7, #1] + 8000d2a: 4622 mov r2, r4 + 8000d2c: 4668 mov r0, sp + 8000d2e: f005 fdcf bl 80068d0 + p++; + 8000d32: 3702 adds r7, #2 + } + + if(!last_line && (offset+len) >= p_start) { + 8000d34: f1b8 0f00 cmp.w r8, #0 + 8000d38: d129 bne.n 8000d8e + 8000d3a: 1933 adds r3, r6, r4 + 8000d3c: f5b3 7f60 cmp.w r3, #896 ; 0x380 + 8000d40: db15 blt.n 8000d6e + last_line = true; + + // adjust so we're aligned w/ last line + int h = p_start - offset; + if(h) { + 8000d42: f5d6 7860 rsbs r8, r6, #896 ; 0x380 + 8000d46: d022 beq.n 8000d8e + write_bytes(h, buf); + 8000d48: 4669 mov r1, sp + 8000d4a: 4640 mov r0, r8 + memmove(buf, buf+h, len-h); + 8000d4c: ebc8 0404 rsb r4, r8, r4 + last_line = true; + + // adjust so we're aligned w/ last line + int h = p_start - offset; + if(h) { + write_bytes(h, buf); + 8000d50: f7ff fe74 bl 8000a3c + memmove(buf, buf+h, len-h); + 8000d54: 4622 mov r2, r4 + 8000d56: eb0d 0108 add.w r1, sp, r8 + 8000d5a: 4668 mov r0, sp + 8000d5c: f005 fd9d bl 800689a + len -= h; + 8000d60: b2e4 uxtb r4, r4 + offset += h; + 8000d62: f44f 7660 mov.w r6, #896 ; 0x380 + 8000d66: e012 b.n 8000d8e + 8000d68: 4615 mov r5, r2 + 8000d6a: f04f 0801 mov.w r8, #1 + for(int j=0; (p_count > 0) && (j 0) && (j + offset += len; + 8000d78: b2b6 uxth r6, r6 + } + 8000d7a: e7c7 b.n 8000d0c + + HAL_GPIO_WritePin(GPIOA, CS_PIN, 1); + 8000d7c: 2201 movs r2, #1 + 8000d7e: 2110 movs r1, #16 + 8000d80: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8000d84: f000 f996 bl 80010b4 +} + 8000d88: b020 add sp, #128 ; 0x80 + 8000d8a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + + uint8_t buf[127]; + const uint8_t *p = pixels; + + const uint16_t p_start = 896; + uint32_t p_count = 1280 * progress / 1000; + 8000d8e: 2300 movs r3, #0 + offset += h; + } + } + + if(last_line) { + for(int j=0; (p_count > 0) && (j + 8000d98: 42a3 cmp r3, r4 + 8000d9a: dae5 bge.n 8000d68 + buf[j] |= 0x80; + 8000d9c: f81d 2003 ldrb.w r2, [sp, r3] + 8000da0: f062 027f orn r2, r2, #127 ; 0x7f + 8000da4: f80d 2003 strb.w r2, [sp, r3] + offset += h; + } + } + + if(last_line) { + for(int j=0; (p_count > 0) && (j + 8000dac: f04f 0801 mov.w r8, #1 + 8000db0: 2500 movs r5, #0 + 8000db2: e7dc b.n 8000d6e + 8000db4: 080069ac .word 0x080069ac + +08000db8 : + * @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) +{ + 8000db8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); + assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); + assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); + + /* Configure the port pins */ + while (((GPIO_Init->Pin) >> position) != RESET) + 8000dbc: f8d1 b000 ldr.w fp, [r1] + /*--------------------- 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(); + 8000dc0: f8df 81ac ldr.w r8, [pc, #428] ; 8000f70 + 8000dc4: 4c68 ldr r4, [pc, #416] ; (8000f68 ) + * @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) +{ + 8000dc6: b085 sub sp, #20 + uint32_t position = 0x00; + 8000dc8: 2300 movs r3, #0 + assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); + assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); + assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); + + /* Configure the port pins */ + while (((GPIO_Init->Pin) >> position) != RESET) + 8000dca: fa3b f203 lsrs.w r2, fp, r3 + 8000dce: f000 80c7 beq.w 8000f60 + { + /* Get current io position */ + iocurrent = (GPIO_Init->Pin) & (1U << position); + 8000dd2: 2601 movs r6, #1 + 8000dd4: 409e lsls r6, r3 + + if(iocurrent) + 8000dd6: ea1b 0e06 ands.w lr, fp, r6 + 8000dda: f000 80bf beq.w 8000f5c + { + /*--------------------- GPIO Mode Configuration ------------------------*/ + /* In case of Alternate function mode selection */ + if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) + 8000dde: 684a ldr r2, [r1, #4] + 8000de0: f022 0910 bic.w r9, r2, #16 + 8000de4: f1b9 0f02 cmp.w r9, #2 + 8000de8: d114 bne.n 8000e14 + 8000dea: ea4f 0cd3 mov.w ip, r3, lsr #3 + 8000dee: eb00 0c8c add.w ip, r0, ip, lsl #2 + assert_param(IS_GPIO_AF_INSTANCE(GPIOx)); + assert_param(IS_GPIO_AF(GPIO_Init->Alternate)); + + /* Configure Alternate function mapped with the current IO */ + temp = GPIOx->AFR[position >> 3]; + temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ; + 8000df2: f003 0a07 and.w sl, r3, #7 + /* Check the Alternate function parameters */ + assert_param(IS_GPIO_AF_INSTANCE(GPIOx)); + assert_param(IS_GPIO_AF(GPIO_Init->Alternate)); + + /* Configure Alternate function mapped with the current IO */ + temp = GPIOx->AFR[position >> 3]; + 8000df6: f8dc 7020 ldr.w r7, [ip, #32] + temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ; + 8000dfa: ea4f 0a8a mov.w sl, sl, lsl #2 + 8000dfe: 250f movs r5, #15 + 8000e00: fa05 f50a lsl.w r5, r5, sl + 8000e04: ea27 0705 bic.w r7, r7, r5 + temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4)); + 8000e08: 690d ldr r5, [r1, #16] + 8000e0a: fa05 f50a lsl.w r5, r5, sl + 8000e0e: 433d orrs r5, r7 + GPIOx->AFR[position >> 3] = temp; + 8000e10: f8cc 5020 str.w r5, [ip, #32] + 8000e14: ea4f 0c43 mov.w ip, r3, lsl #1 + } + + /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ + temp = GPIOx->MODER; + temp &= ~(GPIO_MODER_MODE0 << (position * 2)); + 8000e18: 2503 movs r5, #3 + temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4)); + GPIOx->AFR[position >> 3] = temp; + } + + /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ + temp = GPIOx->MODER; + 8000e1a: 6807 ldr r7, [r0, #0] + temp &= ~(GPIO_MODER_MODE0 << (position * 2)); + 8000e1c: fa05 f50c lsl.w r5, r5, ip + 8000e20: 43ed mvns r5, r5 + temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2)); + 8000e22: f002 0a03 and.w sl, r2, #3 + GPIOx->AFR[position >> 3] = temp; + } + + /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ + temp = GPIOx->MODER; + temp &= ~(GPIO_MODER_MODE0 << (position * 2)); + 8000e26: 9501 str r5, [sp, #4] + temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2)); + GPIOx->MODER = temp; + + /* In case of Output or Alternate function mode selection */ + if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || + 8000e28: f109 39ff add.w r9, r9, #4294967295 ; 0xffffffff + GPIOx->AFR[position >> 3] = temp; + } + + /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ + temp = GPIOx->MODER; + temp &= ~(GPIO_MODER_MODE0 << (position * 2)); + 8000e2c: 403d ands r5, r7 + temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2)); + 8000e2e: fa0a f70c lsl.w r7, sl, ip + 8000e32: 433d orrs r5, r7 + GPIOx->MODER = temp; + + /* In case of Output or Alternate function mode selection */ + if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || + 8000e34: f1b9 0f01 cmp.w r9, #1 + + /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ + temp = GPIOx->MODER; + temp &= ~(GPIO_MODER_MODE0 << (position * 2)); + temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2)); + GPIOx->MODER = temp; + 8000e38: 6005 str r5, [r0, #0] + + /* In case of Output or Alternate function mode selection */ + if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || + 8000e3a: d813 bhi.n 8000e64 + (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) + { + /* Check the Speed parameter */ + assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); + /* Configure the IO Speed */ + temp = GPIOx->OSPEEDR; + 8000e3c: 6887 ldr r7, [r0, #8] + temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2)); + 8000e3e: 9d01 ldr r5, [sp, #4] + 8000e40: ea05 0907 and.w r9, r5, r7 + temp |= (GPIO_Init->Speed << (position * 2)); + 8000e44: 68cf ldr r7, [r1, #12] + 8000e46: fa07 f70c lsl.w r7, r7, ip + 8000e4a: ea47 0709 orr.w r7, r7, r9 + GPIOx->OSPEEDR = temp; + 8000e4e: 6087 str r7, [r0, #8] + + /* Configure the IO Output Type */ + temp = GPIOx->OTYPER; + 8000e50: 6847 ldr r7, [r0, #4] + temp &= ~(GPIO_OTYPER_OT0 << position) ; + temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position); + 8000e52: f3c2 1900 ubfx r9, r2, #4, #1 + temp |= (GPIO_Init->Speed << (position * 2)); + GPIOx->OSPEEDR = temp; + + /* Configure the IO Output Type */ + temp = GPIOx->OTYPER; + temp &= ~(GPIO_OTYPER_OT0 << position) ; + 8000e56: ea27 0706 bic.w r7, r7, r6 + temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position); + 8000e5a: fa09 f903 lsl.w r9, r9, r3 + 8000e5e: ea49 0707 orr.w r7, r9, r7 + GPIOx->OTYPER = temp; + 8000e62: 6047 str r7, [r0, #4] + } + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + /* In case of Analog mode, check if ADC control mode is selected */ + if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG) + 8000e64: f1ba 0f03 cmp.w sl, #3 + 8000e68: d107 bne.n 8000e7a + { + /* Configure the IO Output Type */ + temp = GPIOx->ASCR; + 8000e6a: 6ac7 ldr r7, [r0, #44] ; 0x2c + temp &= ~(GPIO_ASCR_ASC0 << position) ; + 8000e6c: ea27 0606 bic.w r6, r7, r6 + temp |= (((GPIO_Init->Mode & ANALOG_MODE) >> 3) << position); + 8000e70: f3c2 07c0 ubfx r7, r2, #3, #1 + 8000e74: 409f lsls r7, r3 + 8000e76: 433e orrs r6, r7 + GPIOx->ASCR = temp; + 8000e78: 62c6 str r6, [r0, #44] ; 0x2c + } + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + + /* Activate the Pull-up or Pull down resistor for the current IO */ + temp = GPIOx->PUPDR; + 8000e7a: 68c6 ldr r6, [r0, #12] + temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2)); + 8000e7c: 9d01 ldr r5, [sp, #4] + 8000e7e: 4035 ands r5, r6 + temp |= ((GPIO_Init->Pull) << (position * 2)); + 8000e80: 688e ldr r6, [r1, #8] + 8000e82: fa06 f60c lsl.w r6, r6, ip + 8000e86: 4335 orrs r5, r6 + GPIOx->PUPDR = temp; + 8000e88: 60c5 str r5, [r0, #12] + + /*--------------------- EXTI Mode Configuration ------------------------*/ + /* Configure the External Interrupt or event for the current IO */ + if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) + 8000e8a: 00d5 lsls r5, r2, #3 + 8000e8c: d566 bpl.n 8000f5c + { + /* Enable SYSCFG Clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + 8000e8e: f8d8 5060 ldr.w r5, [r8, #96] ; 0x60 + 8000e92: f045 0501 orr.w r5, r5, #1 + 8000e96: f8c8 5060 str.w r5, [r8, #96] ; 0x60 + 8000e9a: f8d8 5060 ldr.w r5, [r8, #96] ; 0x60 + 8000e9e: f023 0703 bic.w r7, r3, #3 + 8000ea2: f107 4780 add.w r7, r7, #1073741824 ; 0x40000000 + 8000ea6: f005 0501 and.w r5, r5, #1 + 8000eaa: f507 3780 add.w r7, r7, #65536 ; 0x10000 + 8000eae: 9503 str r5, [sp, #12] + + temp = SYSCFG->EXTICR[position >> 2]; + temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03))); + 8000eb0: f003 0c03 and.w ip, r3, #3 + /*--------------------- 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(); + 8000eb4: 9d03 ldr r5, [sp, #12] + + temp = SYSCFG->EXTICR[position >> 2]; + 8000eb6: 68be ldr r6, [r7, #8] + temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03))); + 8000eb8: ea4f 0c8c mov.w ip, ip, lsl #2 + 8000ebc: 250f movs r5, #15 + 8000ebe: fa05 f50c lsl.w r5, r5, ip + temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))); + 8000ec2: f1b0 4f90 cmp.w r0, #1207959552 ; 0x48000000 + { + /* Enable SYSCFG Clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + temp = SYSCFG->EXTICR[position >> 2]; + temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03))); + 8000ec6: ea26 0605 bic.w r6, r6, r5 + temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))); + 8000eca: d019 beq.n 8000f00 + 8000ecc: 4d27 ldr r5, [pc, #156] ; (8000f6c ) + 8000ece: 42a8 cmp r0, r5 + 8000ed0: d018 beq.n 8000f04 + 8000ed2: f505 6580 add.w r5, r5, #1024 ; 0x400 + 8000ed6: 42a8 cmp r0, r5 + 8000ed8: d016 beq.n 8000f08 + 8000eda: f505 6580 add.w r5, r5, #1024 ; 0x400 + 8000ede: 42a8 cmp r0, r5 + 8000ee0: d014 beq.n 8000f0c + 8000ee2: f505 6580 add.w r5, r5, #1024 ; 0x400 + 8000ee6: 42a8 cmp r0, r5 + 8000ee8: d012 beq.n 8000f10 + 8000eea: f505 6580 add.w r5, r5, #1024 ; 0x400 + 8000eee: 42a8 cmp r0, r5 + 8000ef0: d010 beq.n 8000f14 + 8000ef2: f505 6580 add.w r5, r5, #1024 ; 0x400 + 8000ef6: 42a8 cmp r0, r5 + 8000ef8: bf14 ite ne + 8000efa: 2507 movne r5, #7 + 8000efc: 2506 moveq r5, #6 + 8000efe: e00a b.n 8000f16 + 8000f00: 2500 movs r5, #0 + 8000f02: e008 b.n 8000f16 + 8000f04: 2501 movs r5, #1 + 8000f06: e006 b.n 8000f16 + 8000f08: 2502 movs r5, #2 + 8000f0a: e004 b.n 8000f16 + 8000f0c: 2503 movs r5, #3 + 8000f0e: e002 b.n 8000f16 + 8000f10: 2504 movs r5, #4 + 8000f12: e000 b.n 8000f16 + 8000f14: 2505 movs r5, #5 + 8000f16: fa05 f50c lsl.w r5, r5, ip + 8000f1a: 4335 orrs r5, r6 + SYSCFG->EXTICR[position >> 2] = temp; + 8000f1c: 60bd str r5, [r7, #8] + + /* Clear EXTI line configuration */ + temp = EXTI->IMR1; + 8000f1e: 4d12 ldr r5, [pc, #72] ; (8000f68 ) + 8000f20: 682d ldr r5, [r5, #0] + temp &= ~((uint32_t)iocurrent); + 8000f22: ea6f 060e mvn.w r6, lr + if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) + 8000f26: 03d7 lsls r7, r2, #15 + temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))); + SYSCFG->EXTICR[position >> 2] = temp; + + /* Clear EXTI line configuration */ + temp = EXTI->IMR1; + temp &= ~((uint32_t)iocurrent); + 8000f28: bf54 ite pl + 8000f2a: 4035 andpl r5, r6 + if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) + { + temp |= iocurrent; + 8000f2c: ea4e 0505 orrmi.w r5, lr, r5 + } + EXTI->IMR1 = temp; + 8000f30: 6025 str r5, [r4, #0] + + temp = EXTI->EMR1; + 8000f32: 6865 ldr r5, [r4, #4] + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) + 8000f34: 0397 lsls r7, r2, #14 + temp |= iocurrent; + } + EXTI->IMR1 = temp; + + temp = EXTI->EMR1; + temp &= ~((uint32_t)iocurrent); + 8000f36: bf54 ite pl + 8000f38: 4035 andpl r5, r6 + if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) + { + temp |= iocurrent; + 8000f3a: ea4e 0505 orrmi.w r5, lr, r5 + } + EXTI->EMR1 = temp; + 8000f3e: 6065 str r5, [r4, #4] + + /* Clear Rising Falling edge configuration */ + temp = EXTI->RTSR1; + 8000f40: 68a5 ldr r5, [r4, #8] + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) + 8000f42: 02d7 lsls r7, r2, #11 + } + EXTI->EMR1 = temp; + + /* Clear Rising Falling edge configuration */ + temp = EXTI->RTSR1; + temp &= ~((uint32_t)iocurrent); + 8000f44: bf54 ite pl + 8000f46: 4035 andpl r5, r6 + if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) + { + temp |= iocurrent; + 8000f48: ea4e 0505 orrmi.w r5, lr, r5 + } + EXTI->RTSR1 = temp; + 8000f4c: 60a5 str r5, [r4, #8] + + temp = EXTI->FTSR1; + 8000f4e: 68e5 ldr r5, [r4, #12] + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) + 8000f50: 0292 lsls r2, r2, #10 + temp |= iocurrent; + } + EXTI->RTSR1 = temp; + + temp = EXTI->FTSR1; + temp &= ~((uint32_t)iocurrent); + 8000f52: bf54 ite pl + 8000f54: 4035 andpl r5, r6 + if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) + { + temp |= iocurrent; + 8000f56: ea4e 0505 orrmi.w r5, lr, r5 + } + EXTI->FTSR1 = temp; + 8000f5a: 60e5 str r5, [r4, #12] + } + } + + position++; + 8000f5c: 3301 adds r3, #1 + 8000f5e: e734 b.n 8000dca + } +} + 8000f60: b005 add sp, #20 + 8000f62: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 8000f66: bf00 nop + 8000f68: 40010400 .word 0x40010400 + 8000f6c: 48000400 .word 0x48000400 + 8000f70: 40021000 .word 0x40021000 + +08000f74 : + * @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) +{ + 8000f74: e92d 4ff7 stmdb sp!, {r0, r1, r2, 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); + 8000f78: 4a47 ldr r2, [pc, #284] ; (8001098 ) + /*------------------------- EXTI Mode Configuration --------------------*/ + /* Clear the External Interrupt or Event for the current IO */ + + tmp = SYSCFG->EXTICR[position >> 2]; + tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03))); + if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)))) + 8000f7a: f8df a124 ldr.w sl, [pc, #292] ; 80010a0 + 8000f7e: f8df b124 ldr.w fp, [pc, #292] ; 80010a4 + * 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) +{ + uint32_t position = 0x00; + 8000f82: 2300 movs r3, #0 + + /* Configure the port pins */ + while ((GPIO_Pin >> position) != RESET) + { + /* Get current io position */ + iocurrent = (GPIO_Pin) & (1U << position); + 8000f84: f04f 0801 mov.w r8, #1 + + if (iocurrent) + { + /*------------------------- GPIO Mode Configuration --------------------*/ + /* Configure IO in Analog Mode */ + GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2)); + 8000f88: f04f 0903 mov.w r9, #3 + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + /* Configure the port pins */ + while ((GPIO_Pin >> position) != RESET) + 8000f8c: fa31 f403 lsrs.w r4, r1, r3 + 8000f90: d07e beq.n 8001090 + { + /* Get current io position */ + iocurrent = (GPIO_Pin) & (1U << position); + 8000f92: fa08 f603 lsl.w r6, r8, r3 + + if (iocurrent) + 8000f96: ea11 0406 ands.w r4, r1, r6 + 8000f9a: 9401 str r4, [sp, #4] + 8000f9c: d076 beq.n 800108c + { + /*------------------------- GPIO Mode Configuration --------------------*/ + /* Configure IO in Analog Mode */ + GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2)); + 8000f9e: 6807 ldr r7, [r0, #0] + 8000fa0: 005c lsls r4, r3, #1 + 8000fa2: fa09 f404 lsl.w r4, r9, r4 + 8000fa6: ea4f 0cd3 mov.w ip, r3, lsr #3 + 8000faa: 4327 orrs r7, r4 + 8000fac: eb00 0c8c add.w ip, r0, ip, lsl #2 + 8000fb0: 6007 str r7, [r0, #0] + + /* Configure the default Alternate Function in current IO */ + GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ; + 8000fb2: f8dc 7020 ldr.w r7, [ip, #32] + 8000fb6: f003 0e07 and.w lr, r3, #7 + 8000fba: 463d mov r5, r7 + 8000fbc: ea4f 0e8e mov.w lr, lr, lsl #2 + 8000fc0: 270f movs r7, #15 + 8000fc2: fa07 fe0e lsl.w lr, r7, lr + 8000fc6: ea25 0e0e bic.w lr, r5, lr + 8000fca: f8cc e020 str.w lr, [ip, #32] + + /* Configure the default value for IO Speed */ + GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2)); + 8000fce: f8d0 e008 ldr.w lr, [r0, #8] + 8000fd2: 43e4 mvns r4, r4 + 8000fd4: ea0e 0e04 and.w lr, lr, r4 + 8000fd8: f8c0 e008 str.w lr, [r0, #8] + + /* Configure the default value IO Output Type */ + GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ; + 8000fdc: f8d0 e004 ldr.w lr, [r0, #4] + 8000fe0: 43f6 mvns r6, r6 + 8000fe2: ea0e 0e06 and.w lr, lr, r6 + 8000fe6: f8c0 e004 str.w lr, [r0, #4] + + /* Deactivate the Pull-up and Pull-down resistor for the current IO */ + GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2)); + 8000fea: f8d0 e00c ldr.w lr, [r0, #12] + 8000fee: ea04 040e and.w r4, r4, lr + 8000ff2: 60c4 str r4, [r0, #12] + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + /* Deactivate the Control bit of Analog mode for the current IO */ + GPIOx->ASCR &= ~(GPIO_ASCR_ASC0<< position); + 8000ff4: 6ac4 ldr r4, [r0, #44] ; 0x2c + 8000ff6: 4026 ands r6, r4 + 8000ff8: 62c6 str r6, [r0, #44] ; 0x2c + 8000ffa: f023 0603 bic.w r6, r3, #3 + 8000ffe: f106 4680 add.w r6, r6, #1073741824 ; 0x40000000 + 8001002: f506 3680 add.w r6, r6, #65536 ; 0x10000 + + /*------------------------- EXTI Mode Configuration --------------------*/ + /* Clear the External Interrupt or Event for the current IO */ + + tmp = SYSCFG->EXTICR[position >> 2]; + tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03))); + 8001006: f003 0e03 and.w lr, r3, #3 +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + + /*------------------------- EXTI Mode Configuration --------------------*/ + /* Clear the External Interrupt or Event for the current IO */ + + tmp = SYSCFG->EXTICR[position >> 2]; + 800100a: 68b4 ldr r4, [r6, #8] + tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03))); + 800100c: ea4f 0e8e mov.w lr, lr, lsl #2 + 8001010: fa07 f70e lsl.w r7, r7, lr + if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)))) + 8001014: f1b0 4f90 cmp.w r0, #1207959552 ; 0x48000000 + + /*------------------------- EXTI Mode Configuration --------------------*/ + /* Clear the External Interrupt or Event for the current IO */ + + tmp = SYSCFG->EXTICR[position >> 2]; + tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03))); + 8001018: ea04 0c07 and.w ip, r4, r7 + if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)))) + 800101c: d015 beq.n 800104a + 800101e: 4c1f ldr r4, [pc, #124] ; (800109c ) + 8001020: 42a0 cmp r0, r4 + 8001022: d014 beq.n 800104e + 8001024: f504 6480 add.w r4, r4, #1024 ; 0x400 + 8001028: 42a0 cmp r0, r4 + 800102a: d012 beq.n 8001052 + 800102c: f504 6480 add.w r4, r4, #1024 ; 0x400 + 8001030: 42a0 cmp r0, r4 + 8001032: d010 beq.n 8001056 + 8001034: f504 6480 add.w r4, r4, #1024 ; 0x400 + 8001038: 42a0 cmp r0, r4 + 800103a: d00e beq.n 800105a + 800103c: 4550 cmp r0, sl + 800103e: d00e beq.n 800105e + 8001040: 4558 cmp r0, fp + 8001042: bf0c ite eq + 8001044: 2406 moveq r4, #6 + 8001046: 2407 movne r4, #7 + 8001048: e00a b.n 8001060 + 800104a: 2400 movs r4, #0 + 800104c: e008 b.n 8001060 + 800104e: 2401 movs r4, #1 + 8001050: e006 b.n 8001060 + 8001052: 2402 movs r4, #2 + 8001054: e004 b.n 8001060 + 8001056: 2403 movs r4, #3 + 8001058: e002 b.n 8001060 + 800105a: 2404 movs r4, #4 + 800105c: e000 b.n 8001060 + 800105e: 2405 movs r4, #5 + 8001060: fa04 f40e lsl.w r4, r4, lr + 8001064: 45a4 cmp ip, r4 + 8001066: d111 bne.n 800108c + { + tmp = ((uint32_t)0x0F) << (4 * (position & 0x03)); + SYSCFG->EXTICR[position >> 2] &= ~tmp; + 8001068: 68b4 ldr r4, [r6, #8] + + /* Clear EXTI line configuration */ + EXTI->IMR1 &= ~((uint32_t)iocurrent); + 800106a: 9d01 ldr r5, [sp, #4] + tmp = SYSCFG->EXTICR[position >> 2]; + tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03))); + if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)))) + { + tmp = ((uint32_t)0x0F) << (4 * (position & 0x03)); + SYSCFG->EXTICR[position >> 2] &= ~tmp; + 800106c: ea24 0707 bic.w r7, r4, r7 + 8001070: 60b7 str r7, [r6, #8] + + /* Clear EXTI line configuration */ + EXTI->IMR1 &= ~((uint32_t)iocurrent); + 8001072: 6814 ldr r4, [r2, #0] + 8001074: 43ed mvns r5, r5 + 8001076: 402c ands r4, r5 + 8001078: 6014 str r4, [r2, #0] + EXTI->EMR1 &= ~((uint32_t)iocurrent); + 800107a: 6854 ldr r4, [r2, #4] + 800107c: 402c ands r4, r5 + 800107e: 6054 str r4, [r2, #4] + + /* Clear Rising Falling edge configuration */ + EXTI->RTSR1 &= ~((uint32_t)iocurrent); + 8001080: 6894 ldr r4, [r2, #8] + 8001082: 402c ands r4, r5 + 8001084: 6094 str r4, [r2, #8] + EXTI->FTSR1 &= ~((uint32_t)iocurrent); + 8001086: 68d4 ldr r4, [r2, #12] + 8001088: 4025 ands r5, r4 + 800108a: 60d5 str r5, [r2, #12] + } + } + + position++; + 800108c: 3301 adds r3, #1 + 800108e: e77d b.n 8000f8c + } +} + 8001090: b003 add sp, #12 + 8001092: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 8001096: bf00 nop + 8001098: 40010400 .word 0x40010400 + 800109c: 48000400 .word 0x48000400 + 80010a0: 48001400 .word 0x48001400 + 80010a4: 48001800 .word 0x48001800 + +080010a8 : + GPIO_PinState bitstatus; + + /* Check the parameters */ + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET) + 80010a8: 6903 ldr r3, [r0, #16] + } + else + { + bitstatus = GPIO_PIN_RESET; + } + return bitstatus; + 80010aa: 4219 tst r1, r3 +} + 80010ac: bf14 ite ne + 80010ae: 2001 movne r0, #1 + 80010b0: 2000 moveq r0, #0 + 80010b2: 4770 bx lr + +080010b4 : +{ + /* Check the parameters */ + assert_param(IS_GPIO_PIN(GPIO_Pin)); + assert_param(IS_GPIO_PIN_ACTION(PinState)); + + if(PinState != GPIO_PIN_RESET) + 80010b4: b10a cbz r2, 80010ba + { + GPIOx->BSRR = (uint32_t)GPIO_Pin; + 80010b6: 6181 str r1, [r0, #24] + 80010b8: 4770 bx lr + } + else + { + GPIOx->BRR = (uint32_t)GPIO_Pin; + 80010ba: 6281 str r1, [r0, #40] ; 0x28 + 80010bc: 4770 bx lr + +080010be : +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; + 80010be: 6943 ldr r3, [r0, #20] + 80010c0: 4059 eors r1, r3 + 80010c2: 6141 str r1, [r0, #20] + 80010c4: 4770 bx lr + +080010c6 : + * @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) +{ + 80010c6: b082 sub sp, #8 + __IO uint32_t tmp = GPIO_LCKR_LCKK; + 80010c8: f44f 3380 mov.w r3, #65536 ; 0x10000 + 80010cc: 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; + 80010ce: 9b01 ldr r3, [sp, #4] + 80010d0: 430b orrs r3, r1 + 80010d2: 9301 str r3, [sp, #4] + /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ + GPIOx->LCKR = tmp; + 80010d4: 9b01 ldr r3, [sp, #4] + 80010d6: 61c3 str r3, [r0, #28] + /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */ + GPIOx->LCKR = GPIO_Pin; + 80010d8: 61c1 str r1, [r0, #28] + /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ + GPIOx->LCKR = tmp; + 80010da: 9b01 ldr r3, [sp, #4] + 80010dc: 61c3 str r3, [r0, #28] + /* Read LCKK bit*/ + tmp = GPIOx->LCKR; + 80010de: 69c3 ldr r3, [r0, #28] + 80010e0: 9301 str r3, [sp, #4] + + if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET) + 80010e2: 69c0 ldr r0, [r0, #28] + 80010e4: f480 3080 eor.w r0, r0, #65536 ; 0x10000 + } + else + { + return HAL_ERROR; + } +} + 80010e8: f3c0 4000 ubfx r0, r0, #16, #1 + 80010ec: b002 add sp, #8 + 80010ee: 4770 bx lr + +080010f0 : + * @brief EXTI line detection callback. + * @param GPIO_Pin: Specifies the port pin connected to corresponding EXTI line. + * @retval None + */ +__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) +{ + 80010f0: 4770 bx lr + ... + +080010f4 : + * @brief Handle EXTI interrupt request. + * @param GPIO_Pin: Specifies the port pin connected to corresponding EXTI line. + * @retval None + */ +void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) +{ + 80010f4: b508 push {r3, lr} + /* EXTI line interrupt detected */ + if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET) + 80010f6: 4b04 ldr r3, [pc, #16] ; (8001108 ) + 80010f8: 6959 ldr r1, [r3, #20] + 80010fa: 4201 tst r1, r0 + 80010fc: d002 beq.n 8001104 + { + __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); + 80010fe: 6158 str r0, [r3, #20] + HAL_GPIO_EXTI_Callback(GPIO_Pin); + 8001100: f7ff fff6 bl 80010f0 + 8001104: bd08 pop {r3, pc} + 8001106: bf00 nop + 8001108: 40010400 .word 0x40010400 + +0800110c : +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) + 800110c: 6803 ldr r3, [r0, #0] + * @param hspi: SPI handle + * @param Timeout: Timeout duration + * @param Tickstart: tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart) + 800110e: b082 sub sp, #8 +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) + 8001110: 689a ldr r2, [r3, #8] + 8001112: f412 5fc0 tst.w r2, #6144 ; 0x1800 + 8001116: d1fb bne.n 8001110 + * @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) + 8001118: 689a ldr r2, [r3, #8] + 800111a: f002 0280 and.w r2, r2, #128 ; 0x80 + 800111e: 2a00 cmp r2, #0 + 8001120: d1fa bne.n 8001118 +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) + 8001122: 6898 ldr r0, [r3, #8] + 8001124: f410 60c0 ands.w r0, r0, #1536 ; 0x600 + 8001128: d006 beq.n 8001138 + { + if ((Fifo == SPI_SR_FRLVL) && (State == SPI_FRLVL_EMPTY)) + { + tmpreg = *((__IO uint8_t *)&hspi->Instance->DR); + 800112a: 7b1a ldrb r2, [r3, #12] + 800112c: b2d2 uxtb r2, r2 + 800112e: f88d 2007 strb.w r2, [sp, #7] + /* To avoid GCC warning */ + UNUSED(tmpreg); + 8001132: f89d 2007 ldrb.w r2, [sp, #7] + 8001136: e7f4 b.n 8001122 + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + return HAL_OK; +} + 8001138: b002 add sp, #8 + 800113a: 4770 bx lr + +0800113c : + * @param hspi: pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi) +{ + 800113c: b570 push {r4, r5, r6, lr} + uint32_t frxth; + + /* Check the SPI handle allocation */ + if (hspi == NULL) + 800113e: 2800 cmp r0, #0 + 8001140: d041 beq.n 80011c6 + { + assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial)); + assert_param(IS_SPI_CRC_LENGTH(hspi->Init.CRCLength)); + } +#else + hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + 8001142: 2300 movs r3, #0 + 8001144: 6283 str r3, [r0, #40] ; 0x28 +#endif /* USE_SPI_CRC */ + + if (hspi->State == HAL_SPI_STATE_RESET) + 8001146: f890 305d ldrb.w r3, [r0, #93] ; 0x5d + 800114a: f003 02ff and.w r2, r3, #255 ; 0xff + 800114e: b90b cbnz r3, 8001154 + { + /* Allocate lock resource and initialize it */ + hspi->Lock = HAL_UNLOCKED; + 8001150: f880 205c strb.w r2, [r0, #92] ; 0x5c + } + + hspi->State = HAL_SPI_STATE_BUSY; + + /* Disable the selected SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + 8001154: 6801 ldr r1, [r0, #0] + + /* Align by default the rs fifo threshold on the data size */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + 8001156: 68c5 ldr r5, [r0, #12] + + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ +//PDG// HAL_SPI_MspInit(hspi); + } + + hspi->State = HAL_SPI_STATE_BUSY; + 8001158: 2202 movs r2, #2 + 800115a: f880 205d strb.w r2, [r0, #93] ; 0x5d + + /* Disable the selected SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + 800115e: 680b ldr r3, [r1, #0] + 8001160: f023 0340 bic.w r3, r3, #64 ; 0x40 + 8001164: 600b str r3, [r1, #0] + /* CRC must be disabled */ + hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + } + + /* Align the CRC Length on the data size */ + if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE) + 8001166: 6b03 ldr r3, [r0, #48] ; 0x30 + { + frxth = SPI_RXFIFO_THRESHOLD_HF; + } + else + { + frxth = SPI_RXFIFO_THRESHOLD_QF; + 8001168: f5b5 6fe0 cmp.w r5, #1792 ; 0x700 + 800116c: bf8c ite hi + 800116e: 2400 movhi r4, #0 + 8001170: f44f 5480 movls.w r4, #4096 ; 0x1000 + /* CRC must be disabled */ + hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + } + + /* Align the CRC Length on the data size */ + if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE) + 8001174: b92b cbnz r3, 8001182 + { + /* CRC Length aligned on the data size : value set by default */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + 8001176: f5b5 6fe0 cmp.w r5, #1792 ; 0x700 + { + hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT; + } + else + { + hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT; + 800117a: bf96 itet ls + 800117c: 2301 movls r3, #1 + if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE) + { + /* CRC Length aligned on the data size : value set by default */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + { + hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT; + 800117e: 6302 strhi r2, [r0, #48] ; 0x30 + } + else + { + hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT; + 8001180: 6303 strls r3, [r0, #48] ; 0x30 + } + + /*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/ + /* Configure : SPI Mode, Communication Mode, Clock polarity and phase, NSS management, + Communication speed, First bit and CRC calculation state */ + WRITE_REG(hspi->Instance->CR1, (hspi->Init.Mode | hspi->Init.Direction | + 8001182: 6882 ldr r2, [r0, #8] + 8001184: 6846 ldr r6, [r0, #4] + 8001186: 6983 ldr r3, [r0, #24] + 8001188: 4316 orrs r6, r2 + 800118a: 6902 ldr r2, [r0, #16] + 800118c: 4316 orrs r6, r2 + 800118e: 6942 ldr r2, [r0, #20] + 8001190: 4316 orrs r6, r2 + 8001192: 69c2 ldr r2, [r0, #28] + 8001194: 4316 orrs r6, r2 + 8001196: 6a02 ldr r2, [r0, #32] + 8001198: 4316 orrs r6, r2 + 800119a: f403 7200 and.w r2, r3, #512 ; 0x200 + 800119e: 4332 orrs r2, r6 + 80011a0: 600a str r2, [r1, #0] + hspi->Instance->CR1 |= SPI_CR1_CRCL; + } +#endif /* USE_SPI_CRC */ + + /* Configure : NSS management, TI Mode, NSS Pulse, Data size and Rx Fifo Threshold */ + WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) | hspi->Init.TIMode | + 80011a2: 6a42 ldr r2, [r0, #36] ; 0x24 + 80011a4: 4315 orrs r5, r2 + 80011a6: 6b42 ldr r2, [r0, #52] ; 0x34 + 80011a8: 0c1b lsrs r3, r3, #16 + 80011aa: 4315 orrs r5, r2 + 80011ac: f003 0204 and.w r2, r3, #4 + 80011b0: ea45 0302 orr.w r3, r5, r2 + 80011b4: 4323 orrs r3, r4 + 80011b6: 604b str r3, [r1, #4] + /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */ + CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD); +#endif /* SPI_I2SCFGR_I2SMOD */ + + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->State = HAL_SPI_STATE_READY; + 80011b8: 2201 movs r2, #1 +#if defined(SPI_I2SCFGR_I2SMOD) + /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */ + CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD); +#endif /* SPI_I2SCFGR_I2SMOD */ + + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + 80011ba: 2300 movs r3, #0 + 80011bc: 6603 str r3, [r0, #96] ; 0x60 + hspi->State = HAL_SPI_STATE_READY; + 80011be: f880 205d strb.w r2, [r0, #93] ; 0x5d + + return HAL_OK; + 80011c2: 4618 mov r0, r3 + 80011c4: bd70 pop {r4, r5, r6, pc} + uint32_t frxth; + + /* Check the SPI handle allocation */ + if (hspi == NULL) + { + return HAL_ERROR; + 80011c6: 2001 movs r0, #1 + + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->State = HAL_SPI_STATE_READY; + + return HAL_OK; +} + 80011c8: bd70 pop {r4, r5, r6, pc} + +080011ca : + * @param Size: amount of data to be sent + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + 80011ca: e92d 41f3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, lr} + 80011ce: 461e mov r6, r3 + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + 80011d0: f890 305c ldrb.w r3, [r0, #92] ; 0x5c + 80011d4: 2b01 cmp r3, #1 + * @param Size: amount of data to be sent + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + 80011d6: 4604 mov r4, r0 + 80011d8: 460d mov r5, r1 + 80011da: 4690 mov r8, r2 + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + 80011dc: f000 8089 beq.w 80012f2 + 80011e0: 2301 movs r3, #1 + 80011e2: f880 305c strb.w r3, [r0, #92] ; 0x5c + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + 80011e6: f7ff fc27 bl 8000a38 + 80011ea: 4607 mov r7, r0 + + if (hspi->State != HAL_SPI_STATE_READY) + 80011ec: f894 005d ldrb.w r0, [r4, #93] ; 0x5d + 80011f0: b2c0 uxtb r0, r0 + 80011f2: 2801 cmp r0, #1 + 80011f4: d175 bne.n 80012e2 + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pData == NULL) || (Size == 0U)) + 80011f6: 2d00 cmp r5, #0 + 80011f8: d074 beq.n 80012e4 + 80011fa: f1b8 0f00 cmp.w r8, #0 + 80011fe: d071 beq.n 80012e4 + errorcode = HAL_ERROR; + goto error; + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + 8001200: 2303 movs r3, #3 + 8001202: f884 305d strb.w r3, [r4, #93] ; 0x5d + hspi->RxXferCount = 0U; + hspi->TxISR = NULL; + hspi->RxISR = NULL; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + 8001206: 68a3 ldr r3, [r4, #8] + 8001208: 6822 ldr r2, [r4, #0] + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (uint8_t *)pData; + 800120a: 63a5 str r5, [r4, #56] ; 0x38 + goto error; + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + 800120c: 2100 movs r1, #0 + 800120e: 6621 str r1, [r4, #96] ; 0x60 + hspi->RxXferCount = 0U; + hspi->TxISR = NULL; + hspi->RxISR = NULL; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + 8001210: f5b3 4f00 cmp.w r3, #32768 ; 0x8000 + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (uint8_t *)pData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + 8001214: f8a4 803e strh.w r8, [r4, #62] ; 0x3e + + /*Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + hspi->RxXferSize = 0U; + hspi->RxXferCount = 0U; + 8001218: f8a4 1046 strh.w r1, [r4, #70] ; 0x46 + hspi->RxISR = NULL; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + SPI_1LINE_TX(hspi); + 800121c: bf08 it eq + 800121e: 6813 ldreq r3, [r2, #0] + hspi->pTxBuffPtr = (uint8_t *)pData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + 8001220: 6421 str r1, [r4, #64] ; 0x40 + hspi->RxISR = NULL; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + SPI_1LINE_TX(hspi); + 8001222: bf08 it eq + 8001224: f443 4380 orreq.w r3, r3, #16384 ; 0x4000 + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + hspi->RxXferSize = 0U; + 8001228: f8a4 1044 strh.w r1, [r4, #68] ; 0x44 + hspi->RxXferCount = 0U; + hspi->TxISR = NULL; + 800122c: 6521 str r1, [r4, #80] ; 0x50 + hspi->RxISR = NULL; + 800122e: 64e1 str r1, [r4, #76] ; 0x4c + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (uint8_t *)pData; + hspi->TxXferSize = Size; + 8001230: f8a4 803c strh.w r8, [r4, #60] ; 0x3c + hspi->RxISR = NULL; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + SPI_1LINE_TX(hspi); + 8001234: bf08 it eq + 8001236: 6013 streq r3, [r2, #0] + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + 8001238: 6813 ldr r3, [r2, #0] + 800123a: 0659 lsls r1, r3, #25 + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + 800123c: bf5e ittt pl + 800123e: 6813 ldrpl r3, [r2, #0] + 8001240: f043 0340 orrpl.w r3, r3, #64 ; 0x40 + 8001244: 6013 strpl r3, [r2, #0] + } + /* Transmit data in 8 Bit mode */ + else + { +#endif + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U)) + 8001246: 6863 ldr r3, [r4, #4] + 8001248: b11b cbz r3, 8001252 + 800124a: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 800124c: b29b uxth r3, r3 + 800124e: 2b01 cmp r3, #1 + 8001250: d115 bne.n 800127e + { + if (hspi->TxXferCount > 1U) + 8001252: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 8001254: b29b uxth r3, r3 + 8001256: 2b01 cmp r3, #1 + 8001258: d903 bls.n 8001262 + { + /* write on the data register in packing mode */ + hspi->Instance->DR = *((uint16_t *)pData); + 800125a: f835 3b02 ldrh.w r3, [r5], #2 + 800125e: 60d3 str r3, [r2, #12] + 8001260: e01b b.n 800129a + pData += sizeof(uint16_t); + hspi->TxXferCount -= 2U; + } + else + { + *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++); + 8001262: 782b ldrb r3, [r5, #0] + 8001264: 7313 strb r3, [r2, #12] + hspi->TxXferCount--; + 8001266: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 8001268: 3b01 subs r3, #1 + 800126a: b29b uxth r3, r3 + 800126c: 87e3 strh r3, [r4, #62] ; 0x3e + 800126e: e005 b.n 800127c + pData += sizeof(uint16_t); + hspi->TxXferCount -= 2U; + } + else + { + *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++); + 8001270: 782a ldrb r2, [r5, #0] + 8001272: 731a strb r2, [r3, #12] + hspi->TxXferCount--; + 8001274: 8fe2 ldrh r2, [r4, #62] ; 0x3e + 8001276: 3a01 subs r2, #1 + 8001278: b292 uxth r2, r2 + 800127a: 87e2 strh r2, [r4, #62] ; 0x3e + pData += sizeof(uint16_t); + hspi->TxXferCount -= 2U; + } + else + { + *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++); + 800127c: 3501 adds r5, #1 + { + *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++); + hspi->TxXferCount--; + } + } + while (hspi->TxXferCount > 0U) + 800127e: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 8001280: b29b uxth r3, r3 + 8001282: b1d3 cbz r3, 80012ba + { + /* Wait until TXE flag is set to send data */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) + 8001284: 6823 ldr r3, [r4, #0] + 8001286: 689a ldr r2, [r3, #8] + 8001288: 0792 lsls r2, r2, #30 + 800128a: d50b bpl.n 80012a4 + { + if (hspi->TxXferCount > 1U) + 800128c: 8fe2 ldrh r2, [r4, #62] ; 0x3e + 800128e: b292 uxth r2, r2 + 8001290: 2a01 cmp r2, #1 + 8001292: d9ed bls.n 8001270 + { + /* write on the data register in packing mode */ + hspi->Instance->DR = *((uint16_t *)pData); + 8001294: f835 2b02 ldrh.w r2, [r5], #2 + 8001298: 60da str r2, [r3, #12] + pData += sizeof(uint16_t); + hspi->TxXferCount -= 2U; + 800129a: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 800129c: 3b02 subs r3, #2 + 800129e: b29b uxth r3, r3 + 80012a0: 87e3 strh r3, [r4, #62] ; 0x3e + 80012a2: e7ec b.n 800127e + } + } + else + { + /* Timeout management */ + if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout))) + 80012a4: b90e cbnz r6, 80012aa + { + errorcode = HAL_TIMEOUT; + 80012a6: 2003 movs r0, #3 + 80012a8: e01c b.n 80012e4 + } + } + else + { + /* Timeout management */ + if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout))) + 80012aa: 1c73 adds r3, r6, #1 + 80012ac: d0e7 beq.n 800127e + 80012ae: f7ff fbc3 bl 8000a38 + 80012b2: 1bc0 subs r0, r0, r7 + 80012b4: 4286 cmp r6, r0 + 80012b6: d8e2 bhi.n 800127e + 80012b8: e7f5 b.n 80012a6 + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK) + 80012ba: 4620 mov r0, r4 + 80012bc: f7ff ff26 bl 800110c + 80012c0: b108 cbz r0, 80012c6 + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + 80012c2: 2320 movs r3, #32 + 80012c4: 6623 str r3, [r4, #96] ; 0x60 + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + 80012c6: 68a3 ldr r3, [r4, #8] + 80012c8: b933 cbnz r3, 80012d8 + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + 80012ca: 9301 str r3, [sp, #4] + 80012cc: 6823 ldr r3, [r4, #0] + 80012ce: 68da ldr r2, [r3, #12] + 80012d0: 9201 str r2, [sp, #4] + 80012d2: 689b ldr r3, [r3, #8] + 80012d4: 9301 str r3, [sp, #4] + 80012d6: 9b01 ldr r3, [sp, #4] + } + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + 80012d8: 6e20 ldr r0, [r4, #96] ; 0x60 + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + 80012da: 3000 adds r0, #0 + 80012dc: bf18 it ne + 80012de: 2001 movne r0, #1 + 80012e0: e000 b.n 80012e4 + 80012e2: 2002 movs r0, #2 + { + errorcode = HAL_ERROR; + } + +error: + hspi->State = HAL_SPI_STATE_READY; + 80012e4: 2301 movs r3, #1 + 80012e6: f884 305d strb.w r3, [r4, #93] ; 0x5d + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + 80012ea: 2300 movs r3, #0 + 80012ec: f884 305c strb.w r3, [r4, #92] ; 0x5c + return errorcode; + 80012f0: e000 b.n 80012f4 + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + 80012f2: 2002 movs r0, #2 +error: + hspi->State = HAL_SPI_STATE_READY; + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return errorcode; +} + 80012f4: b002 add sp, #8 + 80012f6: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +080012fa : + * @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) +{ + 80012fa: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 80012fe: 461e mov r6, r3 + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + 8001300: f890 305c ldrb.w r3, [r0, #92] ; 0x5c + * @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) +{ + 8001304: f8dd 8020 ldr.w r8, [sp, #32] + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + 8001308: 2b01 cmp r3, #1 + * @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) +{ + 800130a: 4604 mov r4, r0 + 800130c: 460d mov r5, r1 + 800130e: 4617 mov r7, r2 + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + 8001310: f000 80d7 beq.w 80014c2 + 8001314: 2301 movs r3, #1 + 8001316: f880 305c strb.w r3, [r0, #92] ; 0x5c + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + 800131a: f7ff fb8d bl 8000a38 + + tmp = hspi->State; + 800131e: f894 305d ldrb.w r3, [r4, #93] ; 0x5d + tmp1 = hspi->Init.Mode; + 8001322: 6861 ldr r1, [r4, #4] + __HAL_LOCK(hspi); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + tmp = hspi->State; + 8001324: b2db uxtb r3, r3 + tmp1 = hspi->Init.Mode; + + if (!((tmp == HAL_SPI_STATE_READY) || \ + 8001326: 2b01 cmp r3, #1 + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + 8001328: 4681 mov r9, r0 + + tmp = hspi->State; + tmp1 = hspi->Init.Mode; + + if (!((tmp == HAL_SPI_STATE_READY) || \ + 800132a: d00a beq.n 8001342 + 800132c: f5b1 7f82 cmp.w r1, #260 ; 0x104 + 8001330: f040 80bc bne.w 80014ac + ((tmp1 == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp == HAL_SPI_STATE_BUSY_RX)))) + 8001334: 68a2 ldr r2, [r4, #8] + 8001336: 2a00 cmp r2, #0 + 8001338: f040 80b8 bne.w 80014ac + 800133c: 2b04 cmp r3, #4 + 800133e: f040 80b5 bne.w 80014ac + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + 8001342: 2d00 cmp r5, #0 + 8001344: f000 80b4 beq.w 80014b0 + 8001348: 2f00 cmp r7, #0 + 800134a: f000 80b1 beq.w 80014b0 + 800134e: 2e00 cmp r6, #0 + 8001350: f000 80ae beq.w 80014b0 + errorcode = HAL_ERROR; + goto error; + } + + /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */ + if (hspi->State != HAL_SPI_STATE_BUSY_RX) + 8001354: f894 305d ldrb.w r3, [r4, #93] ; 0x5d + hspi->State = HAL_SPI_STATE_BUSY_TX_RX; + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + 8001358: 6427 str r7, [r4, #64] ; 0x40 + errorcode = HAL_ERROR; + goto error; + } + + /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */ + if (hspi->State != HAL_SPI_STATE_BUSY_RX) + 800135a: 2b04 cmp r3, #4 + { + hspi->State = HAL_SPI_STATE_BUSY_TX_RX; + 800135c: bf1c itt ne + 800135e: 2305 movne r3, #5 + 8001360: f884 305d strbne.w r3, [r4, #93] ; 0x5d + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + 8001364: 2300 movs r3, #0 + 8001366: 6623 str r3, [r4, #96] ; 0x60 + hspi->pTxBuffPtr = (uint8_t *)pTxData; + hspi->TxXferCount = Size; + hspi->TxXferSize = Size; + + /*Init field not used in handle to zero */ + hspi->RxISR = NULL; + 8001368: 64e3 str r3, [r4, #76] ; 0x4c + hspi->TxISR = NULL; + 800136a: 6523 str r3, [r4, #80] ; 0x50 + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Set the Rx Fifo threshold */ + if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount > 1U)) + 800136c: 68e3 ldr r3, [r4, #12] + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + hspi->RxXferCount = Size; + 800136e: f8a4 6046 strh.w r6, [r4, #70] ; 0x46 + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Set the Rx Fifo threshold */ + if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount > 1U)) + 8001372: f5b3 6fe0 cmp.w r3, #1792 ; 0x700 + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + hspi->RxXferCount = Size; + hspi->RxXferSize = Size; + 8001376: f8a4 6044 strh.w r6, [r4, #68] ; 0x44 + hspi->pTxBuffPtr = (uint8_t *)pTxData; + 800137a: 63a5 str r5, [r4, #56] ; 0x38 + hspi->TxXferCount = Size; + 800137c: 87e6 strh r6, [r4, #62] ; 0x3e + hspi->TxXferSize = Size; + 800137e: 87a6 strh r6, [r4, #60] ; 0x3c + 8001380: 6823 ldr r3, [r4, #0] + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Set the Rx Fifo threshold */ + if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount > 1U)) + 8001382: d804 bhi.n 800138e + 8001384: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46 + 8001388: b292 uxth r2, r2 + 800138a: 2a01 cmp r2, #1 + 800138c: d903 bls.n 8001396 + { + /* set fiforxthreshold according the reception data length: 16bit */ + CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + 800138e: 685a ldr r2, [r3, #4] + 8001390: f422 5280 bic.w r2, r2, #4096 ; 0x1000 + 8001394: e002 b.n 800139c + } + else + { + /* set fiforxthreshold according the reception data length: 8bit */ + SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + 8001396: 685a ldr r2, [r3, #4] + 8001398: f442 5280 orr.w r2, r2, #4096 ; 0x1000 + 800139c: 605a str r2, [r3, #4] + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + 800139e: 681a ldr r2, [r3, #0] + 80013a0: 0650 lsls r0, r2, #25 + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + 80013a2: bf5e ittt pl + 80013a4: 681a ldrpl r2, [r3, #0] + 80013a6: f042 0240 orrpl.w r2, r2, #64 ; 0x40 + 80013aa: 601a strpl r2, [r3, #0] + } + /* Transmit and Receive data in 8 Bit mode */ + else + { +#endif + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U)) + 80013ac: b119 cbz r1, 80013b6 + 80013ae: 8fe2 ldrh r2, [r4, #62] ; 0x3e + 80013b0: b292 uxth r2, r2 + 80013b2: 2a01 cmp r2, #1 + 80013b4: d112 bne.n 80013dc + { + if (hspi->TxXferCount > 1U) + 80013b6: 8fe2 ldrh r2, [r4, #62] ; 0x3e + 80013b8: b292 uxth r2, r2 + 80013ba: 2a01 cmp r2, #1 + 80013bc: d907 bls.n 80013ce + { + hspi->Instance->DR = *((uint16_t *)pTxData); + 80013be: f835 2b02 ldrh.w r2, [r5], #2 + 80013c2: 60da str r2, [r3, #12] + pTxData += sizeof(uint16_t); + hspi->TxXferCount -= 2U; + 80013c4: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 80013c6: 3b02 subs r3, #2 + 80013c8: b29b uxth r3, r3 + 80013ca: 87e3 strh r3, [r4, #62] ; 0x3e + 80013cc: e006 b.n 80013dc + } + else + { + *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++); + 80013ce: 782a ldrb r2, [r5, #0] + 80013d0: 731a strb r2, [r3, #12] + hspi->TxXferCount--; + 80013d2: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 80013d4: 3b01 subs r3, #1 + 80013d6: b29b uxth r3, r3 + 80013d8: 87e3 strh r3, [r4, #62] ; 0x3e + pTxData += sizeof(uint16_t); + hspi->TxXferCount -= 2U; + } + else + { + *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++); + 80013da: 3501 adds r5, #1 + { + (*(uint8_t *)pRxData++) = *(__IO uint8_t *)&hspi->Instance->DR; + hspi->RxXferCount--; + } + /* Next Data is a Transmission (Tx). Tx is allowed */ + txallowed = 1U; + 80013dc: 2601 movs r6, #1 + { + *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++); + hspi->TxXferCount--; + } + } + while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U)) + 80013de: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 80013e0: b29b uxth r3, r3 + 80013e2: 2b00 cmp r3, #0 + 80013e4: d052 beq.n 800148c + { + /* check TXE flag */ + if (txallowed && (hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))) + 80013e6: b1e6 cbz r6, 8001422 + 80013e8: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 80013ea: b29b uxth r3, r3 + 80013ec: b1c3 cbz r3, 8001420 + 80013ee: 6823 ldr r3, [r4, #0] + 80013f0: 689a ldr r2, [r3, #8] + 80013f2: 0791 lsls r1, r2, #30 + 80013f4: d514 bpl.n 8001420 + { + if (hspi->TxXferCount > 1U) + 80013f6: 8fe2 ldrh r2, [r4, #62] ; 0x3e + 80013f8: b292 uxth r2, r2 + 80013fa: 2a01 cmp r2, #1 + 80013fc: d907 bls.n 800140e + { + hspi->Instance->DR = *((uint16_t *)pTxData); + 80013fe: f835 2b02 ldrh.w r2, [r5], #2 + 8001402: 60da str r2, [r3, #12] + pTxData += sizeof(uint16_t); + hspi->TxXferCount -= 2U; + 8001404: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 8001406: 3b02 subs r3, #2 + 8001408: b29b uxth r3, r3 + 800140a: 87e3 strh r3, [r4, #62] ; 0x3e + 800140c: e006 b.n 800141c + } + else + { + *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++); + 800140e: 782a ldrb r2, [r5, #0] + 8001410: 731a strb r2, [r3, #12] + hspi->TxXferCount--; + 8001412: 8fe3 ldrh r3, [r4, #62] ; 0x3e + 8001414: 3b01 subs r3, #1 + 8001416: b29b uxth r3, r3 + 8001418: 87e3 strh r3, [r4, #62] ; 0x3e + pTxData += sizeof(uint16_t); + hspi->TxXferCount -= 2U; + } + else + { + *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++); + 800141a: 3501 adds r5, #1 + hspi->TxXferCount--; + } + /* Next Data is a reception (Rx). Tx not allowed */ + txallowed = 0U; + 800141c: 2600 movs r6, #0 + 800141e: e000 b.n 8001422 + } + } + while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U)) + { + /* check TXE flag */ + if (txallowed && (hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))) + 8001420: 2601 movs r6, #1 + } +#endif /* USE_SPI_CRC */ + } + + /* Wait until RXNE flag is reset */ + if ((hspi->RxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))) + 8001422: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46 + 8001426: b29b uxth r3, r3 + 8001428: b32b cbz r3, 8001476 + 800142a: 6823 ldr r3, [r4, #0] + 800142c: 689a ldr r2, [r3, #8] + 800142e: 07d2 lsls r2, r2, #31 + 8001430: d521 bpl.n 8001476 + { + if (hspi->RxXferCount > 1U) + 8001432: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46 + 8001436: b292 uxth r2, r2 + 8001438: 2a01 cmp r2, #1 + 800143a: d912 bls.n 8001462 + { + *((uint16_t *)pRxData) = hspi->Instance->DR; + 800143c: 68da ldr r2, [r3, #12] + 800143e: f827 2b02 strh.w r2, [r7], #2 + pRxData += sizeof(uint16_t); + hspi->RxXferCount -= 2U; + 8001442: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46 + 8001446: 3a02 subs r2, #2 + 8001448: b292 uxth r2, r2 + 800144a: f8a4 2046 strh.w r2, [r4, #70] ; 0x46 + if (hspi->RxXferCount <= 1U) + 800144e: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46 + 8001452: b292 uxth r2, r2 + 8001454: 2a01 cmp r2, #1 + 8001456: d80d bhi.n 8001474 + { + /* set fiforxthresold before to switch on 8 bit data size */ + SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + 8001458: 685a ldr r2, [r3, #4] + 800145a: f442 5280 orr.w r2, r2, #4096 ; 0x1000 + 800145e: 605a str r2, [r3, #4] + 8001460: e008 b.n 8001474 + } + } + else + { + (*(uint8_t *)pRxData++) = *(__IO uint8_t *)&hspi->Instance->DR; + 8001462: 7b1b ldrb r3, [r3, #12] + 8001464: 703b strb r3, [r7, #0] + hspi->RxXferCount--; + 8001466: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46 + 800146a: 3b01 subs r3, #1 + 800146c: b29b uxth r3, r3 + 800146e: f8a4 3046 strh.w r3, [r4, #70] ; 0x46 + SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + } + } + else + { + (*(uint8_t *)pRxData++) = *(__IO uint8_t *)&hspi->Instance->DR; + 8001472: 3701 adds r7, #1 + hspi->RxXferCount--; + } + /* Next Data is a Transmission (Tx). Tx is allowed */ + txallowed = 1U; + 8001474: 2601 movs r6, #1 + } + if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout)) + 8001476: f1b8 3fff cmp.w r8, #4294967295 ; 0xffffffff + 800147a: d0b0 beq.n 80013de + 800147c: f7ff fadc bl 8000a38 + 8001480: ebc9 0000 rsb r0, r9, r0 + 8001484: 4580 cmp r8, r0 + 8001486: d8aa bhi.n 80013de + { + errorcode = HAL_TIMEOUT; + 8001488: 2003 movs r0, #3 + 800148a: e012 b.n 80014b2 + { + *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++); + hspi->TxXferCount--; + } + } + while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U)) + 800148c: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46 + 8001490: b29b uxth r3, r3 + 8001492: 2b00 cmp r3, #0 + 8001494: d1a7 bne.n 80013e6 + errorcode = HAL_ERROR; + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK) + 8001496: 4620 mov r0, r4 + 8001498: f7ff fe38 bl 800110c + 800149c: b108 cbz r0, 80014a2 + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + 800149e: 2320 movs r3, #32 + 80014a0: 6623 str r3, [r4, #96] ; 0x60 + } + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + 80014a2: 6e20 ldr r0, [r4, #96] ; 0x60 + tmp1 = hspi->Init.Mode; + + if (!((tmp == HAL_SPI_STATE_READY) || \ + ((tmp1 == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp == HAL_SPI_STATE_BUSY_RX)))) + { + errorcode = HAL_BUSY; + 80014a4: 3000 adds r0, #0 + 80014a6: bf18 it ne + 80014a8: 2001 movne r0, #1 + 80014aa: e002 b.n 80014b2 + 80014ac: 2002 movs r0, #2 + 80014ae: e000 b.n 80014b2 + goto error; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + 80014b0: 2001 movs r0, #1 + { + errorcode = HAL_ERROR; + } + +error : + hspi->State = HAL_SPI_STATE_READY; + 80014b2: 2301 movs r3, #1 + 80014b4: f884 305d strb.w r3, [r4, #93] ; 0x5d + __HAL_UNLOCK(hspi); + 80014b8: 2300 movs r3, #0 + 80014ba: f884 305c strb.w r3, [r4, #92] ; 0x5c + 80014be: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + 80014c2: 2002 movs r0, #2 + +error : + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return errorcode; +} + 80014c4: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + +080014c8 : + * @param Size: amount of data to be received + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + 80014c8: e92d 41ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr} + 80014cc: 461e mov r6, r3 +#endif /* USE_SPI_CRC */ + uint32_t tickstart = 0U; + HAL_StatusTypeDef errorcode = HAL_OK; + + + if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES)) + 80014ce: 6843 ldr r3, [r0, #4] + 80014d0: f5b3 7f82 cmp.w r3, #260 ; 0x104 + * @param Size: amount of data to be received + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + 80014d4: 4604 mov r4, r0 + 80014d6: 460d mov r5, r1 + 80014d8: 4690 mov r8, r2 +#endif /* USE_SPI_CRC */ + uint32_t tickstart = 0U; + HAL_StatusTypeDef errorcode = HAL_OK; + + + if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES)) + 80014da: d10a bne.n 80014f2 + 80014dc: 6883 ldr r3, [r0, #8] + 80014de: b943 cbnz r3, 80014f2 + { + hspi->State = HAL_SPI_STATE_BUSY_RX; + 80014e0: 2304 movs r3, #4 + 80014e2: f880 305d strb.w r3, [r0, #93] ; 0x5d + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout); + 80014e6: 4613 mov r3, r2 + 80014e8: 9600 str r6, [sp, #0] + 80014ea: 460a mov r2, r1 + 80014ec: f7ff ff05 bl 80012fa + 80014f0: e093 b.n 800161a + } + + /* Process Locked */ + __HAL_LOCK(hspi); + 80014f2: f894 305c ldrb.w r3, [r4, #92] ; 0x5c + 80014f6: 2b01 cmp r3, #1 + 80014f8: d073 beq.n 80015e2 + 80014fa: 2301 movs r3, #1 + 80014fc: f884 305c strb.w r3, [r4, #92] ; 0x5c + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + 8001500: f7ff fa9a bl 8000a38 + 8001504: 4607 mov r7, r0 + + if (hspi->State != HAL_SPI_STATE_READY) + 8001506: f894 005d ldrb.w r0, [r4, #93] ; 0x5d + 800150a: b2c0 uxtb r0, r0 + 800150c: 2801 cmp r0, #1 + 800150e: d160 bne.n 80015d2 + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pData == NULL) || (Size == 0U)) + 8001510: 2d00 cmp r5, #0 + 8001512: d05f beq.n 80015d4 + 8001514: f1b8 0f00 cmp.w r8, #0 + 8001518: d05c beq.n 80015d4 + errorcode = HAL_ERROR; + goto error; + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + 800151a: 2304 movs r3, #4 + 800151c: f884 305d strb.w r3, [r4, #93] ; 0x5d + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + 8001520: 2100 movs r1, #0 + 8001522: 6822 ldr r2, [r4, #0] + hspi->RxXferCount--; + } +#endif /* USE_SPI_CRC */ + + /* Set the Rx Fifo threshold */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + 8001524: 68e3 ldr r3, [r4, #12] + goto error; + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + 8001526: 6621 str r1, [r4, #96] ; 0x60 + hspi->pRxBuffPtr = (uint8_t *)pData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + 8001528: f8a4 8046 strh.w r8, [r4, #70] ; 0x46 + + /*Init field not used in handle to zero */ + hspi->pTxBuffPtr = (uint8_t *)NULL; + hspi->TxXferSize = 0U; + hspi->TxXferCount = 0U; + 800152c: 87e1 strh r1, [r4, #62] ; 0x3e + hspi->RxXferCount--; + } +#endif /* USE_SPI_CRC */ + + /* Set the Rx Fifo threshold */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + 800152e: f5b3 6fe0 cmp.w r3, #1792 ; 0x700 + { + /* set fiforxthresold according the reception data length: 16bit */ + CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + 8001532: 6853 ldr r3, [r2, #4] + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pData; + 8001534: 6425 str r5, [r4, #64] ; 0x40 + + /* Set the Rx Fifo threshold */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + { + /* set fiforxthresold according the reception data length: 16bit */ + CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + 8001536: bf8c ite hi + 8001538: f423 5380 bichi.w r3, r3, #4096 ; 0x1000 + } + else + { + /* set fiforxthresold according the reception data length: 8bit */ + SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + 800153c: f443 5380 orrls.w r3, r3, #4096 ; 0x1000 + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pData; + hspi->RxXferSize = Size; + 8001540: f8a4 8044 strh.w r8, [r4, #68] ; 0x44 + hspi->RxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->pTxBuffPtr = (uint8_t *)NULL; + 8001544: 63a1 str r1, [r4, #56] ; 0x38 + hspi->TxXferSize = 0U; + 8001546: 87a1 strh r1, [r4, #60] ; 0x3c + hspi->TxXferCount = 0U; + hspi->RxISR = NULL; + 8001548: 64e1 str r1, [r4, #76] ; 0x4c + hspi->TxISR = NULL; + 800154a: 6521 str r1, [r4, #80] ; 0x50 + CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + } + else + { + /* set fiforxthresold according the reception data length: 8bit */ + SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD); + 800154c: 6053 str r3, [r2, #4] + } + + /* Configure communication direction: 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + 800154e: 68a3 ldr r3, [r4, #8] + 8001550: f5b3 4f00 cmp.w r3, #32768 ; 0x8000 + { + SPI_1LINE_RX(hspi); + 8001554: bf02 ittt eq + 8001556: 6813 ldreq r3, [r2, #0] + 8001558: f423 4380 biceq.w r3, r3, #16384 ; 0x4000 + 800155c: 6013 streq r3, [r2, #0] + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + 800155e: 6813 ldr r3, [r2, #0] + 8001560: 0658 lsls r0, r3, #25 + 8001562: d410 bmi.n 8001586 + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + 8001564: 6813 ldr r3, [r2, #0] + 8001566: f043 0340 orr.w r3, r3, #64 ; 0x40 + 800156a: 6013 str r3, [r2, #0] + 800156c: e00b b.n 8001586 +#endif + /* Transfer loop */ + while (hspi->RxXferCount > 0U) + { + /* Check the RXNE flag */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) + 800156e: 6893 ldr r3, [r2, #8] + 8001570: 07d9 lsls r1, r3, #31 + 8001572: d50f bpl.n 8001594 + { + /* read the received data */ + (* (uint8_t *)pData) = *(__IO uint8_t *)&hspi->Instance->DR; + 8001574: 7b13 ldrb r3, [r2, #12] + 8001576: f805 3b01 strb.w r3, [r5], #1 + pData += sizeof(uint8_t); + hspi->RxXferCount--; + 800157a: f8b4 2046 ldrh.w r2, [r4, #70] ; 0x46 + 800157e: 3a01 subs r2, #1 + 8001580: b292 uxth r2, r2 + 8001582: f8a4 2046 strh.w r2, [r4, #70] ; 0x46 +#if 0 + if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT) + { +#endif + /* Transfer loop */ + while (hspi->RxXferCount > 0U) + 8001586: f8b4 3046 ldrh.w r3, [r4, #70] ; 0x46 + 800158a: 6822 ldr r2, [r4, #0] + 800158c: b29b uxth r3, r3 + 800158e: 2b00 cmp r3, #0 + 8001590: d1ed bne.n 800156e + 8001592: e00a b.n 80015aa + hspi->RxXferCount--; + } + else + { + /* Timeout management */ + if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout))) + 8001594: b90e cbnz r6, 800159a + { + errorcode = HAL_TIMEOUT; + 8001596: 2003 movs r0, #3 + 8001598: e01c b.n 80015d4 + hspi->RxXferCount--; + } + else + { + /* Timeout management */ + if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout))) + 800159a: 1c73 adds r3, r6, #1 + 800159c: d0f3 beq.n 8001586 + 800159e: f7ff fa4b bl 8000a38 + 80015a2: 1bc0 subs r0, r0, r7 + 80015a4: 4286 cmp r6, r0 + 80015a6: d8ee bhi.n 8001586 + 80015a8: e7f5 b.n 8001596 + * @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) + 80015aa: 6861 ldr r1, [r4, #4] + 80015ac: f5b1 7f82 cmp.w r1, #260 ; 0x104 + 80015b0: d10a bne.n 80015c8 + 80015b2: 68a3 ldr r3, [r4, #8] + 80015b4: f5b3 4f00 cmp.w r3, #32768 ; 0x8000 + 80015b8: d002 beq.n 80015c0 + || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))) + 80015ba: f5b3 6f80 cmp.w r3, #1024 ; 0x400 + 80015be: d103 bne.n 80015c8 + { + /* Disable SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + 80015c0: 6813 ldr r3, [r2, #0] + 80015c2: f023 0340 bic.w r3, r3, #64 ; 0x40 + 80015c6: 6013 str r3, [r2, #0] + * @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) + 80015c8: 6893 ldr r3, [r2, #8] + 80015ca: f003 0380 and.w r3, r3, #128 ; 0x80 + 80015ce: b153 cbz r3, 80015e6 + 80015d0: e7fa b.n 80015c8 + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + 80015d2: 2002 movs r0, #2 + { + errorcode = HAL_ERROR; + } + +error : + hspi->State = HAL_SPI_STATE_READY; + 80015d4: 2301 movs r3, #1 + 80015d6: f884 305d strb.w r3, [r4, #93] ; 0x5d + __HAL_UNLOCK(hspi); + 80015da: 2300 movs r3, #0 + 80015dc: f884 305c strb.w r3, [r4, #92] ; 0x5c + return errorcode; + 80015e0: e01b b.n 800161a + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout); + } + + /* Process Locked */ + __HAL_LOCK(hspi); + 80015e2: 2002 movs r0, #2 + 80015e4: e019 b.n 800161a + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + + if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE) + 80015e6: f5b1 7f82 cmp.w r1, #260 ; 0x104 + 80015ea: d106 bne.n 80015fa + 80015ec: 68a3 ldr r3, [r4, #8] + 80015ee: f5b3 4f00 cmp.w r3, #32768 ; 0x8000 + 80015f2: d007 beq.n 8001604 + || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))) + 80015f4: f5b3 6f80 cmp.w r3, #1024 ; 0x400 + 80015f8: d004 beq.n 8001604 + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } +#endif /* USE_SPI_CRC */ + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + 80015fa: 6e20 ldr r0, [r4, #96] ; 0x60 + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + 80015fc: 3000 adds r0, #0 + 80015fe: bf18 it ne + 8001600: 2001 movne r0, #1 + 8001602: e7e7 b.n 80015d4 +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) + 8001604: 6893 ldr r3, [r2, #8] + 8001606: f413 6fc0 tst.w r3, #1536 ; 0x600 + 800160a: d0f6 beq.n 80015fa + { + if ((Fifo == SPI_SR_FRLVL) && (State == SPI_FRLVL_EMPTY)) + { + tmpreg = *((__IO uint8_t *)&hspi->Instance->DR); + 800160c: 7b13 ldrb r3, [r2, #12] + 800160e: b2db uxtb r3, r3 + 8001610: f88d 300f strb.w r3, [sp, #15] + /* To avoid GCC warning */ + UNUSED(tmpreg); + 8001614: f89d 300f ldrb.w r3, [sp, #15] + 8001618: e7f4 b.n 8001604 + +error : + hspi->State = HAL_SPI_STATE_READY; + __HAL_UNLOCK(hspi); + return errorcode; +} + 800161a: b004 add sp, #16 + 800161c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +08001620 : + +// checksum_more() +// + static void +checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len) +{ + 8001620: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + // do a nice progress bar as it works. + while(len) { + int here = MIN(len, 8196); + int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN; + + oled_show_progress(screen_verify, percent); + 8001624: f8df a054 ldr.w sl, [pc, #84] ; 800167c + +// checksum_more() +// + static void +checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len) +{ + 8001628: 4680 mov r8, r0 + 800162a: 460e mov r6, r1 + 800162c: 4617 mov r7, r2 + 800162e: 461c mov r4, r3 + // do a nice progress bar as it works. + while(len) { + int here = MIN(len, 8196); + 8001630: f242 0904 movw r9, #8196 ; 0x2004 +// + static void +checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len) +{ + // do a nice progress bar as it works. + while(len) { + 8001634: b1f4 cbz r4, 8001674 + int here = MIN(len, 8196); + int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN; + + oled_show_progress(screen_verify, percent); + 8001636: 6831 ldr r1, [r6, #0] + 8001638: 480f ldr r0, [pc, #60] ; (8001678 ) + static void +checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len) +{ + // do a nice progress bar as it works. + while(len) { + int here = MIN(len, 8196); + 800163a: 454c cmp r4, r9 + int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN; + + oled_show_progress(screen_verify, percent); + 800163c: f04f 0364 mov.w r3, #100 ; 0x64 + static void +checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len) +{ + // do a nice progress bar as it works. + while(len) { + int here = MIN(len, 8196); + 8001640: 4625 mov r5, r4 + int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN; + + oled_show_progress(screen_verify, percent); + 8001642: fb03 f101 mul.w r1, r3, r1 + static void +checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len) +{ + // do a nice progress bar as it works. + while(len) { + int here = MIN(len, 8196); + 8001646: bfa8 it ge + 8001648: 464d movge r5, r9 + int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN; + + oled_show_progress(screen_verify, percent); + 800164a: fbb1 f1fa udiv r1, r1, sl + 800164e: f7ff fb33 bl 8000cb8 + sha256_update(ctx, addr, here); + 8001652: 4639 mov r1, r7 + 8001654: 462a mov r2, r5 + 8001656: 4640 mov r0, r8 + 8001658: f003 fec2 bl 80053e0 + + *total += here; + 800165c: 6833 ldr r3, [r6, #0] + 800165e: 442b add r3, r5 + 8001660: 6033 str r3, [r6, #0] + addr += here; + 8001662: 442f add r7, r5 + len -= here; + 8001664: 1b64 subs r4, r4, r5 + + if(dfu_button_pressed()) dfu_by_request(); + 8001666: f001 fcbb bl 8002fe0 + 800166a: 2800 cmp r0, #0 + 800166c: d0e2 beq.n 8001634 + 800166e: f7fe ff4b bl 8000508 + 8001672: e7df b.n 8001634 + } +} + 8001674: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 8001678: 08006ab6 .word 0x08006ab6 + 800167c: 0010741c .word 0x0010741c + +08001680 : + +// checksum_flash() +// + void +checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32]) +{ + 8001680: b570 push {r4, r5, r6, lr} + 8001682: b0a6 sub sp, #152 ; 0x98 + 8001684: 4606 mov r6, r0 + const uint8_t *start = (const uint8_t *)FIRMWARE_START; + + SHA256_CTX ctx; + uint32_t total_len = 0; + 8001686: 2300 movs r3, #0 + uint8_t first[32]; + + sha256_init(&ctx); + 8001688: a80a add r0, sp, #40 ; 0x28 + // start of firmware (just after we end) to header + checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64); + + // from after header to end + checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE, + FW_HDR->firmware_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE)); + 800168a: 4d3d ldr r5, [pc, #244] ; (8001780 ) +checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32]) +{ + const uint8_t *start = (const uint8_t *)FIRMWARE_START; + + SHA256_CTX ctx; + uint32_t total_len = 0; + 800168c: 9301 str r3, [sp, #4] + +// checksum_flash() +// + void +checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32]) +{ + 800168e: 460c mov r4, r1 + + SHA256_CTX ctx; + uint32_t total_len = 0; + uint8_t first[32]; + + sha256_init(&ctx); + 8001690: f003 fe7c bl 800538c + + // start of firmware (just after we end) to header + checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64); + 8001694: f44f 537f mov.w r3, #16320 ; 0x3fc0 + 8001698: 4a3a ldr r2, [pc, #232] ; (8001784 ) + 800169a: a901 add r1, sp, #4 + 800169c: a80a add r0, sp, #40 ; 0x28 + 800169e: f7ff ffbf bl 8001620 + + // from after header to end + checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE, + 80016a2: 69ab ldr r3, [r5, #24] + 80016a4: 4a38 ldr r2, [pc, #224] ; (8001788 ) + 80016a6: f5a3 4380 sub.w r3, r3, #16384 ; 0x4000 + 80016aa: a901 add r1, sp, #4 + 80016ac: a80a add r0, sp, #40 ; 0x28 + 80016ae: f7ff ffb7 bl 8001620 + FW_HDR->firmware_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE)); + + sha256_final(&ctx, first); + 80016b2: a902 add r1, sp, #8 + 80016b4: a80a add r0, sp, #40 ; 0x28 + 80016b6: f003 feb1 bl 800541c + + // double SHA256 + sha256_init(&ctx); + 80016ba: a80a add r0, sp, #40 ; 0x28 + 80016bc: f003 fe66 bl 800538c + sha256_update(&ctx, first, sizeof(first)); + 80016c0: 2220 movs r2, #32 + 80016c2: a902 add r1, sp, #8 + 80016c4: a80a add r0, sp, #40 ; 0x28 + 80016c6: f003 fe8b bl 80053e0 + sha256_final(&ctx, fw_digest); + 80016ca: 4631 mov r1, r6 + 80016cc: a80a add r0, sp, #40 ; 0x28 + 80016ce: f003 fea5 bl 800541c + + // start over, and get the rest of flash. All of it. + sha256_init(&ctx); + 80016d2: a80a add r0, sp, #40 ; 0x28 + 80016d4: f003 fe5a bl 800538c + + // .. and chain in what we have so far + sha256_update(&ctx, fw_digest, 32); + 80016d8: 2220 movs r2, #32 + 80016da: 4631 mov r1, r6 + 80016dc: a80a add r0, sp, #40 ; 0x28 + 80016de: f003 fe7f bl 80053e0 + + // bootloader, including pairing secret area. + const uint8_t *base = (const uint8_t *)BL_FLASH_BASE; + checksum_more(&ctx, &total_len, base, start-base); + 80016e2: f44f 4300 mov.w r3, #32768 ; 0x8000 + 80016e6: f04f 6200 mov.w r2, #134217728 ; 0x8000000 + 80016ea: a901 add r1, sp, #4 + 80016ec: a80a add r0, sp, #40 ; 0x28 + 80016ee: f7ff ff97 bl 8001620 + + // probably-blank area after firmware, and filesystem area + const uint8_t *fs = start + FW_HDR->firmware_length; + 80016f2: 69aa ldr r2, [r5, #24] + 80016f4: f102 6200 add.w r2, r2, #134217728 ; 0x8000000 + 80016f8: f502 4200 add.w r2, r2, #32768 ; 0x8000 + const uint8_t *last = base + MAIN_FLASH_SIZE; + checksum_more(&ctx, &total_len, fs, last-fs); + 80016fc: f1c2 6301 rsb r3, r2, #135266304 ; 0x8100000 + 8001700: a901 add r1, sp, #4 + 8001702: a80a add r0, sp, #40 ; 0x28 + 8001704: f7ff ff8c bl 8001620 + + // OTP area + checksum_more(&ctx, &total_len, (void *)0x1fff7000, 0x400); + 8001708: f44f 6380 mov.w r3, #1024 ; 0x400 + 800170c: 4a1f ldr r2, [pc, #124] ; (800178c ) + 800170e: a901 add r1, sp, #4 + 8001710: a80a add r0, sp, #40 ; 0x28 + 8001712: f7ff ff85 bl 8001620 + + // "just in case" ... the option bytes (2 banks) + checksum_more(&ctx, &total_len, (void *)0x1fff7800, 0x28); + 8001716: 2328 movs r3, #40 ; 0x28 + 8001718: eb0d 0003 add.w r0, sp, r3 + 800171c: 4a1c ldr r2, [pc, #112] ; (8001790 ) + 800171e: a901 add r1, sp, #4 + 8001720: f7ff ff7e bl 8001620 + checksum_more(&ctx, &total_len, (void *)0x1ffff800, 0x28); + 8001724: 2328 movs r3, #40 ; 0x28 + 8001726: eb0d 0003 add.w r0, sp, r3 + 800172a: 4a1a ldr r2, [pc, #104] ; (8001794 ) + 800172c: a901 add r1, sp, #4 + 800172e: f7ff ff77 bl 8001620 + + // System ROM (they say it can't change, but clearly + // implemented as flash cells) + checksum_more(&ctx, &total_len, (void *)0x1fff0000, 0x7000); + 8001732: f44f 43e0 mov.w r3, #28672 ; 0x7000 + 8001736: 4a18 ldr r2, [pc, #96] ; (8001798 ) + 8001738: a901 add r1, sp, #4 + 800173a: a80a add r0, sp, #40 ; 0x28 + 800173c: f7ff ff70 bl 8001620 + + // device serial number, just for kicks + checksum_more(&ctx, &total_len, (void *)0x1fff7590, 12); + 8001740: 230c movs r3, #12 + 8001742: 4a16 ldr r2, [pc, #88] ; (800179c ) + 8001744: a901 add r1, sp, #4 + 8001746: a80a add r0, sp, #40 ; 0x28 + 8001748: f7ff ff6a bl 8001620 + + ASSERT(total_len == TOTAL_CHECKSUM_LEN); + 800174c: 9a01 ldr r2, [sp, #4] + 800174e: 4b14 ldr r3, [pc, #80] ; (80017a0 ) + 8001750: 429a cmp r2, r3 + 8001752: d002 beq.n 800175a + 8001754: 4813 ldr r0, [pc, #76] ; (80017a4 ) + 8001756: f7fe fe39 bl 80003cc + + sha256_final(&ctx, world_digest); + 800175a: 4621 mov r1, r4 + 800175c: a80a add r0, sp, #40 ; 0x28 + 800175e: f003 fe5d bl 800541c + + // double SHA256 (a bitcoin fetish) + sha256_init(&ctx); + 8001762: a80a add r0, sp, #40 ; 0x28 + 8001764: f003 fe12 bl 800538c + sha256_update(&ctx, world_digest, 32); + 8001768: 2220 movs r2, #32 + 800176a: 4621 mov r1, r4 + 800176c: a80a add r0, sp, #40 ; 0x28 + 800176e: f003 fe37 bl 80053e0 + sha256_final(&ctx, world_digest); + 8001772: 4621 mov r1, r4 + 8001774: a80a add r0, sp, #40 ; 0x28 + 8001776: f003 fe51 bl 800541c +} + 800177a: b026 add sp, #152 ; 0x98 + 800177c: bd70 pop {r4, r5, r6, pc} + 800177e: bf00 nop + 8001780: 0800bf80 .word 0x0800bf80 + 8001784: 08008000 .word 0x08008000 + 8001788: 0800c000 .word 0x0800c000 + 800178c: 1fff7000 .word 0x1fff7000 + 8001790: 1fff7800 .word 0x1fff7800 + 8001794: 1ffff800 .word 0x1ffff800 + 8001798: 1fff0000 .word 0x1fff0000 + 800179c: 1fff7590 .word 0x1fff7590 + 80017a0: 0010741c .word 0x0010741c + 80017a4: 08006940 .word 0x08006940 + +080017a8 : +// 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]) +{ + 80017a8: b570 push {r4, r5, r6, lr} + const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE; + + memset(min_version, 0, 8); + 80017aa: 2300 movs r3, #0 +// we can allow. All zeros if any if okay. +// + void +get_min_version(uint8_t min_version[8]) +{ + const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE; + 80017ac: 4c0b ldr r4, [pc, #44] ; (80017dc ) + + memset(min_version, 0, 8); + + for(int i=0; i) + void +get_min_version(uint8_t min_version[8]) +{ + const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE; + + memset(min_version, 0, 8); + 80017b0: 6003 str r3, [r0, #0] +// 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]) +{ + 80017b2: 4605 mov r5, r0 + const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE; + + memset(min_version, 0, 8); + 80017b4: 6043 str r3, [r0, #4] + // is it programmed? + if(otp[0] == 0xff) continue; + + // is it a timestamp value? + if(otp[0] >= 0x40) continue; + if(otp[0] < 0x10) continue; + 80017b6: 7823 ldrb r3, [r4, #0] + 80017b8: 3b10 subs r3, #16 + 80017ba: 2b2f cmp r3, #47 ; 0x2f + 80017bc: d80a bhi.n 80017d4 + + if(memcmp(otp, min_version, 8) > 0) { + 80017be: 4629 mov r1, r5 + 80017c0: 2208 movs r2, #8 + 80017c2: 4620 mov r0, r4 + 80017c4: f005 f84f bl 8006866 + 80017c8: 2800 cmp r0, #0 + memcpy(min_version, otp, 8); + 80017ca: bfc1 itttt gt + 80017cc: 4623 movgt r3, r4 + 80017ce: cb03 ldmiagt r3!, {r0, r1} + 80017d0: 6028 strgt r0, [r5, #0] + 80017d2: 6069 strgt r1, [r5, #4] +{ + const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE; + + memset(min_version, 0, 8); + + for(int i=0; i + + if(memcmp(otp, min_version, 8) > 0) { + memcpy(min_version, otp, 8); + } + } +} + 80017da: bd70 pop {r4, r5, r6, pc} + 80017dc: 1fff7000 .word 0x1fff7000 + 80017e0: 1fff7400 .word 0x1fff7400 + +080017e4 : + +// check_is_downgrade() +// + bool +check_is_downgrade(const uint8_t timestamp[8]) +{ + 80017e4: b513 push {r0, r1, r4, lr} + 80017e6: 4604 mov r4, r0 + // look at FW_HDR->timestamp and compare to a growing list in main flash OTP + uint8_t min[8]; + + get_min_version(min); + 80017e8: 4668 mov r0, sp + 80017ea: f7ff ffdd bl 80017a8 + + return (memcmp(timestamp, min, 8) < 0); + 80017ee: 2208 movs r2, #8 + 80017f0: 4669 mov r1, sp + 80017f2: 4620 mov r0, r4 + 80017f4: f005 f837 bl 8006866 +} + 80017f8: 0fc0 lsrs r0, r0, #31 + 80017fa: b002 add sp, #8 + 80017fc: bd10 pop {r4, pc} + ... + +08001800 : + +// check_factory_key() +// + void +check_factory_key(uint32_t pubkey_num) +{ + 8001800: b510 push {r4, lr} + if(IS_FACTORY_KEY(pubkey_num)) return; + 8001802: b950 cbnz r0, 800181a + 8001804: 4604 mov r4, r0 +#else + const int wait = 10; +#endif + + for(int i=0; i < wait; i++) { + oled_show_progress(screen_devmode, (i*100)/wait); + 8001806: 4621 mov r1, r4 + 8001808: 4804 ldr r0, [pc, #16] ; (800181c ) + 800180a: f7ff fa55 bl 8000cb8 + const int wait = 100; +#else + const int wait = 10; +#endif + + for(int i=0; i < wait; i++) { + 800180e: 3401 adds r4, #1 + oled_show_progress(screen_devmode, (i*100)/wait); + + delay_ms(250); + 8001810: 20fa movs r0, #250 ; 0xfa + 8001812: f001 fb85 bl 8002f20 + const int wait = 100; +#else + const int wait = 10; +#endif + + for(int i=0; i < wait; i++) { + 8001816: 2c64 cmp r4, #100 ; 0x64 + 8001818: d1f5 bne.n 8001806 + 800181a: bd10 pop {r4, pc} + 800181c: 08006da5 .word 0x08006da5 + +08001820 : +// verify_header() +// + bool +verify_header(const coldcardFirmwareHeader_t *hdr) +{ + if(hdr->magic_value != FW_HEADER_MAGIC) goto fail; + 8001820: 6802 ldr r2, [r0, #0] + 8001822: 4b0c ldr r3, [pc, #48] ; (8001854 ) + 8001824: 429a cmp r2, r3 + 8001826: d112 bne.n 800184e + if(hdr->version_string[0] == 0x0) goto fail; + 8001828: 7b03 ldrb r3, [r0, #12] + 800182a: b173 cbz r3, 800184a + if(hdr->timestamp[0] >= 0x40) goto fail; // 22 yr product lifetime + 800182c: 7903 ldrb r3, [r0, #4] + 800182e: 2b3f cmp r3, #63 ; 0x3f + 8001830: d80d bhi.n 800184e + if(hdr->firmware_length < FW_MIN_LENGTH) goto fail; + 8001832: 6983 ldr r3, [r0, #24] + 8001834: f5a3 2380 sub.w r3, r3, #262144 ; 0x40000 + 8001838: f5b3 2f38 cmp.w r3, #753664 ; 0xb8000 + 800183c: d807 bhi.n 800184e + if(hdr->firmware_length > FW_MAX_LENGTH) goto fail; + if(hdr->pubkey_num >= NUM_KNOWN_PUBKEYS) goto fail; + 800183e: 6940 ldr r0, [r0, #20] + 8001840: 2805 cmp r0, #5 + 8001842: bf8c ite hi + 8001844: 2000 movhi r0, #0 + 8001846: 2001 movls r0, #1 + 8001848: 4770 bx lr + + return true; +fail: + return false; + 800184a: 4618 mov r0, r3 + 800184c: 4770 bx lr + 800184e: 2000 movs r0, #0 +} + 8001850: 4770 bx lr + 8001852: bf00 nop + 8001854: cc001234 .word 0xcc001234 + +08001858 : +// +// Given double-sha256 over the firmware bytes, check the signature. +// + bool +verify_signature(const coldcardFirmwareHeader_t *hdr, const uint8_t fw_check[32]) +{ + 8001858: b573 push {r0, r1, r4, r5, r6, lr} + int ok = uECC_verify(approved_pubkeys[hdr->pubkey_num], fw_check, 32, + 800185a: 4a0a ldr r2, [pc, #40] ; (8001884 ) + 800185c: 6944 ldr r4, [r0, #20] +// +// Given double-sha256 over the firmware bytes, check the signature. +// + bool +verify_signature(const coldcardFirmwareHeader_t *hdr, const uint8_t fw_check[32]) +{ + 800185e: 4605 mov r5, r0 + int ok = uECC_verify(approved_pubkeys[hdr->pubkey_num], fw_check, 32, + 8001860: eb02 1484 add.w r4, r2, r4, lsl #6 +// +// Given double-sha256 over the firmware bytes, check the signature. +// + bool +verify_signature(const coldcardFirmwareHeader_t *hdr, const uint8_t fw_check[32]) +{ + 8001864: 460e mov r6, r1 + int ok = uECC_verify(approved_pubkeys[hdr->pubkey_num], fw_check, 32, + 8001866: f004 fc9f bl 80061a8 + 800186a: f105 0340 add.w r3, r5, #64 ; 0x40 + 800186e: 9000 str r0, [sp, #0] + 8001870: 2220 movs r2, #32 + 8001872: 4631 mov r1, r6 + 8001874: 4620 mov r0, r4 + 8001876: f004 fe35 bl 80064e4 + hdr->signature, uECC_secp256k1()); + return ok; +} + 800187a: 3000 adds r0, #0 + 800187c: bf18 it ne + 800187e: 2001 movne r0, #1 + 8001880: b002 add sp, #8 + 8001882: bd70 pop {r4, r5, r6, pc} + 8001884: 08007090 .word 0x08007090 + +08001888 : + +// verify_firmware() +// + void +verify_firmware(void) +{ + 8001888: b510 push {r4, lr} + STATIC_ASSERT(sizeof(coldcardFirmwareHeader_t) == FW_HEADER_SIZE); + + // watch for unprogrammed header. and some + if(FW_HDR->version_string[0] == 0xff) goto blank; + 800188a: 4c13 ldr r4, [pc, #76] ; (80018d8 ) + 800188c: 7b23 ldrb r3, [r4, #12] + 800188e: 2bff cmp r3, #255 ; 0xff + +// verify_firmware() +// + void +verify_firmware(void) +{ + 8001890: b090 sub sp, #64 ; 0x40 + STATIC_ASSERT(sizeof(coldcardFirmwareHeader_t) == FW_HEADER_SIZE); + + // watch for unprogrammed header. and some + if(FW_HDR->version_string[0] == 0xff) goto blank; + 8001892: d01a beq.n 80018ca + if(!verify_header(FW_HDR)) goto fail; + 8001894: 4620 mov r0, r4 + 8001896: f7ff ffc3 bl 8001820 + 800189a: b1a0 cbz r0, 80018c6 + + // measure checksum + uint8_t fw_check[32], world_check[32]; + checksum_flash(fw_check, world_check); + 800189c: a908 add r1, sp, #32 + 800189e: 4668 mov r0, sp + 80018a0: f7ff feee bl 8001680 + + // Verify the signature + // - use pubkey_num to pick a specific key + if(!verify_signature(FW_HDR, fw_check)) goto fail; + 80018a4: 4669 mov r1, sp + 80018a6: 4620 mov r0, r4 + 80018a8: f7ff ffd6 bl 8001858 + 80018ac: b158 cbz r0, 80018c6 + + // Push the hash to the 508a which might make the Genuine light green, + // but only if we arrived at same hash before. It decides. + int not_green = ae_set_gpio_secure(world_check); + 80018ae: a808 add r0, sp, #32 + 80018b0: f001 f9b8 bl 8002c24 + + // maybe show big warning if not an "approved" key + if(not_green) { + 80018b4: b110 cbz r0, 80018bc + check_factory_key(FW_HDR->pubkey_num); + 80018b6: 6960 ldr r0, [r4, #20] + 80018b8: f7ff ffa2 bl 8001800 + } + + oled_show_progress(screen_verify, 100); + 80018bc: 2164 movs r1, #100 ; 0x64 + 80018be: 4807 ldr r0, [pc, #28] ; (80018dc ) + 80018c0: f7ff f9fa bl 8000cb8 + + return; + 80018c4: e006 b.n 80018d4 + +fail: + oled_show(screen_corrupt); + 80018c6: 4806 ldr r0, [pc, #24] ; (80018e0 ) + 80018c8: e000 b.n 80018cc + enter_dfu(); + return; + +blank: + oled_show(screen_dfu); + 80018ca: 4806 ldr r0, [pc, #24] ; (80018e4 ) + 80018cc: f7ff f9b4 bl 8000c38 + enter_dfu(); + 80018d0: f7fe fdca bl 8000468 + return; +} + 80018d4: b010 add sp, #64 ; 0x40 + 80018d6: bd10 pop {r4, pc} + 80018d8: 0800bf80 .word 0x0800bf80 + 80018dc: 08006ab6 .word 0x08006ab6 + 80018e0: 08006fd1 .word 0x08006fd1 + 80018e4: 08006ca3 .word 0x08006ca3 + +080018e8 : + void +systick_setup(void) +{ + const uint32_t ticks = HCLK_FREQUENCY/1000; + + SysTick->LOAD = (ticks - 1); + 80018e8: 4b03 ldr r3, [pc, #12] ; (80018f8 ) + 80018ea: 4a04 ldr r2, [pc, #16] ; (80018fc ) + 80018ec: 605a str r2, [r3, #4] + SysTick->VAL = 0; + 80018ee: 2200 movs r2, #0 + 80018f0: 609a str r2, [r3, #8] + SysTick->CTRL = SYSTICK_CLKSOURCE_HCLK | SysTick_CTRL_ENABLE_Msk; + 80018f2: 2205 movs r2, #5 + 80018f4: 601a str r2, [r3, #0] + 80018f6: 4770 bx lr + 80018f8: e000e010 .word 0xe000e010 + 80018fc: 0001387f .word 0x0001387f + +08001900 : + +// clocks_setup() +// + void +clocks_setup(void) +{ + 8001900: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + + // Configure LSE Drive Capability + __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); + 8001904: 4d2b ldr r5, [pc, #172] ; (80019b4 ) + 8001906: f8d5 3090 ldr.w r3, [r5, #144] ; 0x90 + +// clocks_setup() +// + void +clocks_setup(void) +{ + 800190a: b0b9 sub sp, #228 ; 0xe4 + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + + // Configure LSE Drive Capability + __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); + 800190c: f023 0318 bic.w r3, r3, #24 + 8001910: f8c5 3090 str.w r3, [r5, #144] ; 0x90 + + // Enable HSE Oscillator and activate PLL with HSE as source + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + 8001914: 2301 movs r3, #1 + 8001916: 9305 str r3, [sp, #20] + + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + 8001918: f44f 3380 mov.w r3, #65536 ; 0x10000 + RCC_OscInitStruct.LSEState = RCC_LSE_OFF; + RCC_OscInitStruct.MSIState = RCC_MSI_OFF; + + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + 800191c: 2703 movs r7, #3 + __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); + + // Enable HSE Oscillator and activate PLL with HSE as source + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + 800191e: 9306 str r3, [sp, #24] + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + + // Select PLL as system clock source and configure + // the HCLK, PCLK1 and PCLK2 clocks dividers + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK + 8001920: 230f movs r3, #15 + + // Enable HSE Oscillator and activate PLL with HSE as source + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.LSEState = RCC_LSE_OFF; + 8001922: 2400 movs r4, #0 + RCC_OscInitStruct.MSIState = RCC_MSI_OFF; + + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + 8001924: 2602 movs r6, #2 + + // Select PLL as system clock source and configure + // the HCLK, PCLK1 and PCLK2 clocks dividers + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + 8001926: e88d 0088 stmia.w sp, {r3, r7} + + RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM; + RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN; + RCC_OscInitStruct.PLL.PLLP = CKCC_CLK_PLLP; + 800192a: f04f 0807 mov.w r8, #7 + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + + RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM; + RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN; + 800192e: 2328 movs r3, #40 ; 0x28 + RCC_OscInitStruct.PLL.PLLP = CKCC_CLK_PLLP; + RCC_OscInitStruct.PLL.PLLQ = CKCC_CLK_PLLQ; + 8001930: f04f 0904 mov.w r9, #4 + + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + HAL_RCC_OscConfig(&RCC_OscInitStruct); + 8001934: a805 add r0, sp, #20 + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + + RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM; + RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN; + 8001936: 9312 str r3, [sp, #72] ; 0x48 + + // Enable HSE Oscillator and activate PLL with HSE as source + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.LSEState = RCC_LSE_OFF; + 8001938: 9407 str r4, [sp, #28] + RCC_OscInitStruct.MSIState = RCC_MSI_OFF; + 800193a: 940b str r4, [sp, #44] ; 0x2c + + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + 800193c: 9710 str r7, [sp, #64] ; 0x40 + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + 800193e: 960f str r6, [sp, #60] ; 0x3c + // the HCLK, PCLK1 and PCLK2 clocks dividers + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + + RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM; + 8001940: 9611 str r6, [sp, #68] ; 0x44 + RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN; + RCC_OscInitStruct.PLL.PLLP = CKCC_CLK_PLLP; + 8001942: f8cd 804c str.w r8, [sp, #76] ; 0x4c + RCC_OscInitStruct.PLL.PLLQ = CKCC_CLK_PLLQ; + 8001946: f8cd 9050 str.w r9, [sp, #80] ; 0x50 + RCC_OscInitStruct.PLL.PLLR = CKCC_CLK_PLLR; + 800194a: 9615 str r6, [sp, #84] ; 0x54 + + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + 800194c: 9402 str r4, [sp, #8] + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + 800194e: 9403 str r4, [sp, #12] + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + 8001950: 9404 str r4, [sp, #16] + + HAL_RCC_OscConfig(&RCC_OscInitStruct); + 8001952: f002 fb21 bl 8003f98 + + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); + 8001956: 4649 mov r1, r9 + 8001958: 4668 mov r0, sp + 800195a: f002 fd2d bl 80043b8 + + // DIS-able MSI-Hardware auto calibration mode with LSE + CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN); + 800195e: 682b ldr r3, [r5, #0] + 8001960: f023 0304 bic.w r3, r3, #4 + 8001964: 602b str r3, [r5, #0] + + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1|RCC_PERIPHCLK_I2C1 + 8001966: 4b14 ldr r3, [pc, #80] ; (80019b8 ) + 8001968: 9316 str r3, [sp, #88] ; 0x58 + PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; + // 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; + 800196a: f04f 5380 mov.w r3, #268435456 ; 0x10000000 + 800196e: 9334 str r3, [sp, #208] ; 0xd0 + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1; + 8001970: f04f 6380 mov.w r3, #67108864 ; 0x4000000 + 8001974: 9331 str r3, [sp, #196] ; 0xc4 + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1; + 8001976: 9333 str r3, [sp, #204] ; 0xcc + + PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE; + PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24; + 8001978: 2318 movs r3, #24 + // HSE(8MHz)/PLLM(2)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz. + // + PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; + PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + 800197a: f44f 7280 mov.w r2, #256 ; 0x100 + PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1; + + PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE; + PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24; + 800197e: 9319 str r3, [sp, #100] ; 0x64 + PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK + |RCC_PLLSAI1_48M2CLK + |RCC_PLLSAI1_ADC1CLK; + + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + 8001980: a816 add r0, sp, #88 ; 0x58 + PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24; + PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7; + PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK + 8001982: 4b0e ldr r3, [pc, #56] ; (80019bc ) + // HSE(8MHz)/PLLM(2)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz. + // + PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; + PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + 8001984: 9237 str r2, [sp, #220] ; 0xdc + PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24; + PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7; + PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2; + PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK + 8001986: 931d str r3, [sp, #116] ; 0x74 + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1|RCC_PERIPHCLK_I2C1 + |RCC_PERIPHCLK_USB |RCC_PERIPHCLK_ADC + |RCC_PERIPHCLK_RNG |RCC_PERIPHCLK_RTC; + + PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; + 8001988: 942a str r4, [sp, #168] ; 0xa8 + // 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; + 800198a: 942f str r4, [sp, #188] ; 0xbc + PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1; + + PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE; + 800198c: 9717 str r7, [sp, #92] ; 0x5c + PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2; + 800198e: 9618 str r6, [sp, #96] ; 0x60 + PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24; + PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7; + 8001990: f8cd 8068 str.w r8, [sp, #104] ; 0x68 + PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2; + 8001994: 961b str r6, [sp, #108] ; 0x6c + PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2; + 8001996: 961c str r6, [sp, #112] ; 0x70 + PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK + |RCC_PLLSAI1_48M2CLK + |RCC_PLLSAI1_ADC1CLK; + + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + 8001998: f002 ff12 bl 80047c0 + + __HAL_RCC_RTC_ENABLE(); + 800199c: f8d5 3090 ldr.w r3, [r5, #144] ; 0x90 + 80019a0: f443 4300 orr.w r3, r3, #32768 ; 0x8000 + 80019a4: f8c5 3090 str.w r3, [r5, #144] ; 0x90 + + // setup SYSTICK, but we don't have the irq hooked up and not using HAL + systick_setup(); + 80019a8: f7ff ff9e bl 80018e8 +} + 80019ac: b039 add sp, #228 ; 0xe4 + 80019ae: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 80019b2: bf00 nop + 80019b4: 40021000 .word 0x40021000 + 80019b8: 00066840 .word 0x00066840 + 80019bc: 01110000 .word 0x01110000 + +080019c0 : + } else { + + // write changes to OB flash bytes + + // Set OPTSTRT bit + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + 80019c0: 4b36 ldr r3, [pc, #216] ; (8001a9c ) + 80019c2: 695a ldr r2, [r3, #20] + 80019c4: f442 3200 orr.w r2, r2, #131072 ; 0x20000 + 80019c8: 615a str r2, [r3, #20] + 80019ca: 461a mov r2, r3 + __attribute__((section(".ramfunc"))) + __attribute__((always_inline)) + static inline uint32_t +_flash_wait_done(void) +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + 80019cc: 6911 ldr r1, [r2, #16] + 80019ce: 4b33 ldr r3, [pc, #204] ; (8001a9c ) + 80019d0: 03c8 lsls r0, r1, #15 + 80019d2: d4fb bmi.n 80019cc + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + 80019d4: 691a ldr r2, [r3, #16] + 80019d6: 0791 lsls r1, r2, #30 + 80019d8: d41e bmi.n 8001a18 + 80019da: 691a ldr r2, [r3, #16] + 80019dc: 0712 lsls r2, r2, #28 + 80019de: d41b bmi.n 8001a18 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + 80019e0: 691a ldr r2, [r3, #16] +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + 80019e2: 06d0 lsls r0, r2, #27 + 80019e4: d418 bmi.n 8001a18 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + 80019e6: 691a ldr r2, [r3, #16] + 80019e8: 0691 lsls r1, r2, #26 + 80019ea: d415 bmi.n 8001a18 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + 80019ec: 691a ldr r2, [r3, #16] + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + 80019ee: 0652 lsls r2, r2, #25 + 80019f0: d412 bmi.n 8001a18 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + 80019f2: 691a ldr r2, [r3, #16] + 80019f4: 0610 lsls r0, r2, #24 + 80019f6: d40f bmi.n 8001a18 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + 80019f8: 691a ldr r2, [r3, #16] + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + 80019fa: 05d1 lsls r1, r2, #23 + 80019fc: d40c bmi.n 8001a18 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + 80019fe: 691a ldr r2, [r3, #16] + 8001a00: 0592 lsls r2, r2, #22 + 8001a02: d409 bmi.n 8001a18 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || + 8001a04: 691b ldr r3, [r3, #16] + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + 8001a06: 0458 lsls r0, r3, #17 + 8001a08: d406 bmi.n 8001a18 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || + 8001a0a: 4b24 ldr r3, [pc, #144] ; (8001a9c ) + 8001a0c: 691a ldr r2, [r3, #16] + 8001a0e: 0411 lsls r1, r2, #16 + 8001a10: d402 bmi.n 8001a18 +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) + 8001a12: 699a ldr r2, [r3, #24] + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || + 8001a14: 2a00 cmp r2, #0 + 8001a16: da02 bge.n 8001a1e +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +#endif + ) { + // Save an error code; somewhat random + return FLASH->SR; + 8001a18: 4b20 ldr r3, [pc, #128] ; (8001a9c ) + 8001a1a: 691b ldr r3, [r3, #16] + 8001a1c: e004 b.n 8001a28 + } + + // Check FLASH End of Operation flag + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) { + 8001a1e: 691a ldr r2, [r3, #16] + 8001a20: 07d2 lsls r2, r2, #31 + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + 8001a22: bf44 itt mi + 8001a24: 2201 movmi r2, #1 + 8001a26: 611a strmi r2, [r3, #16] + + /// Wait for update to complete + _flash_wait_done(); + + // lock OB again. + SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK); + 8001a28: 4b1c ldr r3, [pc, #112] ; (8001a9c ) + 8001a2a: 695a ldr r2, [r3, #20] + 8001a2c: f042 4280 orr.w r2, r2, #1073741824 ; 0x40000000 + 8001a30: 615a str r2, [r3, #20] + + // include "launch" to make them take effect NOW + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); + 8001a32: 695a ldr r2, [r3, #20] + 8001a34: f042 6200 orr.w r2, r2, #134217728 ; 0x8000000 + 8001a38: 615a str r2, [r3, #20] + 8001a3a: 461a mov r2, r3 + __attribute__((section(".ramfunc"))) + __attribute__((always_inline)) + static inline uint32_t +_flash_wait_done(void) +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + 8001a3c: 6911 ldr r1, [r2, #16] + 8001a3e: 4b17 ldr r3, [pc, #92] ; (8001a9c ) + 8001a40: 03c8 lsls r0, r1, #15 + 8001a42: d4fb bmi.n 8001a3c + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + 8001a44: 691a ldr r2, [r3, #16] + 8001a46: 0791 lsls r1, r2, #30 + 8001a48: d41e bmi.n 8001a88 + 8001a4a: 691a ldr r2, [r3, #16] + 8001a4c: 0712 lsls r2, r2, #28 + 8001a4e: d41b bmi.n 8001a88 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + 8001a50: 691a ldr r2, [r3, #16] +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + 8001a52: 06d0 lsls r0, r2, #27 + 8001a54: d418 bmi.n 8001a88 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + 8001a56: 691a ldr r2, [r3, #16] + 8001a58: 0691 lsls r1, r2, #26 + 8001a5a: d415 bmi.n 8001a88 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + 8001a5c: 691a ldr r2, [r3, #16] + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + 8001a5e: 0652 lsls r2, r2, #25 + 8001a60: d412 bmi.n 8001a88 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + 8001a62: 691a ldr r2, [r3, #16] + 8001a64: 0610 lsls r0, r2, #24 + 8001a66: d40f bmi.n 8001a88 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + 8001a68: 691a ldr r2, [r3, #16] + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + 8001a6a: 05d1 lsls r1, r2, #23 + 8001a6c: d40c bmi.n 8001a88 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + 8001a6e: 691a ldr r2, [r3, #16] + 8001a70: 0592 lsls r2, r2, #22 + 8001a72: d409 bmi.n 8001a88 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || + 8001a74: 691b ldr r3, [r3, #16] + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + 8001a76: 0458 lsls r0, r3, #17 + 8001a78: d406 bmi.n 8001a88 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || + 8001a7a: 4b08 ldr r3, [pc, #32] ; (8001a9c ) + 8001a7c: 691a ldr r2, [r3, #16] + 8001a7e: 0411 lsls r1, r2, #16 + 8001a80: d402 bmi.n 8001a88 +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) + 8001a82: 699a ldr r2, [r3, #24] + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || + 8001a84: 2a00 cmp r2, #0 + 8001a86: da02 bge.n 8001a8e +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +#endif + ) { + // Save an error code; somewhat random + return FLASH->SR; + 8001a88: 4b04 ldr r3, [pc, #16] ; (8001a9c ) + 8001a8a: 691b ldr r3, [r3, #16] + 8001a8c: 4770 bx lr + } + + // Check FLASH End of Operation flag + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) { + 8001a8e: 691a ldr r2, [r3, #16] + 8001a90: 07d2 lsls r2, r2, #31 + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + 8001a92: bf44 itt mi + 8001a94: 2201 movmi r2, #1 + 8001a96: 611a strmi r2, [r3, #16] + 8001a98: 4770 bx lr + 8001a9a: bf00 nop + 8001a9c: 40022000 .word 0x40022000 + +08001aa0 : + +// flash_setup0() +// + void +flash_setup0(void) +{ + 8001aa0: b507 push {r0, r1, r2, lr} + // put the ram-callable functions into place + extern uint8_t _srelocate, _etext, _erelocate; + memcpy(&_srelocate, &_etext, ((uint32_t)&_erelocate)-(uint32_t)&_srelocate); + 8001aa2: 4809 ldr r0, [pc, #36] ; (8001ac8 ) + 8001aa4: 4a09 ldr r2, [pc, #36] ; (8001acc ) + 8001aa6: 490a ldr r1, [pc, #40] ; (8001ad0 ) + 8001aa8: 1a12 subs r2, r2, r0 + 8001aaa: f004 feeb bl 8006884 + + // turn on clock to flash registers + __HAL_RCC_FLASH_CLK_ENABLE(); + 8001aae: 4b09 ldr r3, [pc, #36] ; (8001ad4 ) + 8001ab0: 6c9a ldr r2, [r3, #72] ; 0x48 + 8001ab2: f442 7280 orr.w r2, r2, #256 ; 0x100 + 8001ab6: 649a str r2, [r3, #72] ; 0x48 + 8001ab8: 6c9b ldr r3, [r3, #72] ; 0x48 + 8001aba: f403 7380 and.w r3, r3, #256 ; 0x100 + 8001abe: 9301 str r3, [sp, #4] + 8001ac0: 9b01 ldr r3, [sp, #4] +} + 8001ac2: b003 add sp, #12 + 8001ac4: f85d fb04 ldr.w pc, [sp], #4 + 8001ac8: 10006000 .word 0x10006000 + 8001acc: 1000624c .word 0x1000624c + 8001ad0: 08007568 .word 0x08007568 + 8001ad4: 40021000 .word 0x40021000 + +08001ad8 : +// + void +flash_lock(void) +{ + // see HAL_FLASH_Lock(); + SET_BIT(FLASH->CR, FLASH_CR_LOCK); + 8001ad8: 4a02 ldr r2, [pc, #8] ; (8001ae4 ) + 8001ada: 6953 ldr r3, [r2, #20] + 8001adc: f043 4300 orr.w r3, r3, #2147483648 ; 0x80000000 + 8001ae0: 6153 str r3, [r2, #20] + 8001ae2: 4770 bx lr + 8001ae4: 40022000 .word 0x40022000 + +08001ae8 : +// + void +flash_unlock(void) +{ + // see HAL_FLASH_Unlock(); + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK)) { + 8001ae8: 4b07 ldr r3, [pc, #28] ; (8001b08 ) + 8001aea: 695a ldr r2, [r3, #20] + 8001aec: 2a00 cmp r2, #0 + 8001aee: da0a bge.n 8001b06 + // Authorize the FLASH Registers access + WRITE_REG(FLASH->KEYR, FLASH_KEY1); + 8001af0: 4a06 ldr r2, [pc, #24] ; (8001b0c ) + 8001af2: 609a str r2, [r3, #8] + WRITE_REG(FLASH->KEYR, FLASH_KEY2); + 8001af4: f102 3288 add.w r2, r2, #2290649224 ; 0x88888888 + 8001af8: 609a str r2, [r3, #8] + + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK)) { + 8001afa: 695b ldr r3, [r3, #20] + 8001afc: 2b00 cmp r3, #0 + 8001afe: da02 bge.n 8001b06 + INCONSISTENT("failed to unlock"); + 8001b00: 4803 ldr r0, [pc, #12] ; (8001b10 ) + 8001b02: f7fe bc63 b.w 80003cc + 8001b06: 4770 bx lr + 8001b08: 40022000 .word 0x40022000 + 8001b0c: 45670123 .word 0x45670123 + 8001b10: 08007210 .word 0x08007210 + +08001b14 : +// - also does "launch" when done +// - also locks/unlocks the main flash +// + void +flash_ob_lock(bool lock) +{ + 8001b14: b510 push {r4, lr} + if(!lock) { + 8001b16: b990 cbnz r0, 8001b3e + // unlock sequence + if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK)) { + 8001b18: 4c0b ldr r4, [pc, #44] ; (8001b48 ) + 8001b1a: 6963 ldr r3, [r4, #20] + 8001b1c: 005a lsls r2, r3, #1 + 8001b1e: d512 bpl.n 8001b46 + flash_unlock(); + 8001b20: f7ff ffe2 bl 8001ae8 + + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1); + 8001b24: 4b09 ldr r3, [pc, #36] ; (8001b4c ) + 8001b26: 60e3 str r3, [r4, #12] + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2); + 8001b28: f103 3344 add.w r3, r3, #1145324612 ; 0x44444444 + 8001b2c: 60e3 str r3, [r4, #12] + + if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK)) { + 8001b2e: 6963 ldr r3, [r4, #20] + 8001b30: 005b lsls r3, r3, #1 + 8001b32: d508 bpl.n 8001b46 + INCONSISTENT("failed to OB unlock"); + 8001b34: 4806 ldr r0, [pc, #24] ; (8001b50 ) + // include "launch" to make them take effect NOW + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); + + _flash_wait_done(); + } +} + 8001b36: e8bd 4010 ldmia.w sp!, {r4, lr} + + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1); + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2); + + if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK)) { + INCONSISTENT("failed to OB unlock"); + 8001b3a: f7fe bc47 b.w 80003cc + // include "launch" to make them take effect NOW + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); + + _flash_wait_done(); + } +} + 8001b3e: e8bd 4010 ldmia.w sp!, {r4, lr} + 8001b42: f7ff bf3d b.w 80019c0 + 8001b46: bd10 pop {r4, pc} + 8001b48: 40022000 .word 0x40022000 + 8001b4c: 08192a3b .word 0x08192a3b + 8001b50: 08007210 .word 0x08007210 + +08001b54 : + +// pick_pairing_secret() +// + static void +pick_pairing_secret(void) +{ + 8001b54: b5d0 push {r4, r6, r7, lr} + 8001b56: f5ad 6d84 sub.w sp, sp, #1056 ; 0x420 + // important the RNG works here. ok to call setup multiple times. + rng_setup(); + 8001b5a: f000 f9b3 bl 8001ec4 + 8001b5e: f44f 747a mov.w r4, #1000 ; 0x3e8 + + // Demo to anyone watching that the RNG is working, but likely only + // to be seen by production team during self-test/initial powerup. + uint8_t tmp[1024]; + for(int i=0; i<1000; i++) { + rng_buffer(tmp, sizeof(tmp)); + 8001b62: f44f 6180 mov.w r1, #1024 ; 0x400 + 8001b66: a808 add r0, sp, #32 + 8001b68: f000 f9d8 bl 8001f1c + + oled_show_raw(sizeof(tmp), (void *)tmp); + 8001b6c: a908 add r1, sp, #32 + 8001b6e: f44f 6080 mov.w r0, #1024 ; 0x400 + 8001b72: f7ff f837 bl 8000be4 + rng_setup(); + + // Demo to anyone watching that the RNG is working, but likely only + // to be seen by production team during self-test/initial powerup. + uint8_t tmp[1024]; + for(int i=0; i<1000; i++) { + 8001b76: 3c01 subs r4, #1 + 8001b78: d1f3 bne.n 8001b62 + } + + // .. but don't use those numbers, because those are semi-public now. + uint32_t secret[8]; + for(int i=0; i<8; i++) { + secret[i] = rng_sample(); + 8001b7a: f000 f98f bl 8001e9c + 8001b7e: f84d 0024 str.w r0, [sp, r4, lsl #2] + oled_show_raw(sizeof(tmp), (void *)tmp); + } + + // .. but don't use those numbers, because those are semi-public now. + uint32_t secret[8]; + for(int i=0; i<8; i++) { + 8001b82: 3401 adds r4, #1 + 8001b84: 2c08 cmp r4, #8 + 8001b86: d1f8 bne.n 8001b7a + secret[i] = rng_sample(); + } + + // enforce policy that first word is not all ones (so it never + // looks like unprogrammed flash). + while(secret[0] == ~0) { + 8001b88: 9b00 ldr r3, [sp, #0] + 8001b8a: 3301 adds r3, #1 + 8001b8c: d103 bne.n 8001b96 + secret[0] = rng_sample(); + 8001b8e: f000 f985 bl 8001e9c + 8001b92: 9000 str r0, [sp, #0] + 8001b94: e7f8 b.n 8001b88 + + + // write into flash here + uint32_t dest = (uint32_t)&rom_secrets->pairing_secret; + + flash_unlock(); + 8001b96: f7ff ffa7 bl 8001ae8 + 8001b9a: 2400 movs r4, #0 + for(int i=0; i<8; i+=2, dest += 8) { + uint64_t val = (((uint64_t)secret[i]) << 32) | secret[i+1]; + 8001b9c: eb0d 0304 add.w r3, sp, r4 + + if(flash_burn(dest, val)) { + 8001ba0: f85d 7004 ldr.w r7, [sp, r4] + 8001ba4: 685a ldr r2, [r3, #4] + 8001ba6: 2600 movs r6, #0 + 8001ba8: 4630 mov r0, r6 + 8001baa: 4639 mov r1, r7 + 8001bac: ea40 0002 orr.w r0, r0, r2 + 8001bb0: 4602 mov r2, r0 + 8001bb2: f104 6000 add.w r0, r4, #134217728 ; 0x8000000 + 8001bb6: 460b mov r3, r1 + 8001bb8: f500 40f0 add.w r0, r0, #30720 ; 0x7800 + 8001bbc: f004 feb0 bl 8006920 <__flash_burn_veneer> + 8001bc0: b110 cbz r0, 8001bc8 + INCONSISTENT("flash fail"); + 8001bc2: 4805 ldr r0, [pc, #20] ; (8001bd8 ) + 8001bc4: f7fe fc02 bl 80003cc + 8001bc8: 3408 adds r4, #8 + + // write into flash here + uint32_t dest = (uint32_t)&rom_secrets->pairing_secret; + + flash_unlock(); + for(int i=0; i<8; i+=2, dest += 8) { + 8001bca: 2c20 cmp r4, #32 + 8001bcc: d1e6 bne.n 8001b9c + + if(flash_burn(dest, val)) { + INCONSISTENT("flash fail"); + } + } + flash_lock(); + 8001bce: f7ff ff83 bl 8001ad8 +} + 8001bd2: f50d 6d84 add.w sp, sp, #1056 ; 0x420 + 8001bd6: bdd0 pop {r4, r6, r7, pc} + 8001bd8: 08007210 .word 0x08007210 + +08001bdc : +// +// Write the serial number of ATECC508A into flash forever. +// + void +flash_save_ae_serial(const uint8_t serial[9]) +{ + 8001bdc: b51f push {r0, r1, r2, r3, r4, lr} + 8001bde: 4604 mov r4, r0 + + uint64_t tmp[2]; + memset(&tmp, 0x0, sizeof(tmp)); + 8001be0: 2210 movs r2, #16 + 8001be2: 2100 movs r1, #0 + 8001be4: 4668 mov r0, sp + 8001be6: f004 fe73 bl 80068d0 + memcpy(&tmp, serial, 9); + 8001bea: 6820 ldr r0, [r4, #0] + 8001bec: 6861 ldr r1, [r4, #4] + 8001bee: 7a22 ldrb r2, [r4, #8] + 8001bf0: 466b mov r3, sp + 8001bf2: c303 stmia r3!, {r0, r1} + 8001bf4: 701a strb r2, [r3, #0] + + flash_setup0(); + 8001bf6: f7ff ff53 bl 8001aa0 + flash_unlock(); + 8001bfa: f7ff ff75 bl 8001ae8 + + if(flash_burn((uint32_t)&rom_secrets->ae_serial_number[0], tmp[0])) { + 8001bfe: e9dd 2300 ldrd r2, r3, [sp] + 8001c02: 480a ldr r0, [pc, #40] ; (8001c2c ) + 8001c04: f004 fe8c bl 8006920 <__flash_burn_veneer> + 8001c08: b110 cbz r0, 8001c10 + INCONSISTENT("fail1"); + 8001c0a: 4809 ldr r0, [pc, #36] ; (8001c30 ) + 8001c0c: f7fe fbde bl 80003cc + } + if(flash_burn((uint32_t)&rom_secrets->ae_serial_number[1], tmp[1])) { + 8001c10: e9dd 2302 ldrd r2, r3, [sp, #8] + 8001c14: 4807 ldr r0, [pc, #28] ; (8001c34 ) + 8001c16: f004 fe83 bl 8006920 <__flash_burn_veneer> + 8001c1a: b110 cbz r0, 8001c22 + INCONSISTENT("fail2"); + 8001c1c: 4804 ldr r0, [pc, #16] ; (8001c30 ) + 8001c1e: f7fe fbd5 bl 80003cc + } + + flash_lock(); +} + 8001c22: b004 add sp, #16 + 8001c24: e8bd 4010 ldmia.w sp!, {r4, lr} + } + if(flash_burn((uint32_t)&rom_secrets->ae_serial_number[1], tmp[1])) { + INCONSISTENT("fail2"); + } + + flash_lock(); + 8001c28: f7ff bf56 b.w 8001ad8 + 8001c2c: 08007840 .word 0x08007840 + 8001c30: 08007210 .word 0x08007210 + 8001c34: 08007848 .word 0x08007848 + +08001c38 : +// +// Write bag number (probably a string) +// + void +flash_save_bag_number(const uint8_t new_number[32]) +{ + 8001c38: b570 push {r4, r5, r6, lr} + 8001c3a: 4605 mov r5, r0 + + uint32_t dest = (uint32_t)&rom_secrets->bag_number[0]; + uint64_t *src = (uint64_t *)new_number; + + flash_setup0(); + 8001c3c: f7ff ff30 bl 8001aa0 + flash_unlock(); + 8001c40: f7ff ff52 bl 8001ae8 +// + void +flash_save_bag_number(const uint8_t new_number[32]) +{ + + uint32_t dest = (uint32_t)&rom_secrets->bag_number[0]; + 8001c44: 4c09 ldr r4, [pc, #36] ; (8001c6c ) + flash_setup0(); + flash_unlock(); + + // NOTE: can only write once! No provision for read/check, and write + // when non-ones will fail. + for(int i=0; i<(32/8); i++, dest+=8, src++) { + 8001c46: 4e0a ldr r6, [pc, #40] ; (8001c70 ) + 8001c48: 3d08 subs r5, #8 + if(flash_burn(dest, *src)) { + 8001c4a: e9f5 2302 ldrd r2, r3, [r5, #8]! + 8001c4e: 4620 mov r0, r4 + 8001c50: f004 fe66 bl 8006920 <__flash_burn_veneer> + 8001c54: b110 cbz r0, 8001c5c + INCONSISTENT("fail write"); + 8001c56: 4807 ldr r0, [pc, #28] ; (8001c74 ) + 8001c58: f7fe fbb8 bl 80003cc + flash_setup0(); + flash_unlock(); + + // NOTE: can only write once! No provision for read/check, and write + // when non-ones will fail. + for(int i=0; i<(32/8); i++, dest+=8, src++) { + 8001c5c: 3408 adds r4, #8 + 8001c5e: 42b4 cmp r4, r6 + 8001c60: d1f3 bne.n 8001c4a + INCONSISTENT("fail write"); + } + } + + flash_lock(); +} + 8001c62: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} + if(flash_burn(dest, *src)) { + INCONSISTENT("fail write"); + } + } + + flash_lock(); + 8001c66: f7ff bf37 b.w 8001ad8 + 8001c6a: bf00 nop + 8001c6c: 08007850 .word 0x08007850 + 8001c70: 08007870 .word 0x08007870 + 8001c74: 08007210 .word 0x08007210 + +08001c78 : +// +// This is really a state-machine, to recover boards that are booted w/ missing AE chip. +// + void +flash_setup(void) +{ + 8001c78: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + flash_setup0(); + + // see if we have picked a pairing secret yet. + bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32); + 8001c7c: 4d2e ldr r5, [pc, #184] ; (8001d38 ) +// +// This is really a state-machine, to recover boards that are booted w/ missing AE chip. +// + void +flash_setup(void) +{ + 8001c7e: b088 sub sp, #32 + flash_setup0(); + 8001c80: f7ff ff0e bl 8001aa0 + + // see if we have picked a pairing secret yet. + bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32); + 8001c84: 2120 movs r1, #32 + 8001c86: 4628 mov r0, r5 + 8001c88: f000 f8e0 bl 8001e4c + bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32); + 8001c8c: 2120 movs r1, #32 +flash_setup(void) +{ + flash_setup0(); + + // see if we have picked a pairing secret yet. + bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32); + 8001c8e: 4680 mov r8, r0 + bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32); + 8001c90: 482a ldr r0, [pc, #168] ; (8001d3c ) + 8001c92: f000 f8db bl 8001e4c + bool blank_ae = (~rom_secrets->ae_serial_number[0] == 0); + 8001c96: e9d5 6710 ldrd r6, r7, [r5, #64] ; 0x40 +{ + flash_setup0(); + + // see if we have picked a pairing secret yet. + bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32); + bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32); + 8001c9a: 4604 mov r4, r0 + bool blank_ae = (~rom_secrets->ae_serial_number[0] == 0); + + if(blank_ps) { + 8001c9c: f1b8 0f00 cmp.w r8, #0 + 8001ca0: d001 beq.n 8001ca6 + // get some good entropy, save it. + pick_pairing_secret(); + 8001ca2: f7ff ff57 bl 8001b54 + + blank_ps = false; + } + + if(blank_xor || blank_ae) { + 8001ca6: b924 cbnz r4, 8001cb2 + 8001ca8: 3701 adds r7, #1 + 8001caa: bf08 it eq + 8001cac: f1b6 3fff cmpeq.w r6, #4294967295 ; 0xffffffff + 8001cb0: d121 bne.n 8001cf6 + + // configure and lock-down the ATECC508A + int rv = ae_setup_config(); + 8001cb2: f001 f82d bl 8002d10 + + if(rv) { + 8001cb6: b120 cbz r0, 8001cc2 + // hardware fail speaking to AE chip ... be careful not to brick, + // Do not continue!! We might fix the board, or add missing pullup, etc. + oled_show(screen_brick); + 8001cb8: 4821 ldr r0, [pc, #132] ; (8001d40 ) + 8001cba: f7fe ffbd bl 8000c38 + 8001cbe: bf30 wfi + 8001cc0: e7fd b.n 8001cbe + LOCKUP_FOREVER(); + } + + if(blank_xor) { + 8001cc2: b19c cbz r4, 8001cec + // BUT: we are using to mark the 2nd half of a two-phase commit w.r.t AE setup + + uint64_t *src = (uint64_t *)&rom_secrets->pairing_secret; + uint32_t dest = (uint32_t)&rom_secrets->pairing_secret_xor; + + flash_unlock(); + 8001cc4: f7ff ff10 bl 8001ae8 + 8001cc8: 4c1e ldr r4, [pc, #120] ; (8001d44 ) + for(int i=0; i<(32/8); i++, dest+=8, src++) { + 8001cca: 4d1f ldr r5, [pc, #124] ; (8001d48 ) + 8001ccc: f104 0028 add.w r0, r4, #40 ; 0x28 + uint64_t val = ~(*src); + + if(flash_burn(dest, val)) { + 8001cd0: e9f4 2302 ldrd r2, r3, [r4, #8]! + 8001cd4: 43d2 mvns r2, r2 + 8001cd6: 43db mvns r3, r3 + 8001cd8: f004 fe22 bl 8006920 <__flash_burn_veneer> + 8001cdc: b110 cbz r0, 8001ce4 + INCONSISTENT("flash xor fail"); + 8001cde: 481b ldr r0, [pc, #108] ; (8001d4c ) + 8001ce0: f7fe fb74 bl 80003cc + + uint64_t *src = (uint64_t *)&rom_secrets->pairing_secret; + uint32_t dest = (uint32_t)&rom_secrets->pairing_secret_xor; + + flash_unlock(); + for(int i=0; i<(32/8); i++, dest+=8, src++) { + 8001ce4: 42ac cmp r4, r5 + 8001ce6: d1f1 bne.n 8001ccc + + if(flash_burn(dest, val)) { + INCONSISTENT("flash xor fail"); + } + } + flash_lock(); + 8001ce8: f7ff fef6 bl 8001ad8 + // write secret again, complemented, to indicate successful AE programming + confirm_pairing_secret(); + } + + // real power cycle required now. + oled_show(screen_replug); + 8001cec: 4818 ldr r0, [pc, #96] ; (8001d50 ) + 8001cee: f7fe ffa3 bl 8000c38 + 8001cf2: bf30 wfi + 8001cf4: e7fd b.n 8001cf2 + } + + 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); + 8001cf6: 4d10 ldr r5, [pc, #64] ; (8001d38 ) + 8001cf8: cd0f ldmia r5!, {r0, r1, r2, r3} + 8001cfa: 466c mov r4, sp + 8001cfc: c40f stmia r4!, {r0, r1, r2, r3} + 8001cfe: e895 000f ldmia.w r5, {r0, r1, r2, r3} + 8001d02: e884 000f stmia.w r4, {r0, r1, r2, r3} + 8001d06: 4a13 ldr r2, [pc, #76] ; (8001d54 ) +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++) { + 8001d08: 4c13 ldr r4, [pc, #76] ; (8001d58 ) + 8001d0a: 466b mov r3, sp + 8001d0c: 4668 mov r0, sp + *(acc) ^= *(more); + 8001d0e: f812 1f01 ldrb.w r1, [r2, #1]! + 8001d12: 781d ldrb r5, [r3, #0] +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++) { + 8001d14: 42a2 cmp r2, r4 + *(acc) ^= *(more); + 8001d16: ea81 0105 eor.w r1, r1, r5 + 8001d1a: f803 1b01 strb.w r1, [r3], #1 +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++) { + 8001d1e: d1f6 bne.n 8001d0e + xor_mixin(tmp, rom_secrets->pairing_secret_xor, 32); + + if(!check_all_ones(tmp, 32)) { + 8001d20: 2120 movs r1, #32 + 8001d22: f000 f893 bl 8001e4c + 8001d26: b920 cbnz r0, 8001d32 + oled_show(screen_corrupt); + 8001d28: 480c ldr r0, [pc, #48] ; (8001d5c ) + 8001d2a: f7fe ff85 bl 8000c38 + 8001d2e: bf30 wfi + 8001d30: e7fd b.n 8001d2e + // 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. + +} + 8001d32: b008 add sp, #32 + 8001d34: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 8001d38: 08007800 .word 0x08007800 + 8001d3c: 08007820 .word 0x08007820 + 8001d40: 08006d3b .word 0x08006d3b + 8001d44: 080077f8 .word 0x080077f8 + 8001d48: 08007818 .word 0x08007818 + 8001d4c: 08007210 .word 0x08007210 + 8001d50: 08006cda .word 0x08006cda + 8001d54: 0800781f .word 0x0800781f + 8001d58: 0800783f .word 0x0800783f + 8001d5c: 08006fd1 .word 0x08006fd1 + +08001d60 : +// +// This is a one-way trip. Might need power cycle to (fully?) take effect. +// + void +flash_lockdown_hard(uint8_t rdp_level_code) +{ + 8001d60: b510 push {r4, lr} + 8001d62: 4604 mov r4, r0 + flash_setup0(); + 8001d64: f7ff fe9c bl 8001aa0 + + // see FLASH_OB_WRPConfig() + + flash_ob_lock(false); + 8001d68: 2000 movs r0, #0 + 8001d6a: f7ff fed3 bl 8001b14 + // lock first 32k against any writes + FLASH->WRP1AR = (num_pages_locked << 16); + 8001d6e: 4b07 ldr r3, [pc, #28] ; (8001d8c ) + 8001d70: f44f 2270 mov.w r2, #983040 ; 0xf0000 + 8001d74: 62da str r2, [r3, #44] ; 0x2c + FLASH->WRP1BR = 0xff; // unused. + 8001d76: 22ff movs r2, #255 ; 0xff + 8001d78: 631a str r2, [r3, #48] ; 0x30 + FLASH->WRP2AR = 0xff; // unused. + 8001d7a: 64da str r2, [r3, #76] ; 0x4c + FLASH->WRP2BR = 0xff; // unused. + 8001d7c: 651a str r2, [r3, #80] ; 0x50 + FLASH->PCROP2ER = (1<<31); // set PCROP_RDP bit, since maybe we need to? + FLASH->PCROP2SR = 0xffff; +#endif + + // set protection level + FLASH->OPTR = 0xffeff800 | rdp_level_code; // select level X, other values as observed + 8001d7e: 4a04 ldr r2, [pc, #16] ; (8001d90 ) + 8001d80: 4322 orrs r2, r4 + 8001d82: 621a str r2, [r3, #32] + + flash_ob_lock(true); +} + 8001d84: e8bd 4010 ldmia.w sp!, {r4, lr} + 8001d88: f7ff be1a b.w 80019c0 + 8001d8c: 40022000 .word 0x40022000 + 8001d90: ffeff800 .word 0xffeff800 + +08001d94 : +// backup_data_get() +// + uint32_t +backup_data_get(int idx) +{ + ASSERT(idx < 32); + 8001d94: 281f cmp r0, #31 + +// backup_data_get() +// + uint32_t +backup_data_get(int idx) +{ + 8001d96: b510 push {r4, lr} + 8001d98: 4604 mov r4, r0 + ASSERT(idx < 32); + 8001d9a: dd02 ble.n 8001da2 + 8001d9c: 4803 ldr r0, [pc, #12] ; (8001dac ) + 8001d9e: f7fe fb15 bl 80003cc + + return (&RTC->BKP0R)[idx]; + 8001da2: 4b03 ldr r3, [pc, #12] ; (8001db0 ) + 8001da4: f853 0024 ldr.w r0, [r3, r4, lsl #2] +} + 8001da8: bd10 pop {r4, pc} + 8001daa: bf00 nop + 8001dac: 08006940 .word 0x08006940 + 8001db0: 40002850 .word 0x40002850 + +08001db4 : +// backup_data_set() +// + void +backup_data_set(int idx, uint32_t new_value) +{ + ASSERT(idx < 32); + 8001db4: 281f cmp r0, #31 + +// backup_data_set() +// + void +backup_data_set(int idx, uint32_t new_value) +{ + 8001db6: b538 push {r3, r4, r5, lr} + 8001db8: 4604 mov r4, r0 + 8001dba: 460d mov r5, r1 + ASSERT(idx < 32); + 8001dbc: dd02 ble.n 8001dc4 + 8001dbe: 4807 ldr r0, [pc, #28] ; (8001ddc ) + 8001dc0: f7fe fb04 bl 80003cc + + // unlock sequence. + RTC->WPR = 0xCA; + 8001dc4: 4b06 ldr r3, [pc, #24] ; (8001de0 ) + 8001dc6: 22ca movs r2, #202 ; 0xca + 8001dc8: 625a str r2, [r3, #36] ; 0x24 + RTC->WPR = 0x53; + 8001dca: 2253 movs r2, #83 ; 0x53 + 8001dcc: 625a str r2, [r3, #36] ; 0x24 + + (&RTC->BKP0R)[idx] = new_value; + 8001dce: 4a05 ldr r2, [pc, #20] ; (8001de4 ) + 8001dd0: f842 5024 str.w r5, [r2, r4, lsl #2] + + // relock (any value) + // doesn't seem to work tho? stays unlocked + RTC->WPR = 0xff; + 8001dd4: 22ff movs r2, #255 ; 0xff + 8001dd6: 625a str r2, [r3, #36] ; 0x24 + 8001dd8: bd38 pop {r3, r4, r5, pc} + 8001dda: bf00 nop + 8001ddc: 08006940 .word 0x08006940 + 8001de0: 40002800 .word 0x40002800 + 8001de4: 40002850 .word 0x40002850 + +08001de8 : + +// record_highwater_version() +// + int +record_highwater_version(const uint8_t timestamp[8]) +{ + 8001de8: b573 push {r0, r1, r4, r5, r6, lr} + const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE; + + ASSERT(timestamp[0] < 0x40); + 8001dea: 7803 ldrb r3, [r0, #0] + 8001dec: 2b3f cmp r3, #63 ; 0x3f + +// record_highwater_version() +// + int +record_highwater_version(const uint8_t timestamp[8]) +{ + 8001dee: 4605 mov r5, r0 + const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE; + + ASSERT(timestamp[0] < 0x40); + 8001df0: d902 bls.n 8001df8 + 8001df2: 4813 ldr r0, [pc, #76] ; (8001e40 ) + 8001df4: f7fe faea bl 80003cc + ASSERT(timestamp[0] >= 0x10); + 8001df8: 782b ldrb r3, [r5, #0] + 8001dfa: 2b0f cmp r3, #15 + 8001dfc: d802 bhi.n 8001e04 + 8001dfe: 4810 ldr r0, [pc, #64] ; (8001e40 ) + 8001e00: f7fe fae4 bl 80003cc + +// record_highwater_version() +// + int +record_highwater_version(const uint8_t timestamp[8]) +{ + 8001e04: 4c0f ldr r4, [pc, #60] ; (8001e44 ) + + ASSERT(timestamp[0] < 0x40); + ASSERT(timestamp[0] >= 0x10); + + // just write to first blank slot we can find. + for(int i=0; i) + if(check_all_ones(otp, 8)) { + 8001e08: 2108 movs r1, #8 + 8001e0a: 4620 mov r0, r4 + 8001e0c: f000 f81e bl 8001e4c + 8001e10: b180 cbz r0, 8001e34 + // here. + uint64_t val = 0; + memcpy(&val, timestamp, 8); + 8001e12: 6869 ldr r1, [r5, #4] + 8001e14: 6828 ldr r0, [r5, #0] + 8001e16: 466b mov r3, sp + 8001e18: c303 stmia r3!, {r0, r1} + + flash_setup0(); + 8001e1a: f7ff fe41 bl 8001aa0 + + flash_unlock(); + 8001e1e: f7ff fe63 bl 8001ae8 + flash_burn((uint32_t)otp, val); + 8001e22: e9dd 2300 ldrd r2, r3, [sp] + 8001e26: 4620 mov r0, r4 + 8001e28: f004 fd7a bl 8006920 <__flash_burn_veneer> + flash_lock(); + 8001e2c: f7ff fe54 bl 8001ad8 + + return 0; + 8001e30: 2000 movs r0, #0 + 8001e32: e003 b.n 8001e3c + + ASSERT(timestamp[0] < 0x40); + ASSERT(timestamp[0] >= 0x10); + + // just write to first blank slot we can find. + for(int i=0; i + return 0; + } + } + + // no space. + return 1; + 8001e3a: 2001 movs r0, #1 +} + 8001e3c: b002 add sp, #8 + 8001e3e: bd70 pop {r4, r5, r6, pc} + 8001e40: 08006940 .word 0x08006940 + 8001e44: 1fff7000 .word 0x1fff7000 + 8001e48: 1fff7400 .word 0x1fff7400 + +08001e4c : +// +// Return T if all bytes are 0xFF +// + bool +check_all_ones(const void *ptrV, int len) +{ + 8001e4c: 4401 add r1, r0 + uint8_t rv = 0xff; + 8001e4e: 23ff movs r3, #255 ; 0xff + const uint8_t *ptr = (const uint8_t *)ptrV; + + for(; len; len--, ptr++) { + 8001e50: 4288 cmp r0, r1 + 8001e52: d003 beq.n 8001e5c + rv &= *ptr; + 8001e54: f810 2b01 ldrb.w r2, [r0], #1 + 8001e58: 4013 ands r3, r2 + 8001e5a: e7f9 b.n 8001e50 + } + + return (rv == 0xff); +} + 8001e5c: 3bff subs r3, #255 ; 0xff + 8001e5e: 4258 negs r0, r3 + 8001e60: 4158 adcs r0, r3 + 8001e62: 4770 bx lr + +08001e64 : +// +// Return T if all bytes are 0x00 +// + bool +check_all_zeros(const void *ptrV, int len) +{ + 8001e64: 4401 add r1, r0 + uint8_t rv = 0x0; + 8001e66: 2300 movs r3, #0 + const uint8_t *ptr = (const uint8_t *)ptrV; + + for(; len; len--, ptr++) { + 8001e68: 4288 cmp r0, r1 + 8001e6a: d003 beq.n 8001e74 + rv |= *ptr; + 8001e6c: f810 2b01 ldrb.w r2, [r0], #1 + 8001e70: 4313 orrs r3, r2 + 8001e72: e7f9 b.n 8001e68 + } + + return (rv == 0x00); +} + 8001e74: fab3 f083 clz r0, r3 + 8001e78: 0940 lsrs r0, r0, #5 + 8001e7a: 4770 bx lr + +08001e7c : + const uint8_t *left = (const uint8_t *)aV; + const uint8_t *right = (const uint8_t *)bV; + uint8_t diff = 0; + int i; + + for (i = 0; i < len; i++) { + 8001e7c: 2300 movs r3, #0 +// +// Equality check. +// + bool +check_equal(const void *aV, const void *bV, int len) +{ + 8001e7e: b570 push {r4, r5, r6, lr} + const uint8_t *left = (const uint8_t *)aV; + const uint8_t *right = (const uint8_t *)bV; + uint8_t diff = 0; + 8001e80: 461c mov r4, r3 + int i; + + for (i = 0; i < len; i++) { + 8001e82: 4293 cmp r3, r2 + 8001e84: da05 bge.n 8001e92 + diff |= (left[i] ^ right[i]); + 8001e86: 5cc6 ldrb r6, [r0, r3] + 8001e88: 5ccd ldrb r5, [r1, r3] + 8001e8a: 4075 eors r5, r6 + 8001e8c: 432c orrs r4, r5 + const uint8_t *left = (const uint8_t *)aV; + const uint8_t *right = (const uint8_t *)bV; + uint8_t diff = 0; + int i; + + for (i = 0; i < len; i++) { + 8001e8e: 3301 adds r3, #1 + 8001e90: e7f7 b.n 8001e82 + diff |= (left[i] ^ right[i]); + } + + return (diff == 0); +} + 8001e92: fab4 f084 clz r0, r4 + 8001e96: 0940 lsrs r0, r0, #5 + 8001e98: bd70 pop {r4, r5, r6, pc} + ... + +08001e9c : + } + + // Get the new number + uint32_t rv = RNG->DR; + + if(rv != last_rng_result && rv) { + 8001e9c: 4b07 ldr r3, [pc, #28] ; (8001ebc ) +{ + static uint32_t last_rng_result; + + while(1) { + /* Check if data register contains valid random data */ + while(!(RNG->SR & RNG_FLAG_DRDY)) { + 8001e9e: 4a08 ldr r2, [pc, #32] ; (8001ec0 ) + } + + // Get the new number + uint32_t rv = RNG->DR; + + if(rv != last_rng_result && rv) { + 8001ea0: 6819 ldr r1, [r3, #0] + +// rng_sample() +// + uint32_t +rng_sample(void) +{ + 8001ea2: b510 push {r4, lr} + static uint32_t last_rng_result; + + while(1) { + /* Check if data register contains valid random data */ + while(!(RNG->SR & RNG_FLAG_DRDY)) { + 8001ea4: 4614 mov r4, r2 + 8001ea6: 6850 ldr r0, [r2, #4] + 8001ea8: 07c0 lsls r0, r0, #31 + 8001eaa: d5fc bpl.n 8001ea6 + // busy wait; okay to get stuck here... better than failing. + } + + // Get the new number + uint32_t rv = RNG->DR; + 8001eac: 68a0 ldr r0, [r4, #8] + + if(rv != last_rng_result && rv) { + 8001eae: 4288 cmp r0, r1 + 8001eb0: d0f9 beq.n 8001ea6 + 8001eb2: 2800 cmp r0, #0 + 8001eb4: d0f7 beq.n 8001ea6 + last_rng_result = rv; + 8001eb6: 6018 str r0, [r3, #0] + + // keep trying if not a new number + } + + // NOT-REACHED +} + 8001eb8: bd10 pop {r4, pc} + 8001eba: bf00 nop + 8001ebc: 100062b4 .word 0x100062b4 + 8001ec0: 50060800 .word 0x50060800 + +08001ec4 : +// rng_setup() +// + void +rng_setup(void) +{ + if(RNG->CR & RNG_CR_RNGEN) { + 8001ec4: 4b12 ldr r3, [pc, #72] ; (8001f10 ) + 8001ec6: 681a ldr r2, [r3, #0] + 8001ec8: 0752 lsls r2, r2, #29 + +// rng_setup() +// + void +rng_setup(void) +{ + 8001eca: b513 push {r0, r1, r4, lr} + if(RNG->CR & RNG_CR_RNGEN) { + 8001ecc: d41e bmi.n 8001f0c + // already setup + return; + } + + // Enable the Peripheral + __HAL_RCC_RNG_CLK_ENABLE(); + 8001ece: 4a11 ldr r2, [pc, #68] ; (8001f14 ) + 8001ed0: 6cd1 ldr r1, [r2, #76] ; 0x4c + 8001ed2: f441 2180 orr.w r1, r1, #262144 ; 0x40000 + 8001ed6: 64d1 str r1, [r2, #76] ; 0x4c + 8001ed8: 6cd2 ldr r2, [r2, #76] ; 0x4c + 8001eda: f402 2280 and.w r2, r2, #262144 ; 0x40000 + 8001ede: 9201 str r2, [sp, #4] + 8001ee0: 9a01 ldr r2, [sp, #4] + + // Turn on feature. + RNG->CR |= RNG_CR_RNGEN; + 8001ee2: 681a ldr r2, [r3, #0] + 8001ee4: f042 0204 orr.w r2, r2, #4 + 8001ee8: 601a str r2, [r3, #0] + + // Sample twice to be sure that we have a + // valid RNG result. + uint32_t chk = rng_sample(); + 8001eea: f7ff ffd7 bl 8001e9c + 8001eee: 4604 mov r4, r0 + uint32_t chk2 = rng_sample(); + 8001ef0: f7ff ffd4 bl 8001e9c + + // die if we are clearly not getting random values + if(chk == 0 || chk == ~0 + 8001ef4: 1e63 subs r3, r4, #1 + 8001ef6: 3303 adds r3, #3 + 8001ef8: d804 bhi.n 8001f04 + || chk2 == 0 || chk2 == ~0 + 8001efa: 1e43 subs r3, r0, #1 + 8001efc: 3303 adds r3, #3 + 8001efe: d801 bhi.n 8001f04 + || chk == chk2 + 8001f00: 4284 cmp r4, r0 + 8001f02: d103 bne.n 8001f0c + ) { + INCONSISTENT("bad rng"); + 8001f04: 4804 ldr r0, [pc, #16] ; (8001f18 ) + 8001f06: f7fe fa61 bl 80003cc + 8001f0a: e7fe b.n 8001f0a + + while(1) ; + } +} + 8001f0c: b002 add sp, #8 + 8001f0e: bd10 pop {r4, pc} + 8001f10: 50060800 .word 0x50060800 + 8001f14: 40021000 .word 0x40021000 + 8001f18: 08007210 .word 0x08007210 + +08001f1c : + +// rng_buffer() +// + void +rng_buffer(uint8_t *result, int len) +{ + 8001f1c: b5f7 push {r0, r1, r2, r4, r5, r6, r7, lr} + 8001f1e: 4607 mov r7, r0 + 8001f20: 460e mov r6, r1 + while(len > 0) { + 8001f22: 460c mov r4, r1 + 8001f24: 1b35 subs r5, r6, r4 + 8001f26: 2c00 cmp r4, #0 + 8001f28: 443d add r5, r7 + 8001f2a: dd0c ble.n 8001f46 + uint32_t t = rng_sample(); + 8001f2c: f7ff ffb6 bl 8001e9c + + memcpy(result, &t, MIN(4, len)); + 8001f30: 2c04 cmp r4, #4 + 8001f32: 4622 mov r2, r4 +// + void +rng_buffer(uint8_t *result, int len) +{ + while(len > 0) { + uint32_t t = rng_sample(); + 8001f34: 9001 str r0, [sp, #4] + + memcpy(result, &t, MIN(4, len)); + 8001f36: bfa8 it ge + 8001f38: 2204 movge r2, #4 + 8001f3a: a901 add r1, sp, #4 + 8001f3c: 4628 mov r0, r5 + 8001f3e: f004 fca1 bl 8006884 + + len -= 4; + 8001f42: 3c04 subs r4, #4 + 8001f44: e7ee b.n 8001f24 + result += 4; + } +} + 8001f46: b003 add sp, #12 + 8001f48: bdf0 pop {r4, r5, r6, r7, pc} + ... + +08001f4c <_send_byte>: + static inline void +_send_byte(uint8_t ch) +{ + // reset timeout timer (Systick) + uint32_t ticks = 0; + SysTick->VAL = 0; + 8001f4c: 4b08 ldr r3, [pc, #32] ; (8001f70 <_send_byte+0x24>) + +// _send_byte() +// + static inline void +_send_byte(uint8_t ch) +{ + 8001f4e: b510 push {r4, lr} + // reset timeout timer (Systick) + uint32_t ticks = 0; + SysTick->VAL = 0; + 8001f50: 2200 movs r2, #0 + + while(!(MY_UART->ISR & UART_FLAG_TXE)) { + 8001f52: 4c08 ldr r4, [pc, #32] ; (8001f74 <_send_byte+0x28>) + static inline void +_send_byte(uint8_t ch) +{ + // reset timeout timer (Systick) + uint32_t ticks = 0; + SysTick->VAL = 0; + 8001f54: 609a str r2, [r3, #8] + + while(!(MY_UART->ISR & UART_FLAG_TXE)) { + 8001f56: 220b movs r2, #11 + 8001f58: 69e1 ldr r1, [r4, #28] + 8001f5a: 0609 lsls r1, r1, #24 + 8001f5c: d404 bmi.n 8001f68 <_send_byte+0x1c> + // busy-wait until able to send (no fifo?) + if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) { + 8001f5e: 6819 ldr r1, [r3, #0] + 8001f60: 03c9 lsls r1, r1, #15 + 8001f62: d5f9 bpl.n 8001f58 <_send_byte+0xc> + // failsafe timeout + ticks += 1; + if(ticks > 10) break; + 8001f64: 3a01 subs r2, #1 + 8001f66: d1f7 bne.n 8001f58 <_send_byte+0xc> + } + } + MY_UART->TDR = ch; + 8001f68: 4b02 ldr r3, [pc, #8] ; (8001f74 <_send_byte+0x28>) + 8001f6a: b280 uxth r0, r0 + 8001f6c: 8518 strh r0, [r3, #40] ; 0x28 + 8001f6e: bd10 pop {r4, pc} + 8001f70: e000e010 .word 0xe000e010 + 8001f74: 40004c00 .word 0x40004c00 + +08001f78 <_send_bits>: + +// _send_bits() +// + static void +_send_bits(uint8_t tx) +{ + 8001f78: b570 push {r4, r5, r6, lr} + 8001f7a: 4606 mov r6, r0 + 8001f7c: 2508 movs r5, #8 + // serialize and send one byte + uint8_t mask = 0x1; + 8001f7e: 2401 movs r4, #1 + + for(int i=0; i<8; i++, mask <<= 1) { + uint8_t h = (tx & mask) ? BIT1 : BIT0; + 8001f80: 4226 tst r6, r4 + + _send_byte(h); + 8001f82: bf14 ite ne + 8001f84: 207f movne r0, #127 ; 0x7f + 8001f86: 207d moveq r0, #125 ; 0x7d + 8001f88: f7ff ffe0 bl 8001f4c <_send_byte> +_send_bits(uint8_t tx) +{ + // serialize and send one byte + uint8_t mask = 0x1; + + for(int i=0; i<8; i++, mask <<= 1) { + 8001f8c: 0064 lsls r4, r4, #1 + 8001f8e: 3d01 subs r5, #1 + 8001f90: b2e4 uxtb r4, r4 + 8001f92: d1f5 bne.n 8001f80 <_send_bits+0x8> + uint8_t h = (tx & mask) ? BIT1 : BIT0; + + _send_byte(h); + } +} + 8001f94: bd70 pop {r4, r5, r6, pc} + +08001f96 <_send_serialized>: + +// _send_serialized() +// + static void +_send_serialized(const uint8_t *buf, int len) +{ + 8001f96: b570 push {r4, r5, r6, lr} + 8001f98: 4605 mov r5, r0 + 8001f9a: 460e mov r6, r1 + for(int i=0; i + _send_bits(buf[i]); + 8001fa4: f814 0b01 ldrb.w r0, [r4], #1 + 8001fa8: f7ff ffe6 bl 8001f78 <_send_bits> + 8001fac: e7f7 b.n 8001f9e <_send_serialized+0x8> + } +} + 8001fae: bd70 pop {r4, r5, r6, pc} + +08001fb0 <_flush_rx>: +// + static inline void +_flush_rx(void) +{ + // reset timeout timer (Systick) + SysTick->VAL = 0; + 8001fb0: 4b0c ldr r3, [pc, #48] ; (8001fe4 <_flush_rx+0x34>) + + while(!(MY_UART->ISR & UART_FLAG_TC)) { + 8001fb2: 490d ldr r1, [pc, #52] ; (8001fe8 <_flush_rx+0x38>) +// + static inline void +_flush_rx(void) +{ + // reset timeout timer (Systick) + SysTick->VAL = 0; + 8001fb4: 2200 movs r2, #0 + 8001fb6: 609a str r2, [r3, #8] + + while(!(MY_UART->ISR & UART_FLAG_TC)) { + 8001fb8: 69ca ldr r2, [r1, #28] + 8001fba: 0652 lsls r2, r2, #25 + 8001fbc: d402 bmi.n 8001fc4 <_flush_rx+0x14> + // wait for last bit(byte) to be serialized and sent + + if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) { + 8001fbe: 681a ldr r2, [r3, #0] + 8001fc0: 03d0 lsls r0, r2, #15 + 8001fc2: d5f9 bpl.n 8001fb8 <_flush_rx+0x8> + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); + 8001fc4: bf00 nop + 8001fc6: bf00 nop + 8001fc8: bf00 nop + 8001fca: bf00 nop + 8001fcc: bf00 nop + 8001fce: bf00 nop + 8001fd0: bf00 nop + 8001fd2: bf00 nop + __NOP(); + __NOP(); + __NOP(); + + // clear junk in rx buffer + MY_UART->RQR = USART_RQR_RXFRQ; + 8001fd4: 4b04 ldr r3, [pc, #16] ; (8001fe8 <_flush_rx+0x38>) + 8001fd6: 2208 movs r2, #8 + 8001fd8: 831a strh r2, [r3, #24] + + // clear overrun error + // clear rx timeout flag + // clear framing error + MY_UART->ICR = USART_ICR_ORECF | USART_ICR_RTOCF | USART_ICR_FECF; + 8001fda: f640 020a movw r2, #2058 ; 0x80a + 8001fde: 621a str r2, [r3, #32] + 8001fe0: 4770 bx lr + 8001fe2: bf00 nop + 8001fe4: e000e010 .word 0xe000e010 + 8001fe8: 40004c00 .word 0x40004c00 + +08001fec : + * \param[in] data pointer to data for which CRC should be calculated + * \param[out] crc pointer to 16-bit CRC + */ + static void +crc16_chain(uint8_t length, const uint8_t *data, uint8_t crc[2]) +{ + 8001fec: b5f0 push {r4, r5, r6, r7, lr} + uint16_t crc_register = 0; + uint16_t polynom = 0x8005; + uint8_t shift_register; + uint8_t data_bit, crc_bit; + + crc_register = (((uint16_t) crc[0]) & 0x00FF) | (((uint16_t) crc[1]) << 8); + 8001fee: 7813 ldrb r3, [r2, #0] + 8001ff0: 7854 ldrb r4, [r2, #1] + + for (counter = 0; counter < length; counter++) { + 8001ff2: 460e mov r6, r1 + uint16_t crc_register = 0; + uint16_t polynom = 0x8005; + uint8_t shift_register; + uint8_t data_bit, crc_bit; + + crc_register = (((uint16_t) crc[0]) & 0x00FF) | (((uint16_t) crc[1]) << 8); + 8001ff4: ea43 2304 orr.w r3, r3, r4, lsl #8 + + for (counter = 0; counter < length; counter++) { + 8001ff8: 1a74 subs r4, r6, r1 + 8001ffa: b2e4 uxtb r4, r4 + 8001ffc: 42a0 cmp r0, r4 + 8001ffe: d91a bls.n 8002036 + for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { + data_bit = (data[counter] & shift_register) ? 1 : 0; + 8002000: f816 7b01 ldrb.w r7, [r6], #1 + 8002004: 2508 movs r5, #8 + 8002006: 2401 movs r4, #1 + crc_bit = crc_register >> 15; + + // Shift CRC to the left by 1. + crc_register <<= 1; + + if ((data_bit ^ crc_bit) != 0) + 8002008: 4227 tst r7, r4 + crc_register = (((uint16_t) crc[0]) & 0x00FF) | (((uint16_t) crc[1]) << 8); + + for (counter = 0; counter < length; counter++) { + for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { + data_bit = (data[counter] & shift_register) ? 1 : 0; + crc_bit = crc_register >> 15; + 800200a: ea4f 3ed3 mov.w lr, r3, lsr #15 + + // Shift CRC to the left by 1. + crc_register <<= 1; + + if ((data_bit ^ crc_bit) != 0) + 800200e: bf18 it ne + 8002010: f04f 0c01 movne.w ip, #1 + for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { + data_bit = (data[counter] & shift_register) ? 1 : 0; + crc_bit = crc_register >> 15; + + // Shift CRC to the left by 1. + crc_register <<= 1; + 8002014: ea4f 0343 mov.w r3, r3, lsl #1 + + if ((data_bit ^ crc_bit) != 0) + 8002018: bf08 it eq + 800201a: f04f 0c00 moveq.w ip, #0 + 800201e: 45f4 cmp ip, lr + for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { + data_bit = (data[counter] & shift_register) ? 1 : 0; + crc_bit = crc_register >> 15; + + // Shift CRC to the left by 1. + crc_register <<= 1; + 8002020: b29b uxth r3, r3 + + if ((data_bit ^ crc_bit) != 0) + crc_register ^= polynom; + 8002022: bf1c itt ne + 8002024: f483 4300 eorne.w r3, r3, #32768 ; 0x8000 + 8002028: f083 0305 eorne.w r3, r3, #5 + uint8_t data_bit, crc_bit; + + crc_register = (((uint16_t) crc[0]) & 0x00FF) | (((uint16_t) crc[1]) << 8); + + for (counter = 0; counter < length; counter++) { + for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) { + 800202c: 0064 lsls r4, r4, #1 + 800202e: 3d01 subs r5, #1 + 8002030: b2e4 uxtb r4, r4 + 8002032: d1e9 bne.n 8002008 + 8002034: e7e0 b.n 8001ff8 + if ((data_bit ^ crc_bit) != 0) + crc_register ^= polynom; + } + } + + crc[0] = (uint8_t) (crc_register & 0x00FF); + 8002036: 7013 strb r3, [r2, #0] + crc[1] = (uint8_t) (crc_register >> 8); + 8002038: 0a1b lsrs r3, r3, #8 + 800203a: 7053 strb r3, [r2, #1] + 800203c: bdf0 pop {r4, r5, r6, r7, pc} + ... + +08002040 : + +// ae_check_crc() +// + static bool +ae_check_crc(const uint8_t *data, uint8_t length) +{ + 8002040: b573 push {r0, r1, r4, r5, r6, lr} + uint8_t obs[2] = { 0, 0 }; + + if(data[0] != length) { + 8002042: 7805 ldrb r5, [r0, #0] +// ae_check_crc() +// + static bool +ae_check_crc(const uint8_t *data, uint8_t length) +{ + uint8_t obs[2] = { 0, 0 }; + 8002044: 2400 movs r4, #0 + + if(data[0] != length) { + 8002046: 428d cmp r5, r1 + +// ae_check_crc() +// + static bool +ae_check_crc(const uint8_t *data, uint8_t length) +{ + 8002048: 4606 mov r6, r0 + uint8_t obs[2] = { 0, 0 }; + 800204a: f88d 4004 strb.w r4, [sp, #4] + 800204e: f88d 4005 strb.w r4, [sp, #5] + + if(data[0] != length) { + 8002052: d004 beq.n 800205e + // length is wrong + stats.crc_len_error++; + 8002054: 4a0d ldr r2, [pc, #52] ; (800208c ) + 8002056: 6893 ldr r3, [r2, #8] + 8002058: 3301 adds r3, #1 + 800205a: 6093 str r3, [r2, #8] + 800205c: e013 b.n 8002086 + return false; + } + + crc16_chain(length-2, data, obs); + 800205e: 1ea8 subs r0, r5, #2 + + return (obs[0] == data[length-2] && obs[1] == data[length-1]); + 8002060: 4435 add r5, r6 + // length is wrong + stats.crc_len_error++; + return false; + } + + crc16_chain(length-2, data, obs); + 8002062: aa01 add r2, sp, #4 + 8002064: 4631 mov r1, r6 + 8002066: b2c0 uxtb r0, r0 + 8002068: f7ff ffc0 bl 8001fec + + return (obs[0] == data[length-2] && obs[1] == data[length-1]); + 800206c: f89d 2004 ldrb.w r2, [sp, #4] + 8002070: f815 3c02 ldrb.w r3, [r5, #-2] + 8002074: 429a cmp r2, r3 + 8002076: d106 bne.n 8002086 + 8002078: f89d 4005 ldrb.w r4, [sp, #5] + 800207c: f815 3c01 ldrb.w r3, [r5, #-1] + 8002080: 1b1b subs r3, r3, r4 + 8002082: 425c negs r4, r3 + 8002084: 415c adcs r4, r3 + 8002086: 4620 mov r0, r4 +} + 8002088: b002 add sp, #8 + 800208a: bd70 pop {r4, r5, r6, pc} + 800208c: 100062b8 .word 0x100062b8 + +08002090 : + +// ae_wake() +// + static void +ae_wake(void) +{ + 8002090: b508 push {r3, lr} + // send zero (all low), delay 2.5ms + _send_byte(0x00); + 8002092: 2000 movs r0, #0 + 8002094: f7ff ff5a bl 8001f4c <_send_byte> + + delay_us(2500); + 8002098: f640 10c4 movw r0, #2500 ; 0x9c4 + 800209c: f000 ff4e bl 8002f3c + + _flush_rx(); +} + 80020a0: e8bd 4008 ldmia.w sp!, {r3, lr} + // send zero (all low), delay 2.5ms + _send_byte(0x00); + + delay_us(2500); + + _flush_rx(); + 80020a4: f7ff bf84 b.w 8001fb0 <_flush_rx> + +080020a8 : +// We ignore dump extra bytes not expected, and always read until a timeout. +// Cmds to chip can be up to 155 bytes, but not clear what max len for responses. +// + static int +ae_read_response(uint8_t *buf, int max_len) +{ + 80020a8: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + int max_expect = (max_len+1) * 8; + 80020ac: f101 0801 add.w r8, r1, #1 + 80020b0: ea4f 08c8 mov.w r8, r8, lsl #3 +// We ignore dump extra bytes not expected, and always read until a timeout. +// Cmds to chip can be up to 155 bytes, but not clear what max len for responses. +// + static int +ae_read_response(uint8_t *buf, int max_len) +{ + 80020b4: af00 add r7, sp, #0 + 80020b6: 4605 mov r5, r0 + int max_expect = (max_len+1) * 8; + uint8_t raw[max_expect]; + 80020b8: ebad 0d08 sub.w sp, sp, r8 + + // tell chip to write stuff to bus + _send_bits(IOFLAG_TX); + 80020bc: 2088 movs r0, #136 ; 0x88 +// We ignore dump extra bytes not expected, and always read until a timeout. +// Cmds to chip can be up to 155 bytes, but not clear what max len for responses. +// + static int +ae_read_response(uint8_t *buf, int max_len) +{ + 80020be: 460e mov r6, r1 + int max_expect = (max_len+1) * 8; + uint8_t raw[max_expect]; + + // tell chip to write stuff to bus + _send_bits(IOFLAG_TX); + 80020c0: f7ff ff5a bl 8001f78 <_send_bits> + + // kill first byte which we expect to be IOFLAG_TX echo (0x88) + _flush_rx(); + 80020c4: f7ff ff74 bl 8001fb0 <_flush_rx> + uint32_t ticks = 0; + + // reset timeout timer (Systick) + SysTick->VAL = 0; + + while(!(MY_UART->ISR & UART_FLAG_RXNE) && !(MY_UART->ISR & UART_FLAG_RTOF)) { + 80020c8: 4b2c ldr r3, [pc, #176] ; (800217c ) +_read_byte(void) +{ + uint32_t ticks = 0; + + // reset timeout timer (Systick) + SysTick->VAL = 0; + 80020ca: 482d ldr r0, [pc, #180] ; (8002180 ) + + // It takes between 64 and 131us (tTURNAROUND) for the chip to recover + // and start sending bits to us. We're blocked on reading + // them anyway, so no need to delay. Also a danger of overruns here. + + int actual = 0; + 80020cc: 2400 movs r4, #0 +// + static int +ae_read_response(uint8_t *buf, int max_len) +{ + int max_expect = (max_len+1) * 8; + uint8_t raw[max_expect]; + 80020ce: 46e9 mov r9, sp + // It takes between 64 and 131us (tTURNAROUND) for the chip to recover + // and start sending bits to us. We're blocked on reading + // them anyway, so no need to delay. Also a danger of overruns here. + + int actual = 0; + for(uint8_t *p = raw; ; actual++) { + 80020d0: 466a mov r2, sp +_read_byte(void) +{ + uint32_t ticks = 0; + + // reset timeout timer (Systick) + SysTick->VAL = 0; + 80020d2: 46a6 mov lr, r4 + 80020d4: 469c mov ip, r3 + 80020d6: f8c0 e008 str.w lr, [r0, #8] + 80020da: 2105 movs r1, #5 + + while(!(MY_UART->ISR & UART_FLAG_RXNE) && !(MY_UART->ISR & UART_FLAG_RTOF)) { + 80020dc: f8d3 a01c ldr.w sl, [r3, #28] + 80020e0: f01a 0f20 tst.w sl, #32 + 80020e4: d10c bne.n 8002100 + 80020e6: f8d3 a01c ldr.w sl, [r3, #28] + 80020ea: f41a 6f00 tst.w sl, #2048 ; 0x800 + 80020ee: d107 bne.n 8002100 + // busy-waiting + + if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) { + 80020f0: f8d0 a000 ldr.w sl, [r0] + 80020f4: f41a 3f80 tst.w sl, #65536 ; 0x10000 + 80020f8: d0f0 beq.n 80020dc + ticks += 1; + if(ticks >= 5) { + 80020fa: 3901 subs r1, #1 + 80020fc: d1ee bne.n 80020dc + 80020fe: e01a b.n 8002136 + return -1; + } + } + } + + if(MY_UART->ISR & UART_FLAG_RXNE) { + 8002100: f8dc a01c ldr.w sl, [ip, #28] + 8002104: 491d ldr r1, [pc, #116] ; (800217c ) + 8002106: f01a 0f20 tst.w sl, #32 + 800210a: d007 beq.n 800211c + return MY_UART->RDR & 0x7f; + 800210c: 8c99 ldrh r1, [r3, #36] ; 0x24 + int ch = _read_byte(); + if(ch < 0) { + break; + } + + if(actual < max_expect) { + 800210e: 4544 cmp r4, r8 + 8002110: f001 017f and.w r1, r1, #127 ; 0x7f + 8002114: da0d bge.n 8002132 + *(p++) = ch; + 8002116: 7011 strb r1, [r2, #0] + 8002118: 3201 adds r2, #1 + 800211a: e00a b.n 8002132 + } + + if(MY_UART->ISR & UART_FLAG_RXNE) { + return MY_UART->RDR & 0x7f; + } + if(MY_UART->ISR & UART_FLAG_RTOF) { + 800211c: 69cb ldr r3, [r1, #28] + 800211e: 051b lsls r3, r3, #20 + 8002120: d503 bpl.n 800212a + // "fast" timeout reached, clear flag + MY_UART->ICR = USART_ICR_RTOCF; + 8002122: f44f 6300 mov.w r3, #2048 ; 0x800 + 8002126: 620b str r3, [r1, #32] + 8002128: e005 b.n 8002136 + return -1; + } + INCONSISTENT("rxf"); + 800212a: 4816 ldr r0, [pc, #88] ; (8002184 ) + 800212c: f7fe f94e bl 80003cc + 8002130: e001 b.n 8002136 + // It takes between 64 and 131us (tTURNAROUND) for the chip to recover + // and start sending bits to us. We're blocked on reading + // them anyway, so no need to delay. Also a danger of overruns here. + + int actual = 0; + for(uint8_t *p = raw; ; actual++) { + 8002132: 3401 adds r4, #1 + } + + if(actual < max_expect) { + *(p++) = ch; + } + } + 8002134: e7cf b.n 80020d6 + + // Sometimes our framing is not perfect. + // We might get a spurious bit at the leading edge (perhaps an echo + // of part of the 0x88??) or junk at the end. + actual &= ~7; + 8002136: f024 0407 bic.w r4, r4, #7 + 800213a: 1de3 adds r3, r4, #7 + 800213c: f109 0207 add.w r2, r9, #7 + 8002140: 4629 mov r1, r5 + 8002142: 4499 add r9, r3 +// Return a deserialized byte, or -1 for timeout. +// + static void +deserialize(const uint8_t *from, int from_len, uint8_t *into, int max_into) +{ + while(from_len > 0) { + 8002144: 454a cmp r2, r9 + 8002146: d015 beq.n 8002174 + 8002148: f1a2 0e08 sub.w lr, r2, #8 + 800214c: 2301 movs r3, #1 + 800214e: 2000 movs r0, #0 + uint8_t rv = 0, mask = 0x1; + + for(int i=0; i<8; i++, mask <<= 1) { + if(from[i] == BIT1) { + 8002150: f81e cf01 ldrb.w ip, [lr, #1]! + 8002154: f1bc 0f7f cmp.w ip, #127 ; 0x7f + rv |= mask; + 8002158: bf08 it eq + 800215a: 4318 orreq r0, r3 +deserialize(const uint8_t *from, int from_len, uint8_t *into, int max_into) +{ + while(from_len > 0) { + uint8_t rv = 0, mask = 0x1; + + for(int i=0; i<8; i++, mask <<= 1) { + 800215c: 005b lsls r3, r3, #1 + 800215e: 4596 cmp lr, r2 + 8002160: b2db uxtb r3, r3 + 8002162: d1f5 bne.n 8002150 + if(from[i] == BIT1) { + rv |= mask; + } + } + + *(into++) = rv; + 8002164: f801 0b01 strb.w r0, [r1], #1 + 8002168: 1a73 subs r3, r6, r1 + 800216a: 442b add r3, r5 + from += 8; + from_len -= 8; + + max_into --; + if(max_into <= 0) break; + 800216c: 2b00 cmp r3, #0 + 800216e: f102 0208 add.w r2, r2, #8 + 8002172: dce7 bgt.n 8002144 + // We might get a spurious bit at the leading edge (perhaps an echo + // of part of the 0x88??) or junk at the end. + actual &= ~7; + deserialize(raw, actual, buf, max_len); + + return actual / 8; + 8002174: 10e0 asrs r0, r4, #3 +} + 8002176: 46bd mov sp, r7 + 8002178: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 800217c: 40004c00 .word 0x40004c00 + 8002180: e000e010 .word 0xe000e010 + 8002184: 08007210 .word 0x08007210 + +08002188 : +// ae_reset_chip() +// + void +ae_reset_chip(void) +{ + if(ae_chip_is_setup == AE_CHIP_IS_SETUP) { + 8002188: 4b04 ldr r3, [pc, #16] ; (800219c ) + 800218a: 681a ldr r2, [r3, #0] + 800218c: 4b04 ldr r3, [pc, #16] ; (80021a0 ) + 800218e: 429a cmp r2, r3 + 8002190: d102 bne.n 8002198 + // "The ATECC508A goes into the low power sleep mode and ignores all + // subsequent I/O transitions until the next wake flag. The entire volatile + // state of the device is reset" + _send_bits(IOFLAG_SLEEP); + 8002192: 20cc movs r0, #204 ; 0xcc + 8002194: f7ff bef0 b.w 8001f78 <_send_bits> + 8002198: 4770 bx lr + 800219a: bf00 nop + 800219c: 100062dc .word 0x100062dc + 80021a0: 35d25d63 .word 0x35d25d63 + +080021a4 : +// +// Configure pins. Do not attempt to talk to chip. +// + void +ae_setup(void) +{ + 80021a4: b507 push {r0, r1, r2, lr} + .StopBits = UART_STOPBITS_1, + .Parity = UART_PARITY_NONE, + .Mode = UART_MODE_TX_RX, +#endif + + memset(&stats, 0, sizeof(stats)); + 80021a6: 2100 movs r1, #0 + 80021a8: 2224 movs r2, #36 ; 0x24 + 80021aa: 4816 ldr r0, [pc, #88] ; (8002204 ) + 80021ac: f004 fb90 bl 80068d0 + + // enable clock to that part of chip + __HAL_RCC_UART4_CLK_ENABLE(); + 80021b0: 4b15 ldr r3, [pc, #84] ; (8002208 ) + 80021b2: 6d9a ldr r2, [r3, #88] ; 0x58 + 80021b4: f442 2200 orr.w r2, r2, #524288 ; 0x80000 + 80021b8: 659a str r2, [r3, #88] ; 0x58 + 80021ba: 6d9b ldr r3, [r3, #88] ; 0x58 + 80021bc: f403 2300 and.w r3, r3, #524288 ; 0x80000 + 80021c0: 9301 str r3, [sp, #4] + 80021c2: 9b01 ldr r3, [sp, #4] + // + // For max clock error insensitivity: + // OVER8==0, ONEBIT=1 + + // disable UART so some other bits can be set (only while disabled) + MY_UART->CR1 = 0; + 80021c4: 4b11 ldr r3, [pc, #68] ; (800220c ) + 80021c6: 2200 movs r2, #0 + 80021c8: 601a str r2, [r3, #0] + MY_UART->CR1 = 0x1000002d & ~(0 + 80021ca: 4a11 ldr r2, [pc, #68] ; (8002210 ) + 80021cc: 601a str r2, [r3, #0] + | USART_CR1_RXNEIE + | USART_CR1_IDLEIE + | USART_CR1_OVER8 + | USART_CR1_UE); + + MY_UART->RTOR = 24; // timeout in bit periods: 3 chars or so + 80021ce: 2218 movs r2, #24 + 80021d0: 615a str r2, [r3, #20] + MY_UART->CR2 = USART_CR2_RTOEN; // rx timeout enable + 80021d2: f44f 0200 mov.w r2, #8388608 ; 0x800000 + 80021d6: 605a str r2, [r3, #4] + MY_UART->CR3 = USART_CR3_HDSEL | USART_CR3_ONEBIT; + 80021d8: f640 0208 movw r2, #2056 ; 0x808 + 80021dc: 609a str r2, [r3, #8] + MY_UART->BRR = 0x0000015b; // 230400 bps + 80021de: f240 125b movw r2, #347 ; 0x15b + 80021e2: 60da str r2, [r3, #12] + + // clear rx timeout flag + MY_UART->ICR = USART_ICR_RTOCF; + 80021e4: f44f 6200 mov.w r2, #2048 ; 0x800 + 80021e8: 621a str r2, [r3, #32] + + // finally enable UART + MY_UART->CR1 |= USART_CR1_UE; + 80021ea: 681a ldr r2, [r3, #0] + 80021ec: f042 0201 orr.w r2, r2, #1 + 80021f0: 601a str r2, [r3, #0] + + // configure pin A0 to be AF8_UART4, PULL_NONE + gpio_setup(); + 80021f2: f000 fec1 bl 8002f78 + + // mark it as ready + ae_chip_is_setup = AE_CHIP_IS_SETUP; + 80021f6: 4a07 ldr r2, [pc, #28] ; (8002214 ) + 80021f8: 4b07 ldr r3, [pc, #28] ; (8002218 ) + 80021fa: 601a str r2, [r3, #0] +} + 80021fc: b003 add sp, #12 + 80021fe: f85d fb04 ldr.w pc, [sp], #4 + 8002202: bf00 nop + 8002204: 100062b8 .word 0x100062b8 + 8002208: 40021000 .word 0x40021000 + 800220c: 40004c00 .word 0x40004c00 + 8002210: 1000000c .word 0x1000000c + 8002214: 35d25d63 .word 0x35d25d63 + 8002218: 100062dc .word 0x100062dc + +0800221c : + +// ae_keep_alive() +// + void +ae_keep_alive(void) +{ + 800221c: b508 push {r3, lr} +{ + // "The ATECC508A goes into the idle mode and ignores all subsequent + // I/O transitions until the next wake flag. The contents of TempKey + // and RNG Seed registers are retained." + + ae_wake(); + 800221e: f7ff ff37 bl 8002090 + + _send_bits(IOFLAG_IDLE); + 8002222: 20bb movs r0, #187 ; 0xbb + 8002224: f7ff fea8 bl 8001f78 <_send_bits> + // To reset the watchdog, (1) put it into idle mode, then (2) wake it. + ae_send_idle(); + + // not clear if delay needed here? + ae_wake(); +} + 8002228: e8bd 4008 ldmia.w sp!, {r3, lr} +{ + // To reset the watchdog, (1) put it into idle mode, then (2) wake it. + ae_send_idle(); + + // not clear if delay needed here? + ae_wake(); + 800222c: f7ff bf30 b.w 8002090 + +08002230 : +// Read a one-byte status/error code response from chip. It's wrapped as 4 bytes: +// (len=4) (value) (crc16) (crc16) +// + int +ae_read1(void) +{ + 8002230: b537 push {r0, r1, r2, r4, r5, lr} + 8002232: 4c14 ldr r4, [pc, #80] ; (8002284 ) + 8002234: 2504 movs r5, #4 + uint8_t msg[4]; + + for(int retry=3; retry >= 0; retry--) { + ae_wake(); + 8002236: f7ff ff2b bl 8002090 + + // tell it we want to read a response, read it, and deserialize + int rv = ae_read_response(msg, 4); + 800223a: 2104 movs r1, #4 + 800223c: eb0d 0001 add.w r0, sp, r1 + 8002240: f7ff ff32 bl 80020a8 + + if(rv != 4) { + 8002244: 2804 cmp r0, #4 + + for(int retry=3; retry >= 0; retry--) { + ae_wake(); + + // tell it we want to read a response, read it, and deserialize + int rv = ae_read_response(msg, 4); + 8002246: 4601 mov r1, r0 + + if(rv != 4) { + 8002248: d003 beq.n 8002252 + ERR("rx len"); + stats.len_error++; + 800224a: 6863 ldr r3, [r4, #4] + 800224c: 3301 adds r3, #1 + 800224e: 6063 str r3, [r4, #4] + goto try_again; + 8002250: e00c b.n 800226c + } + + // Check length and CRC bytes. we will retry a few times + // if they are wrong. + if(!ae_check_crc(msg, 4)) { + 8002252: a801 add r0, sp, #4 + 8002254: f7ff fef4 bl 8002040 + 8002258: b918 cbnz r0, 8002262 + ERR("bad crc"); + stats.crc_error++; + 800225a: 6823 ldr r3, [r4, #0] + 800225c: 3301 adds r3, #1 + 800225e: 6023 str r3, [r4, #0] + goto try_again; + 8002260: e004 b.n 800226c + } + + stats.last_resp1 = msg[1]; + 8002262: 4b08 ldr r3, [pc, #32] ; (8002284 ) + 8002264: f89d 0005 ldrb.w r0, [sp, #5] + 8002268: 7758 strb r0, [r3, #29] + + // done, and it worked; return the one byte. + return msg[1]; + 800226a: e008 b.n 800227e + + try_again: + stats.l1_retry++; + 800226c: 6923 ldr r3, [r4, #16] + 800226e: 3301 adds r3, #1 + 8002270: 6123 str r3, [r4, #16] + ae_wake(); + 8002272: f7ff ff0d bl 8002090 + int +ae_read1(void) +{ + uint8_t msg[4]; + + for(int retry=3; retry >= 0; retry--) { + 8002276: 3d01 subs r5, #1 + 8002278: d1dd bne.n 8002236 + stats.l1_retry++; + ae_wake(); + } + + // fail. + return -1; + 800227a: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff +} + 800227e: b003 add sp, #12 + 8002280: bd30 pop {r4, r5, pc} + 8002282: bf00 nop + 8002284: 100062b8 .word 0x100062b8 + +08002288 : +// +// Read and check CRC over N bytes, wrapped in 3-bytes of framing overhead. +// + int +ae_read_n(uint8_t len, uint8_t *body) +{ + 8002288: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + uint8_t tmp[1+len+2]; + 800228c: 1cc6 adds r6, r0, #3 + 800228e: 300a adds r0, #10 + 8002290: f020 0007 bic.w r0, r0, #7 +// +// Read and check CRC over N bytes, wrapped in 3-bytes of framing overhead. +// + int +ae_read_n(uint8_t len, uint8_t *body) +{ + 8002294: af00 add r7, sp, #0 + goto try_again; + } + + if(!ae_check_crc(tmp, actual)) { + ERR("bad crc"); + stats.crc_error++; + 8002296: 4c1e ldr r4, [pc, #120] ; (8002310 ) +// Read and check CRC over N bytes, wrapped in 3-bytes of framing overhead. +// + int +ae_read_n(uint8_t len, uint8_t *body) +{ + uint8_t tmp[1+len+2]; + 8002298: ebad 0d00 sub.w sp, sp, r0 +// +// Read and check CRC over N bytes, wrapped in 3-bytes of framing overhead. +// + int +ae_read_n(uint8_t len, uint8_t *body) +{ + 800229c: 4688 mov r8, r1 + uint8_t tmp[1+len+2]; + 800229e: 466d mov r5, sp + 80022a0: f04f 0904 mov.w r9, #4 + + for(int retry=3; retry >= 0; retry--) { + + int actual = ae_read_response(tmp, len+3); + 80022a4: 4631 mov r1, r6 + 80022a6: 4628 mov r0, r5 + 80022a8: f7ff fefe bl 80020a8 + if(actual < 4) { + 80022ac: 2803 cmp r0, #3 +{ + uint8_t tmp[1+len+2]; + + for(int retry=3; retry >= 0; retry--) { + + int actual = ae_read_response(tmp, len+3); + 80022ae: 4682 mov sl, r0 + if(actual < 4) { + 80022b0: dc03 bgt.n 80022ba + ERR("too short"); + stats.short_error++; + 80022b2: 68e3 ldr r3, [r4, #12] + 80022b4: 3301 adds r3, #1 + 80022b6: 60e3 str r3, [r4, #12] + goto try_again; + 80022b8: e01d b.n 80022f6 + } + + uint8_t resp_len = tmp[0]; + 80022ba: 782a ldrb r2, [r5, #0] + if(resp_len != (len + 3)) { + 80022bc: 4296 cmp r6, r2 + 80022be: d009 beq.n 80022d4 + stats.len_error++; + 80022c0: 6863 ldr r3, [r4, #4] + if(resp_len == 4) { + 80022c2: 2a04 cmp r2, #4 + goto try_again; + } + + uint8_t resp_len = tmp[0]; + if(resp_len != (len + 3)) { + stats.len_error++; + 80022c4: f103 0301 add.w r3, r3, #1 + 80022c8: 6063 str r3, [r4, #4] + if(resp_len == 4) { + 80022ca: d114 bne.n 80022f6 + // Probably an unexpected error. But no way to return a short read, so + // just print out debug info. + ERRV(msg[1], "ae errcode"); + stats.last_resp1 = tmp[1]; + 80022cc: 4b10 ldr r3, [pc, #64] ; (8002310 ) + 80022ce: 786a ldrb r2, [r5, #1] + 80022d0: 775a strb r2, [r3, #29] + 80022d2: e018 b.n 8002306 + } + ERRV(msg[0], "wr len"); // wrong length + goto try_again; + } + + if(!ae_check_crc(tmp, actual)) { + 80022d4: b2c1 uxtb r1, r0 + 80022d6: 4628 mov r0, r5 + 80022d8: f7ff feb2 bl 8002040 + 80022dc: b918 cbnz r0, 80022e6 + ERR("bad crc"); + stats.crc_error++; + 80022de: 6823 ldr r3, [r4, #0] + 80022e0: 3301 adds r3, #1 + 80022e2: 6023 str r3, [r4, #0] + goto try_again; + 80022e4: e007 b.n 80022f6 + } + + // normal case: copy out body of message w/o framing + memcpy(body, tmp+1, actual-3); + 80022e6: f1aa 0203 sub.w r2, sl, #3 + 80022ea: 1c69 adds r1, r5, #1 + 80022ec: 4640 mov r0, r8 + 80022ee: f004 fac9 bl 8006884 + return 0; + 80022f2: 2000 movs r0, #0 + 80022f4: e009 b.n 800230a + + try_again: + stats.ln_retry++; + 80022f6: 6963 ldr r3, [r4, #20] + 80022f8: 3301 adds r3, #1 + 80022fa: 6163 str r3, [r4, #20] + ae_wake(); + 80022fc: f7ff fec8 bl 8002090 + int +ae_read_n(uint8_t len, uint8_t *body) +{ + uint8_t tmp[1+len+2]; + + for(int retry=3; retry >= 0; retry--) { + 8002300: f1b9 0901 subs.w r9, r9, #1 + 8002304: d1ce bne.n 80022a4 + try_again: + stats.ln_retry++; + ae_wake(); + } + + return -1; + 8002306: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff +} + 800230a: 46bd mov sp, r7 + 800230c: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 8002310: 100062b8 .word 0x100062b8 + +08002314 : + +// ae_send_n() +// + int +ae_send_n(aeopcode_t opcode, uint8_t p1, uint16_t p2, const uint8_t *data, uint8_t data_len) +{ + 8002314: b530 push {r4, r5, lr} + 8002316: b085 sub sp, #20 + 8002318: 461d mov r5, r3 + 800231a: f89d 4020 ldrb.w r4, [sp, #32] + uint8_t framed_len; + uint8_t op; + uint8_t p1; + uint8_t p2_lsb; + uint8_t p2_msb; + } known = { + 800231e: f88d 200c strb.w r2, [sp, #12] + 8002322: 2377 movs r3, #119 ; 0x77 + 8002324: f88d 3008 strb.w r3, [sp, #8] + 8002328: 1de3 adds r3, r4, #7 + 800232a: f88d 3009 strb.w r3, [sp, #9] + 800232e: 0a13 lsrs r3, r2, #8 + 8002330: f88d 300d strb.w r3, [sp, #13] + .p2_msb = (p2 >> 8) & 0xff, + }; + + STATIC_ASSERT(sizeof(known) == 6); + + stats.last_op = opcode; + 8002334: 4b14 ldr r3, [pc, #80] ; (8002388 ) + uint8_t framed_len; + uint8_t op; + uint8_t p1; + uint8_t p2_lsb; + uint8_t p2_msb; + } known = { + 8002336: f88d 000a strb.w r0, [sp, #10] + .p2_msb = (p2 >> 8) & 0xff, + }; + + STATIC_ASSERT(sizeof(known) == 6); + + stats.last_op = opcode; + 800233a: 7718 strb r0, [r3, #28] + stats.last_p1 = p1; + 800233c: 7799 strb r1, [r3, #30] + stats.last_p2 = p2; + 800233e: 841a strh r2, [r3, #32] + uint8_t framed_len; + uint8_t op; + uint8_t p1; + uint8_t p2_lsb; + uint8_t p2_msb; + } known = { + 8002340: f88d 100b strb.w r1, [sp, #11] + + stats.last_op = opcode; + stats.last_p1 = p1; + stats.last_p2 = p2; + + ae_wake(); + 8002344: f7ff fea4 bl 8002090 + + _send_serialized((const uint8_t *)&known, sizeof(known)); + 8002348: 2106 movs r1, #6 + 800234a: a802 add r0, sp, #8 + 800234c: f7ff fe23 bl 8001f96 <_send_serialized> + + // CRC will start from frame_len onwards + uint8_t crc[2] = {0, 0}; + 8002350: 2300 movs r3, #0 + crc16_chain(sizeof(known)-1, &known.framed_len, crc); + 8002352: aa01 add r2, sp, #4 + 8002354: f10d 0109 add.w r1, sp, #9 + 8002358: 2005 movs r0, #5 + ae_wake(); + + _send_serialized((const uint8_t *)&known, sizeof(known)); + + // CRC will start from frame_len onwards + uint8_t crc[2] = {0, 0}; + 800235a: f88d 3004 strb.w r3, [sp, #4] + 800235e: f88d 3005 strb.w r3, [sp, #5] + crc16_chain(sizeof(known)-1, &known.framed_len, crc); + 8002362: f7ff fe43 bl 8001fec + + // insert a variable-length body area (sometimes) + if(data_len) { + 8002366: b144 cbz r4, 800237a + _send_serialized(data, data_len); + 8002368: 4621 mov r1, r4 + 800236a: 4628 mov r0, r5 + 800236c: f7ff fe13 bl 8001f96 <_send_serialized> + + crc16_chain(data_len, data, crc); + 8002370: aa01 add r2, sp, #4 + 8002372: 4629 mov r1, r5 + 8002374: 4620 mov r0, r4 + 8002376: f7ff fe39 bl 8001fec + } + + // send final CRC bytes + _send_serialized(crc, 2); + 800237a: a801 add r0, sp, #4 + 800237c: 2102 movs r1, #2 + 800237e: f7ff fe0a bl 8001f96 <_send_serialized> + + // done! + + return 0; +} + 8002382: 2000 movs r0, #0 + 8002384: b005 add sp, #20 + 8002386: bd30 pop {r4, r5, pc} + 8002388: 100062b8 .word 0x100062b8 + +0800238c : + +// ae_send() +// + int +ae_send(aeopcode_t opcode, uint8_t p1, uint16_t p2) +{ + 800238c: b507 push {r0, r1, r2, lr} + return ae_send_n(opcode, p1, p2, NULL, 0); + 800238e: 2300 movs r3, #0 + 8002390: 9300 str r3, [sp, #0] + 8002392: f7ff ffbf bl 8002314 +} + 8002396: b003 add sp, #12 + 8002398: f85d fb04 ldr.w pc, [sp], #4 + +0800239c : +// +// Returns time in MS for max exec time of each command. +// + int +ae_delay_time(aeopcode_t opcode) +{ + 800239c: 3801 subs r0, #1 + 800239e: b2c0 uxtb r0, r0 + 80023a0: 2846 cmp r0, #70 ; 0x46 + 80023a2: bf9a itte ls + 80023a4: 4b01 ldrls r3, [pc, #4] ; (80023ac ) + 80023a6: 5618 ldrsbls r0, [r3, r0] + 80023a8: 2064 movhi r0, #100 ; 0x64 + case OP_Write: // 0x12 + return 26; + } + + return 100; +} + 80023aa: 4770 bx lr + 80023ac: 08007218 .word 0x08007218 + +080023b0 : +// Delay for worse-case time. Don't use in real code, since blocks +// whole system, and some commands are really long! +// + void +ae_delay(aeopcode_t opcode) +{ + 80023b0: b508 push {r3, lr} + delay_ms(ae_delay_time(opcode)); + 80023b2: f7ff fff3 bl 800239c +} + 80023b6: e8bd 4008 ldmia.w sp!, {r3, lr} +// whole system, and some commands are really long! +// + void +ae_delay(aeopcode_t opcode) +{ + delay_ms(ae_delay_time(opcode)); + 80023ba: f000 bdb1 b.w 8002f20 + +080023be : + int +ae_random(uint8_t randout[32]) +{ + int rv; + + rv = ae_send(OP_Random, 0, 0); + 80023be: 2200 movs r2, #0 +// +// Get a fresh random number. +// + int +ae_random(uint8_t randout[32]) +{ + 80023c0: b510 push {r4, lr} + int rv; + + rv = ae_send(OP_Random, 0, 0); + 80023c2: 4611 mov r1, r2 +// +// Get a fresh random number. +// + int +ae_random(uint8_t randout[32]) +{ + 80023c4: 4604 mov r4, r0 + int rv; + + rv = ae_send(OP_Random, 0, 0); + 80023c6: 201b movs r0, #27 + 80023c8: f7ff ffe0 bl 800238c + RET_IF_BAD(rv); + 80023cc: b940 cbnz r0, 80023e0 + + ae_delay(OP_Random); + 80023ce: 201b movs r0, #27 + 80023d0: f7ff ffee bl 80023b0 + + rv = ae_read_n(32, randout); + 80023d4: 4621 mov r1, r4 + 80023d6: 2020 movs r0, #32 + RET_IF_BAD(rv); + + return 0; +} + 80023d8: e8bd 4010 ldmia.w sp!, {r4, lr} + rv = ae_send(OP_Random, 0, 0); + RET_IF_BAD(rv); + + ae_delay(OP_Random); + + rv = ae_read_n(32, randout); + 80023dc: f7ff bf54 b.w 8002288 + RET_IF_BAD(rv); + + return 0; +} + 80023e0: bd10 pop {r4, pc} + +080023e2 : +// +// Do Info(p1=2) command, and return result. +// + uint16_t +ae_get_info(void) +{ + 80023e2: b507 push {r0, r1, r2, lr} + // not doing error checking here + ae_send(OP_Info, 0x2, 0); + 80023e4: 2200 movs r2, #0 + 80023e6: 2102 movs r1, #2 + 80023e8: 2030 movs r0, #48 ; 0x30 + 80023ea: f7ff ffcf bl 800238c + + ae_delay(OP_Info); + 80023ee: 2030 movs r0, #48 ; 0x30 + 80023f0: f7ff ffde bl 80023b0 + + // note: always returns 4 bytes, but most are garbage and unused. + uint8_t tmp[4]; + ae_read_n(4, tmp); + 80023f4: a901 add r1, sp, #4 + 80023f6: 2004 movs r0, #4 + 80023f8: f7ff ff46 bl 8002288 + + return (tmp[0] << 8) | tmp[1]; + 80023fc: f89d 0004 ldrb.w r0, [sp, #4] + 8002400: f89d 3005 ldrb.w r3, [sp, #5] +} + 8002404: ea43 2000 orr.w r0, r3, r0, lsl #8 + 8002408: b003 add sp, #12 + 800240a: f85d fb04 ldr.w pc, [sp], #4 + +0800240e : +// Load Tempkey with a specific value. Resulting Tempkey cannot be +// used with many commands/keys, but is needed for signing. +// + int +ae_load_nonce(const uint8_t nonce[32]) +{ + 800240e: b507 push {r0, r1, r2, lr} + // p1=3 + int rv = ae_send_n(OP_Nonce, 3, 0, nonce, 32); + 8002410: 2320 movs r3, #32 + 8002412: 9300 str r3, [sp, #0] + 8002414: 2200 movs r2, #0 + 8002416: 4603 mov r3, r0 + 8002418: 2103 movs r1, #3 + 800241a: 2016 movs r0, #22 + 800241c: f7ff ff7a bl 8002314 + RET_IF_BAD(rv); + 8002420: b938 cbnz r0, 8002432 + + ae_delay(OP_Nonce); + 8002422: 2016 movs r0, #22 + 8002424: f7ff ffc4 bl 80023b0 + + return ae_read1(); +} + 8002428: b003 add sp, #12 + 800242a: f85d eb04 ldr.w lr, [sp], #4 + int rv = ae_send_n(OP_Nonce, 3, 0, nonce, 32); + RET_IF_BAD(rv); + + ae_delay(OP_Nonce); + + return ae_read1(); + 800242e: f7ff beff b.w 8002230 +} + 8002432: b003 add sp, #12 + 8002434: f85d fb04 ldr.w pc, [sp], #4 + +08002438 : +// Load Tempkey with a nonce value that we both know, but +// is random and we both know is random! Tricky! +// + int +ae_pick_nonce(const uint8_t num_in[20], uint8_t tempkey[32]) +{ + 8002438: b5f0 push {r4, r5, r6, r7, lr} + 800243a: b0a9 sub sp, #164 ; 0xa4 + // we provide some 20 bytes of randomness to chip + int rv; + + // The chip must provide 32-bytes of random-ness, + // so no choice in args to OP.Nonce here (due to ReqRandom). + rv = ae_send_n(OP_Nonce, 0, 0, num_in, 20); + 800243c: 2614 movs r6, #20 + 800243e: 2200 movs r2, #0 +// Load Tempkey with a nonce value that we both know, but +// is random and we both know is random! Tricky! +// + int +ae_pick_nonce(const uint8_t num_in[20], uint8_t tempkey[32]) +{ + 8002440: 4605 mov r5, r0 + 8002442: 460f mov r7, r1 + // we provide some 20 bytes of randomness to chip + int rv; + + // The chip must provide 32-bytes of random-ness, + // so no choice in args to OP.Nonce here (due to ReqRandom). + rv = ae_send_n(OP_Nonce, 0, 0, num_in, 20); + 8002444: 4603 mov r3, r0 + 8002446: 9600 str r6, [sp, #0] + 8002448: 4611 mov r1, r2 + 800244a: 2016 movs r0, #22 + 800244c: f7ff ff62 bl 8002314 + RET_IF_BAD(rv); + 8002450: bb30 cbnz r0, 80024a0 + + ae_delay(OP_Nonce); + 8002452: 2016 movs r0, #22 + 8002454: f7ff ffac bl 80023b0 + + // Nonce command returns the RNG result, but not contents of TempKey + uint8_t randout[32]; + rv = ae_read_n(32, randout); + 8002458: a904 add r1, sp, #16 + 800245a: 2020 movs r0, #32 + 800245c: f7ff ff14 bl 8002288 + RET_IF_BAD(rv); + 8002460: 4604 mov r4, r0 + 8002462: b9e0 cbnz r0, 800249e + // + // return sha256(rndout + num_in + b'\x16\0\0').digest() + // + SHA256_CTX ctx; + + sha256_init(&ctx); + 8002464: a80c add r0, sp, #48 ; 0x30 + 8002466: f002 ff91 bl 800538c + sha256_update(&ctx, randout, 32); + 800246a: 2220 movs r2, #32 + 800246c: a904 add r1, sp, #16 + 800246e: a80c add r0, sp, #48 ; 0x30 + 8002470: f002 ffb6 bl 80053e0 + sha256_update(&ctx, num_in, 20); + 8002474: 4632 mov r2, r6 + 8002476: 4629 mov r1, r5 + 8002478: a80c add r0, sp, #48 ; 0x30 + 800247a: f002 ffb1 bl 80053e0 + const uint8_t fixed[3] = { 0x16, 0, 0 }; + 800247e: 2316 movs r3, #22 + sha256_update(&ctx, fixed, 3); + 8002480: a903 add r1, sp, #12 + 8002482: a80c add r0, sp, #48 ; 0x30 + 8002484: 2203 movs r2, #3 + SHA256_CTX ctx; + + sha256_init(&ctx); + sha256_update(&ctx, randout, 32); + sha256_update(&ctx, num_in, 20); + const uint8_t fixed[3] = { 0x16, 0, 0 }; + 8002486: f88d 300c strb.w r3, [sp, #12] + 800248a: f88d 400d strb.w r4, [sp, #13] + 800248e: f88d 400e strb.w r4, [sp, #14] + sha256_update(&ctx, fixed, 3); + 8002492: f002 ffa5 bl 80053e0 + + sha256_final(&ctx, tempkey); + 8002496: 4639 mov r1, r7 + 8002498: a80c add r0, sp, #48 ; 0x30 + 800249a: f002 ffbf bl 800541c + + ae_delay(OP_Nonce); + + // Nonce command returns the RNG result, but not contents of TempKey + uint8_t randout[32]; + rv = ae_read_n(32, randout); + 800249e: 4620 mov r0, r4 + sha256_update(&ctx, fixed, 3); + + sha256_final(&ctx, tempkey); + + return 0; +} + 80024a0: b029 add sp, #164 ; 0xa4 + 80024a2: bdf0 pop {r4, r5, r6, r7, pc} + +080024a4 : + +// ae_gendig_slot() +// + static int +ae_gendig_slot(int slot_num, const uint8_t slot_key[32], uint8_t digest[32]) +{ + 80024a4: b5f0 push {r4, r5, r6, r7, lr} + 80024a6: b0b3 sub sp, #204 ; 0xcc + 80024a8: 4605 mov r5, r0 + 80024aa: 460f mov r7, r1 + + return sha256(msg).digest() +*/ + uint8_t num_in[20], tempkey[32]; + + rng_buffer(num_in, sizeof(num_in)); + 80024ac: a802 add r0, sp, #8 + 80024ae: 2114 movs r1, #20 + +// ae_gendig_slot() +// + static int +ae_gendig_slot(int slot_num, const uint8_t slot_key[32], uint8_t digest[32]) +{ + 80024b0: 4616 mov r6, r2 + + return sha256(msg).digest() +*/ + uint8_t num_in[20], tempkey[32]; + + rng_buffer(num_in, sizeof(num_in)); + 80024b2: f7ff fd33 bl 8001f1c + int rv = ae_pick_nonce(num_in, tempkey); + 80024b6: a90e add r1, sp, #56 ; 0x38 + 80024b8: a802 add r0, sp, #8 + 80024ba: f7ff ffbd bl 8002438 + RET_IF_BAD(rv); + 80024be: 2800 cmp r0, #0 + 80024c0: d143 bne.n 800254a + + //using Zone=2="Data" => "KeyID specifies a slot in the Data zone" + rv = ae_send(OP_GenDig, 0x2, slot_num); + 80024c2: b2aa uxth r2, r5 + 80024c4: 2102 movs r1, #2 + 80024c6: 2015 movs r0, #21 + 80024c8: f7ff ff60 bl 800238c + RET_IF_BAD(rv); + 80024cc: 2800 cmp r0, #0 + 80024ce: d13c bne.n 800254a + + ae_delay(OP_GenDig); + 80024d0: 2015 movs r0, #21 + 80024d2: f7ff ff6d bl 80023b0 + + rv = ae_read1(); + 80024d6: f7ff feab bl 8002230 + RET_IF_BAD(rv); + 80024da: 4604 mov r4, r0 + 80024dc: bba0 cbnz r0, 8002548 + + ae_keep_alive(); + 80024de: f7ff fe9d bl 800221c + // msg = hkey + b'\x15\x02' + ustruct.pack(" + + uint8_t args[7] = { OP_GenDig, 2, slot_num, 0, 0xEE, 0x01, 0x23 }; + 80024e8: 2315 movs r3, #21 + 80024ea: f88d 3000 strb.w r3, [sp] + 80024ee: 2302 movs r3, #2 + 80024f0: f88d 3001 strb.w r3, [sp, #1] + 80024f4: 23ee movs r3, #238 ; 0xee + 80024f6: f88d 3004 strb.w r3, [sp, #4] + 80024fa: 2301 movs r3, #1 + 80024fc: f88d 3005 strb.w r3, [sp, #5] + uint8_t zeros[25] = { 0 }; + 8002500: 2219 movs r2, #25 + // assert len(msg) == 32+1+1+2+1+2+25+32 + // + SHA256_CTX ctx; + sha256_init(&ctx); + + uint8_t args[7] = { OP_GenDig, 2, slot_num, 0, 0xEE, 0x01, 0x23 }; + 8002502: 2323 movs r3, #35 ; 0x23 + uint8_t zeros[25] = { 0 }; + 8002504: 4621 mov r1, r4 + 8002506: a807 add r0, sp, #28 + // assert len(msg) == 32+1+1+2+1+2+25+32 + // + SHA256_CTX ctx; + sha256_init(&ctx); + + uint8_t args[7] = { OP_GenDig, 2, slot_num, 0, 0xEE, 0x01, 0x23 }; + 8002508: f88d 3006 strb.w r3, [sp, #6] + 800250c: f88d 5002 strb.w r5, [sp, #2] + 8002510: f88d 4003 strb.w r4, [sp, #3] + uint8_t zeros[25] = { 0 }; + 8002514: f004 f9dc bl 80068d0 + + sha256_update(&ctx, slot_key, 32); + 8002518: 2220 movs r2, #32 + 800251a: 4639 mov r1, r7 + 800251c: a816 add r0, sp, #88 ; 0x58 + 800251e: f002 ff5f bl 80053e0 + sha256_update(&ctx, args, sizeof(args)); + 8002522: 2207 movs r2, #7 + 8002524: 4669 mov r1, sp + 8002526: a816 add r0, sp, #88 ; 0x58 + 8002528: f002 ff5a bl 80053e0 + sha256_update(&ctx, zeros, sizeof(zeros)); + 800252c: 2219 movs r2, #25 + 800252e: a907 add r1, sp, #28 + 8002530: a816 add r0, sp, #88 ; 0x58 + 8002532: f002 ff55 bl 80053e0 + sha256_update(&ctx, tempkey, 32); + 8002536: a90e add r1, sp, #56 ; 0x38 + 8002538: a816 add r0, sp, #88 ; 0x58 + 800253a: 2220 movs r2, #32 + 800253c: f002 ff50 bl 80053e0 + + sha256_final(&ctx, digest); + 8002540: 4631 mov r1, r6 + 8002542: a816 add r0, sp, #88 ; 0x58 + 8002544: f002 ff6a bl 800541c + 8002548: 4620 mov r0, r4 + + return 0; +} + 800254a: b033 add sp, #204 ; 0xcc + 800254c: bdf0 pop {r4, r5, r6, r7, pc} + ... + +08002550 : + +// ae_checkmac() +// + int +ae_checkmac(uint8_t keynum, const uint8_t secret[32]) +{ + 8002550: b5f0 push {r4, r5, r6, r7, lr} + 8002552: b0cd sub sp, #308 ; 0x134 + + // Since this is part of the hash, we want random bytes + // for our "other data". Also a number for "numin" of nonce + uint8_t od[32], numin[20]; + + rng_buffer(od, sizeof(od)); + 8002554: ad0c add r5, sp, #48 ; 0x30 + +// ae_checkmac() +// + int +ae_checkmac(uint8_t keynum, const uint8_t secret[32]) +{ + 8002556: 4606 mov r6, r0 + 8002558: 460c mov r4, r1 + + // Since this is part of the hash, we want random bytes + // for our "other data". Also a number for "numin" of nonce + uint8_t od[32], numin[20]; + + rng_buffer(od, sizeof(od)); + 800255a: 4628 mov r0, r5 + 800255c: 2120 movs r1, #32 + 800255e: f7ff fcdd bl 8001f1c + rng_buffer(numin, sizeof(numin)); + 8002562: 2114 movs r1, #20 + 8002564: a807 add r0, sp, #28 + 8002566: f7ff fcd9 bl 8001f1c + + // need this one, want to reset watchdog to this point. + ae_keep_alive(); + 800256a: f7ff fe57 bl 800221c + + // - load tempkey with a known nonce value + uint8_t zeros[8] = {0}; + 800256e: 2300 movs r3, #0 + uint8_t tempkey[32]; + rv = ae_pick_nonce(numin, tempkey); + 8002570: a914 add r1, sp, #80 ; 0x50 + 8002572: a807 add r0, sp, #28 + + // need this one, want to reset watchdog to this point. + ae_keep_alive(); + + // - load tempkey with a known nonce value + uint8_t zeros[8] = {0}; + 8002574: 9305 str r3, [sp, #20] + 8002576: 9306 str r3, [sp, #24] + uint8_t tempkey[32]; + rv = ae_pick_nonce(numin, tempkey); + 8002578: f7ff ff5e bl 8002438 + RET_IF_BAD(rv); + 800257c: 2800 cmp r0, #0 + 800257e: d164 bne.n 800264a + + // - hash nonce and lots of other bits together + SHA256_CTX ctx; + sha256_init(&ctx); + 8002580: a830 add r0, sp, #192 ; 0xc0 + 8002582: f002 ff03 bl 800538c + + // shared secret is 32 bytes from flash + sha256_update(&ctx, secret, 32); + 8002586: 2220 movs r2, #32 + 8002588: 4621 mov r1, r4 + 800258a: a830 add r0, sp, #192 ; 0xc0 + 800258c: f002 ff28 bl 80053e0 + + sha256_update(&ctx, tempkey, 32); + 8002590: 2220 movs r2, #32 + 8002592: a914 add r1, sp, #80 ; 0x50 + 8002594: a830 add r0, sp, #192 ; 0xc0 + 8002596: f002 ff23 bl 80053e0 + sha256_update(&ctx, &od[0], 4); + 800259a: 2204 movs r2, #4 + 800259c: 4629 mov r1, r5 + 800259e: a830 add r0, sp, #192 ; 0xc0 + 80025a0: f002 ff1e bl 80053e0 + + sha256_update(&ctx, zeros, 8); + 80025a4: 2208 movs r2, #8 + 80025a6: a905 add r1, sp, #20 + 80025a8: a830 add r0, sp, #192 ; 0xc0 + 80025aa: f002 ff19 bl 80053e0 + + sha256_update(&ctx, &od[4], 3); + 80025ae: 2203 movs r2, #3 + 80025b0: a90d add r1, sp, #52 ; 0x34 + 80025b2: a830 add r0, sp, #192 ; 0xc0 + 80025b4: f002 ff14 bl 80053e0 + + uint8_t ee = 0xEE; + 80025b8: 23ee movs r3, #238 ; 0xee + sha256_update(&ctx, &ee, 1); + 80025ba: 2201 movs r2, #1 + 80025bc: f10d 010f add.w r1, sp, #15 + 80025c0: a830 add r0, sp, #192 ; 0xc0 + + sha256_update(&ctx, zeros, 8); + + sha256_update(&ctx, &od[4], 3); + + uint8_t ee = 0xEE; + 80025c2: f88d 300f strb.w r3, [sp, #15] + sha256_update(&ctx, &ee, 1); + 80025c6: f002 ff0b bl 80053e0 + sha256_update(&ctx, &od[7], 4); + 80025ca: 2204 movs r2, #4 + 80025cc: f10d 0137 add.w r1, sp, #55 ; 0x37 + 80025d0: a830 add r0, sp, #192 ; 0xc0 + 80025d2: f002 ff05 bl 80053e0 + + uint8_t snp[2] = { 0x01, 0x23 }; + 80025d6: 4b1e ldr r3, [pc, #120] ; (8002650 ) + sha256_update(&ctx, snp, 2); + 80025d8: 2202 movs r2, #2 + + uint8_t ee = 0xEE; + sha256_update(&ctx, &ee, 1); + sha256_update(&ctx, &od[7], 4); + + uint8_t snp[2] = { 0x01, 0x23 }; + 80025da: 881b ldrh r3, [r3, #0] + 80025dc: f8ad 3010 strh.w r3, [sp, #16] + sha256_update(&ctx, snp, 2); + 80025e0: a904 add r1, sp, #16 + 80025e2: a830 add r0, sp, #192 ; 0xc0 + 80025e4: f002 fefc bl 80053e0 + sha256_update(&ctx, &od[11], 2); + 80025e8: 2202 movs r2, #2 + 80025ea: f10d 013b add.w r1, sp, #59 ; 0x3b + 80025ee: a830 add r0, sp, #192 ; 0xc0 + 80025f0: f002 fef6 bl 80053e0 + uint8_t resp[32]; + uint8_t od[13]; + } req; + + // content doesn't matter, but nice and visible: + memcpy(req.ch3, copyright_msg, 32); + 80025f4: 4b17 ldr r3, [pc, #92] ; (8002654 ) + 80025f6: aa1c add r2, sp, #112 ; 0x70 + 80025f8: f103 0e20 add.w lr, r3, #32 + 80025fc: 4617 mov r7, r2 + 80025fe: 6818 ldr r0, [r3, #0] + 8002600: 6859 ldr r1, [r3, #4] + 8002602: 4614 mov r4, r2 + 8002604: c403 stmia r4!, {r0, r1} + 8002606: 3308 adds r3, #8 + 8002608: 4573 cmp r3, lr + 800260a: 4622 mov r2, r4 + 800260c: d1f7 bne.n 80025fe + // this verifies no problem. + int l = (ctx.blocks * 64) + ctx.npartial; + ASSERT(l == 32+32+4+8+3+1+4+2+2); // == 88 +#endif + + sha256_final(&ctx, req.resp); + 800260e: a924 add r1, sp, #144 ; 0x90 + 8002610: a830 add r0, sp, #192 ; 0xc0 + 8002612: f002 ff03 bl 800541c + memcpy(req.od, od, 13); + 8002616: e895 000f ldmia.w r5, {r0, r1, r2, r3} + 800261a: ac2c add r4, sp, #176 ; 0xb0 + 800261c: c407 stmia r4!, {r0, r1, r2} + 800261e: 7023 strb r3, [r4, #0] + + STATIC_ASSERT(sizeof(req) == 32 + 32 + 13); + + // Give our answer to the chip. + rv = ae_send_n(OP_CheckMac, 0x01, keynum, (uint8_t *)&req, sizeof(req)); + 8002620: 234d movs r3, #77 ; 0x4d + 8002622: 4632 mov r2, r6 + 8002624: 2101 movs r1, #1 + 8002626: 9300 str r3, [sp, #0] + 8002628: 2028 movs r0, #40 ; 0x28 + 800262a: 463b mov r3, r7 + 800262c: f7ff fe72 bl 8002314 + + ae_delay(OP_CheckMac); + 8002630: 2028 movs r0, #40 ; 0x28 + 8002632: f7ff febd bl 80023b0 + + rv = ae_read1(); + 8002636: f7ff fdfb bl 8002230 + if(rv != 0) { + 800263a: 4604 mov r4, r0 + 800263c: b918 cbnz r0, 8002646 + return -1; + } +#endif + + // just in case ... always restart watchdog timer. + ae_keep_alive(); + 800263e: f7ff fded bl 800221c + + return 0; + 8002642: 4620 mov r0, r4 + 8002644: e001 b.n 800264a + if(rv == AE_CHECKMAC_FAIL) { + ERR("CM fail"); // typical case: our hashs don't match + } else { + ERRV(rv, "CheckMac"); + } + return -1; + 8002646: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff + + // just in case ... always restart watchdog timer. + ae_keep_alive(); + + return 0; +} + 800264a: b04d add sp, #308 ; 0x134 + 800264c: bdf0 pop {r4, r5, r6, r7, pc} + 800264e: bf00 nop + 8002650: 08007216 .word 0x08007216 + 8002654: 080072a3 .word 0x080072a3 + +08002658 : +// Purpose is to show we are a pair of chips that belong together. +// + int +ae_pair_unlock() +{ + return ae_checkmac(KEYNUM_pairing, rom_secrets->pairing_secret); + 8002658: 4901 ldr r1, [pc, #4] ; (8002660 ) + 800265a: 2001 movs r0, #1 + 800265c: f7ff bf78 b.w 8002550 + 8002660: 08007800 .word 0x08007800 + +08002664 : +// ae_encrypted_read32() +// + static int +ae_encrypted_read32(int data_slot, int blk, + int read_kn, const uint8_t read_key[32], uint8_t data[32]) +{ + 8002664: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 8002668: b088 sub sp, #32 + 800266a: 4617 mov r7, r2 + 800266c: 4698 mov r8, r3 + 800266e: 460e mov r6, r1 + 8002670: 4604 mov r4, r0 + 8002672: 9d0e ldr r5, [sp, #56] ; 0x38 + uint8_t digest[32]; + + ae_keep_alive(); + 8002674: f7ff fdd2 bl 800221c + ae_pair_unlock(); + 8002678: f7ff ffee bl 8002658 + + int rv = ae_gendig_slot(read_kn, read_key, digest); + 800267c: 466a mov r2, sp + 800267e: 4641 mov r1, r8 + 8002680: 4638 mov r0, r7 + 8002682: f7ff ff0f bl 80024a4 + RET_IF_BAD(rv); + 8002686: b9d0 cbnz r0, 80026be + + // read nth 32-byte "block" + rv = ae_send(OP_Read, 0x82, (blk << 8) | (data_slot<<3)); + 8002688: 00e2 lsls r2, r4, #3 + 800268a: ea42 2206 orr.w r2, r2, r6, lsl #8 + 800268e: b292 uxth r2, r2 + 8002690: 2182 movs r1, #130 ; 0x82 + 8002692: 2002 movs r0, #2 + 8002694: f7ff fe7a bl 800238c + RET_IF_BAD(rv); + 8002698: b988 cbnz r0, 80026be + + ae_delay(OP_Read); + 800269a: 2002 movs r0, #2 + 800269c: f7ff fe88 bl 80023b0 + + rv = ae_read_n(32, data); + 80026a0: 4629 mov r1, r5 + 80026a2: 2020 movs r0, #32 + 80026a4: f7ff fdf0 bl 8002288 + RET_IF_BAD(rv); + 80026a8: b948 cbnz r0, 80026be + *(acc) ^= *(more); + 80026aa: 782a ldrb r2, [r5, #0] + 80026ac: f81d 3000 ldrb.w r3, [sp, r0] + 80026b0: 3001 adds r0, #1 + 80026b2: 4053 eors r3, r2 +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++) { + 80026b4: 2820 cmp r0, #32 + *(acc) ^= *(more); + 80026b6: f805 3b01 strb.w r3, [r5], #1 +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++) { + 80026ba: d1f6 bne.n 80026aa + + xor_mixin(data, digest, 32); + + return 0; + 80026bc: 2000 movs r0, #0 +} + 80026be: b008 add sp, #32 + 80026c0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +080026c4 : +// +// Sign a message (already digested) +// + int +ae_sign(uint8_t keynum, uint8_t msg_hash[32], uint8_t signature[64]) +{ + 80026c4: b537 push {r0, r1, r2, r4, r5, lr} + 80026c6: 4605 mov r5, r0 + int rv = ae_load_nonce(msg_hash); + 80026c8: 4608 mov r0, r1 +// +// Sign a message (already digested) +// + int +ae_sign(uint8_t keynum, uint8_t msg_hash[32], uint8_t signature[64]) +{ + 80026ca: 4614 mov r4, r2 + int rv = ae_load_nonce(msg_hash); + 80026cc: f7ff fe9f bl 800240e + RET_IF_BAD(rv); + 80026d0: b988 cbnz r0, 80026f6 + + rv = ae_send_n(OP_Sign, 0x80, keynum, NULL, 0); + 80026d2: 9000 str r0, [sp, #0] + 80026d4: 4603 mov r3, r0 + 80026d6: 462a mov r2, r5 + 80026d8: 2180 movs r1, #128 ; 0x80 + 80026da: 2041 movs r0, #65 ; 0x41 + 80026dc: f7ff fe1a bl 8002314 + RET_IF_BAD(rv); + 80026e0: b948 cbnz r0, 80026f6 + + ae_delay(OP_Sign); + 80026e2: 2041 movs r0, #65 ; 0x41 + 80026e4: f7ff fe64 bl 80023b0 + + rv = ae_read_n(64, signature); + 80026e8: 4621 mov r1, r4 + 80026ea: 2040 movs r0, #64 ; 0x40 + RET_IF_BAD(rv); + + return 0; +} + 80026ec: b003 add sp, #12 + 80026ee: e8bd 4030 ldmia.w sp!, {r4, r5, lr} + rv = ae_send_n(OP_Sign, 0x80, keynum, NULL, 0); + RET_IF_BAD(rv); + + ae_delay(OP_Sign); + + rv = ae_read_n(64, signature); + 80026f2: f7ff bdc9 b.w 8002288 + RET_IF_BAD(rv); + + return 0; +} + 80026f6: b003 add sp, #12 + 80026f8: bd30 pop {r4, r5, pc} + +080026fa : +// +// Inc and return the one-way counter. +// + int +ae_get_counter(uint32_t *result, int counter_number, bool incr) +{ + 80026fa: 4613 mov r3, r2 + 80026fc: b510 push {r4, lr} + int rv = ae_send(OP_Counter, incr ? 0x1 : 0x0, counter_number); + 80026fe: b28a uxth r2, r1 +// +// Inc and return the one-way counter. +// + int +ae_get_counter(uint32_t *result, int counter_number, bool incr) +{ + 8002700: 4604 mov r4, r0 + int rv = ae_send(OP_Counter, incr ? 0x1 : 0x0, counter_number); + 8002702: 4619 mov r1, r3 + 8002704: 2024 movs r0, #36 ; 0x24 + 8002706: f7ff fe41 bl 800238c + RET_IF_BAD(rv); + 800270a: b940 cbnz r0, 800271e + + ae_delay(OP_Counter); + 800270c: 2024 movs r0, #36 ; 0x24 + 800270e: f7ff fe4f bl 80023b0 + + // already in correct endian + rv = ae_read_n(4, (uint8_t *)result); + 8002712: 4621 mov r1, r4 + 8002714: 2004 movs r0, #4 + RET_IF_BAD(rv); + + return 0; +} + 8002716: e8bd 4010 ldmia.w sp!, {r4, lr} + RET_IF_BAD(rv); + + ae_delay(OP_Counter); + + // already in correct endian + rv = ae_read_n(4, (uint8_t *)result); + 800271a: f7ff bdb5 b.w 8002288 + RET_IF_BAD(rv); + + return 0; +} + 800271e: bd10 pop {r4, pc} + +08002720 : +// +// Generate a MAC for the indicated key. Will be dependent on serial number. +// + int +ae_make_mac(uint8_t keynum, uint8_t challenge[32], uint8_t mac_out[32]) +{ + 8002720: b537 push {r0, r1, r2, r4, r5, lr} + int rv = ae_send_n(OP_MAC, (1<<6), keynum, challenge, 32); + 8002722: 2420 movs r4, #32 + 8002724: 460b mov r3, r1 +// +// Generate a MAC for the indicated key. Will be dependent on serial number. +// + int +ae_make_mac(uint8_t keynum, uint8_t challenge[32], uint8_t mac_out[32]) +{ + 8002726: 4615 mov r5, r2 + int rv = ae_send_n(OP_MAC, (1<<6), keynum, challenge, 32); + 8002728: 2140 movs r1, #64 ; 0x40 + 800272a: 4602 mov r2, r0 + 800272c: 9400 str r4, [sp, #0] + 800272e: 2008 movs r0, #8 + 8002730: f7ff fdf0 bl 8002314 + + ae_delay(OP_MAC); + 8002734: 2008 movs r0, #8 + 8002736: f7ff fe3b bl 80023b0 + + rv = ae_read_n(32, mac_out); + 800273a: 4629 mov r1, r5 + 800273c: 4620 mov r0, r4 + RET_IF_BAD(rv); + + return 0; +} + 800273e: b003 add sp, #12 + 8002740: e8bd 4030 ldmia.w sp!, {r4, r5, lr} +{ + int rv = ae_send_n(OP_MAC, (1<<6), keynum, challenge, 32); + + ae_delay(OP_MAC); + + rv = ae_read_n(32, mac_out); + 8002744: f7ff bda0 b.w 8002288 + +08002748 : +// +// Different opcode, OP_HMAC does exactly 32 bytes w/ less steps. +// + int +ae_hmac32(uint8_t keynum, const uint8_t msg[32], uint8_t digest[32]) +{ + 8002748: b538 push {r3, r4, r5, lr} + 800274a: 4605 mov r5, r0 + // Load tempkey w/ message to be HMAC'ed + int rv = ae_load_nonce(msg); + 800274c: 4608 mov r0, r1 +// +// Different opcode, OP_HMAC does exactly 32 bytes w/ less steps. +// + int +ae_hmac32(uint8_t keynum, const uint8_t msg[32], uint8_t digest[32]) +{ + 800274e: 4614 mov r4, r2 + // Load tempkey w/ message to be HMAC'ed + int rv = ae_load_nonce(msg); + 8002750: f7ff fe5d bl 800240e + RET_IF_BAD(rv); + 8002754: b970 cbnz r0, 8002774 + + // Ask for HMAC using specific key + rv = ae_send(OP_HMAC, (1<<2) | (1<<6), keynum); + 8002756: 462a mov r2, r5 + 8002758: 2144 movs r1, #68 ; 0x44 + 800275a: 2011 movs r0, #17 + 800275c: f7ff fe16 bl 800238c + RET_IF_BAD(rv); + 8002760: b940 cbnz r0, 8002774 + + ae_delay(OP_HMAC); + 8002762: 2011 movs r0, #17 + 8002764: f7ff fe24 bl 80023b0 + + rv = ae_read_n(32, digest); + 8002768: 4621 mov r1, r4 + 800276a: 2020 movs r0, #32 + RET_IF_BAD(rv); + + return 0; +} + 800276c: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} + rv = ae_send(OP_HMAC, (1<<2) | (1<<6), keynum); + RET_IF_BAD(rv); + + ae_delay(OP_HMAC); + + rv = ae_read_n(32, digest); + 8002770: f7ff bd8a b.w 8002288 + RET_IF_BAD(rv); + + return 0; +} + 8002774: bd38 pop {r3, r4, r5, pc} + +08002776 : +// +// Return the serial number: it's 9 bytes, altho 3 are fixed. +// + int +ae_get_serial(uint8_t serial[6]) +{ + 8002776: b510 push {r4, lr} + int rv = ae_send(OP_Read, 0x80, 0x0); + 8002778: 2200 movs r2, #0 +// +// Return the serial number: it's 9 bytes, altho 3 are fixed. +// + int +ae_get_serial(uint8_t serial[6]) +{ + 800277a: b08c sub sp, #48 ; 0x30 + 800277c: 4604 mov r4, r0 + int rv = ae_send(OP_Read, 0x80, 0x0); + 800277e: 2180 movs r1, #128 ; 0x80 + 8002780: 2002 movs r0, #2 + 8002782: f7ff fe03 bl 800238c + RET_IF_BAD(rv); + 8002786: bb10 cbnz r0, 80027ce + + ae_delay(OP_Read); + 8002788: 2002 movs r0, #2 + 800278a: f7ff fe11 bl 80023b0 + + uint8_t temp[32]; + rv = ae_read_n(32, temp); + 800278e: a904 add r1, sp, #16 + 8002790: 2020 movs r0, #32 + 8002792: f7ff fd79 bl 8002288 + RET_IF_BAD(rv); + 8002796: 4602 mov r2, r0 + 8002798: b9b0 cbnz r0, 80027c8 + + // reformat to 9 bytes. + uint8_t ts[9]; + memcpy(ts, &temp[0], 4); + memcpy(&ts[4], &temp[8], 5); + 800279a: a906 add r1, sp, #24 + 800279c: c903 ldmia r1, {r0, r1} + rv = ae_read_n(32, temp); + RET_IF_BAD(rv); + + // reformat to 9 bytes. + uint8_t ts[9]; + memcpy(ts, &temp[0], 4); + 800279e: 9b04 ldr r3, [sp, #16] + memcpy(&ts[4], &temp[8], 5); + 80027a0: 9002 str r0, [sp, #8] + + // check the hard-coded values + if((ts[0] != 0x01) || (ts[1] != 0x23) || (ts[8] != 0xEE)) return 1; + 80027a2: b2d8 uxtb r0, r3 + 80027a4: 2801 cmp r0, #1 + rv = ae_read_n(32, temp); + RET_IF_BAD(rv); + + // reformat to 9 bytes. + uint8_t ts[9]; + memcpy(ts, &temp[0], 4); + 80027a6: 9301 str r3, [sp, #4] + memcpy(&ts[4], &temp[8], 5); + 80027a8: f88d 100c strb.w r1, [sp, #12] + + // check the hard-coded values + if((ts[0] != 0x01) || (ts[1] != 0x23) || (ts[8] != 0xEE)) return 1; + 80027ac: d10e bne.n 80027cc + 80027ae: f89d 3005 ldrb.w r3, [sp, #5] + 80027b2: 2b23 cmp r3, #35 ; 0x23 + 80027b4: d10b bne.n 80027ce + 80027b6: b2cb uxtb r3, r1 + 80027b8: 2bee cmp r3, #238 ; 0xee + 80027ba: d108 bne.n 80027ce + + // save only the unique bits. + memcpy(serial, ts+2, 6); + 80027bc: ab0c add r3, sp, #48 ; 0x30 + 80027be: f853 1d2a ldr.w r1, [r3, #-42]! + 80027c2: 6021 str r1, [r4, #0] + 80027c4: 889b ldrh r3, [r3, #4] + 80027c6: 80a3 strh r3, [r4, #4] + + ae_delay(OP_Read); + + uint8_t temp[32]; + rv = ae_read_n(32, temp); + RET_IF_BAD(rv); + 80027c8: 4610 mov r0, r2 + 80027ca: e000 b.n 80027ce + uint8_t ts[9]; + memcpy(ts, &temp[0], 4); + memcpy(&ts[4], &temp[8], 5); + + // check the hard-coded values + if((ts[0] != 0x01) || (ts[1] != 0x23) || (ts[8] != 0xEE)) return 1; + 80027cc: 2001 movs r0, #1 + + // save only the unique bits. + memcpy(serial, ts+2, 6); + + return 0; +} + 80027ce: b00c add sp, #48 ; 0x30 + 80027d0: bd10 pop {r4, pc} + ... + +080027d4 : + +// ae_probe() +// + const char * +ae_probe(void) +{ + 80027d4: b513 push {r0, r1, r4, lr} +ae_send_sleep(void) +{ + // "The ATECC508A goes into the low power sleep mode and ignores all + // subsequent I/O transitions until the next wake flag. The entire volatile + // state of the device is reset" + ae_wake(); + 80027d6: f7ff fc5b bl 8002090 + + _send_bits(IOFLAG_SLEEP); + 80027da: 20cc movs r0, #204 ; 0xcc + 80027dc: f7ff fbcc bl 8001f78 <_send_bits> + + // Make it sleep / wake it up. + ae_send_sleep(); + + // Wake it again (to reset state) + ae_wake(); + 80027e0: f7ff fc56 bl 8002090 + + // do a real read w/ CRC + // with no command happening, expect 0x11: "After Wake, prior to first command" + ae_read1(); + 80027e4: f7ff fd24 bl 8002230 + + uint8_t chk = ae_read1(); + 80027e8: f7ff fd22 bl 8002230 + if(chk != AE_AFTER_WAKE) return "wk fl"; + 80027ec: b2c0 uxtb r0, r0 + 80027ee: 2811 cmp r0, #17 + 80027f0: d10b bne.n 800280a + } +#endif + + // read the serial number one time + uint8_t serial[6]; + if(ae_get_serial(serial)) return "no ser"; + 80027f2: 4668 mov r0, sp + 80027f4: f7ff ffbf bl 8002776 + 80027f8: 4604 mov r4, r0 + 80027fa: b940 cbnz r0, 800280e +ae_send_sleep(void) +{ + // "The ATECC508A goes into the low power sleep mode and ignores all + // subsequent I/O transitions until the next wake flag. The entire volatile + // state of the device is reset" + ae_wake(); + 80027fc: f7ff fc48 bl 8002090 + + _send_bits(IOFLAG_SLEEP); + 8002800: 20cc movs r0, #204 ; 0xcc + 8002802: f7ff fbb9 bl 8001f78 <_send_bits> + if(ae_get_serial(serial)) return "no ser"; + + // put into a low-power mode, might be a bit before we come back + ae_send_sleep(); + + return NULL; + 8002806: 4620 mov r0, r4 + 8002808: e002 b.n 8002810 + // do a real read w/ CRC + // with no command happening, expect 0x11: "After Wake, prior to first command" + ae_read1(); + + uint8_t chk = ae_read1(); + if(chk != AE_AFTER_WAKE) return "wk fl"; + 800280a: 4802 ldr r0, [pc, #8] ; (8002814 ) + 800280c: e000 b.n 8002810 + } +#endif + + // read the serial number one time + uint8_t serial[6]; + if(ae_get_serial(serial)) return "no ser"; + 800280e: 4802 ldr r0, [pc, #8] ; (8002818 ) + + // put into a low-power mode, might be a bit before we come back + ae_send_sleep(); + + return NULL; +} + 8002810: b002 add sp, #8 + 8002812: bd10 pop {r4, pc} + 8002814: 080072c4 .word 0x080072c4 + 8002818: 080072ca .word 0x080072ca + +0800281c : +// +// Read a 16-bit bitmask of which data slots are presently locked. +// + int +ae_slot_locks(void) +{ + 800281c: b507 push {r0, r1, r2, lr} + // Bytes 88, 89 in the Config zone is a bitmap of + // which slots are locked. Have to read 4 bytes here tho + int rv = ae_send(OP_Read, 0x00, 88/4); + 800281e: 2216 movs r2, #22 + 8002820: 2100 movs r1, #0 + 8002822: 2002 movs r0, #2 + 8002824: f7ff fdb2 bl 800238c + if(rv) return -1; + 8002828: b950 cbnz r0, 8002840 + + ae_delay(OP_Read); + 800282a: 2002 movs r0, #2 + 800282c: f7ff fdc0 bl 80023b0 + + uint8_t tmp[4]; + rv = ae_read_n(4, tmp); + 8002830: a901 add r1, sp, #4 + 8002832: 2004 movs r0, #4 + 8002834: f7ff fd28 bl 8002288 + if(rv) return -2; + 8002838: b928 cbnz r0, 8002846 + + // returns positive 16-bit number on success + return (tmp[1] << 8) | tmp[0]; + 800283a: f8bd 0004 ldrh.w r0, [sp, #4] + 800283e: e004 b.n 800284a +ae_slot_locks(void) +{ + // Bytes 88, 89 in the Config zone is a bitmap of + // which slots are locked. Have to read 4 bytes here tho + int rv = ae_send(OP_Read, 0x00, 88/4); + if(rv) return -1; + 8002840: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff + 8002844: e001 b.n 800284a + + ae_delay(OP_Read); + + uint8_t tmp[4]; + rv = ae_read_n(4, tmp); + if(rv) return -2; + 8002846: f06f 0001 mvn.w r0, #1 + + // returns positive 16-bit number on success + return (tmp[1] << 8) | tmp[0]; +} + 800284a: b003 add sp, #12 + 800284c: f85d fb04 ldr.w pc, [sp], #4 + +08002850 : +// +// -- can also lock it. +// + int +ae_write_data_slot(int slot_num, const uint8_t *data, int len, bool lock_it) +{ + 8002850: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + ASSERT(len == 32 || len == 72); // limitation for this project. + 8002854: 2a20 cmp r2, #32 +// +// -- can also lock it. +// + int +ae_write_data_slot(int slot_num, const uint8_t *data, int len, bool lock_it) +{ + 8002856: b085 sub sp, #20 + 8002858: 4605 mov r5, r0 + 800285a: af02 add r7, sp, #8 + 800285c: 4689 mov r9, r1 + 800285e: 4616 mov r6, r2 + 8002860: 461c mov r4, r3 + ASSERT(len == 32 || len == 72); // limitation for this project. + 8002862: d004 beq.n 800286e + 8002864: 2a48 cmp r2, #72 ; 0x48 + 8002866: d002 beq.n 800286e + 8002868: 4836 ldr r0, [pc, #216] ; (8002944 ) + 800286a: f7fd fdaf bl 80003cc + + for(int blk=0; blk<3; blk++) { + // have to write each "block" of 32-bytes, separately + // zone => data + int rv = ae_send_n(OP_Write, 0x80|2, (blk<<8) | (slot_num<<3), data+(blk*32), 32); + 800286e: ea4f 0ac5 mov.w sl, r5, lsl #3 + 8002872: fa1f fa8a uxth.w sl, sl + 8002876: f04f 0800 mov.w r8, #0 + 800287a: f04f 0b20 mov.w fp, #32 + 800287e: ea4a 2208 orr.w r2, sl, r8, lsl #8 + 8002882: b292 uxth r2, r2 + 8002884: f8cd b000 str.w fp, [sp] + 8002888: eb09 1348 add.w r3, r9, r8, lsl #5 + 800288c: 2182 movs r1, #130 ; 0x82 + 800288e: 2012 movs r0, #18 + 8002890: f7ff fd40 bl 8002314 + RET_IF_BAD(rv); + 8002894: 2800 cmp r0, #0 + 8002896: d150 bne.n 800293a + + ae_delay(OP_Write); + 8002898: 2012 movs r0, #18 + 800289a: f7ff fd89 bl 80023b0 + + rv = ae_read1(); + 800289e: f7ff fcc7 bl 8002230 + RET_IF_BAD(rv); + 80028a2: 2800 cmp r0, #0 + 80028a4: d149 bne.n 800293a + + if(len == 32) break; + 80028a6: 2e20 cmp r6, #32 + 80028a8: d004 beq.n 80028b4 + int +ae_write_data_slot(int slot_num, const uint8_t *data, int len, bool lock_it) +{ + ASSERT(len == 32 || len == 72); // limitation for this project. + + for(int blk=0; blk<3; blk++) { + 80028aa: f108 0801 add.w r8, r8, #1 + 80028ae: f1b8 0f03 cmp.w r8, #3 + 80028b2: d1e4 bne.n 800287e + RET_IF_BAD(rv); + + if(len == 32) break; + } + + if(lock_it) { + 80028b4: 2c00 cmp r4, #0 + 80028b6: d03f beq.n 8002938 + ASSERT(slot_num != 8); // no support for mega slot 8 + 80028b8: 2d08 cmp r5, #8 + RET_IF_BAD(rv); + + if(len == 32) break; + } + + if(lock_it) { + 80028ba: 466c mov r4, sp + ASSERT(slot_num != 8); // no support for mega slot 8 + 80028bc: d107 bne.n 80028ce + 80028be: 4821 ldr r0, [pc, #132] ; (8002944 ) + 80028c0: f7fd fd84 bl 80003cc + ASSERT(len == 32); + 80028c4: 2e20 cmp r6, #32 + 80028c6: d104 bne.n 80028d2 + + // Assume 36/72-byte long slot, which will be partially written, and rest + // should be ones. + const int slot_len = (slot_num <= 7) ? 36 : 72; + 80028c8: f04f 0848 mov.w r8, #72 ; 0x48 + 80028cc: e008 b.n 80028e0 + if(len == 32) break; + } + + if(lock_it) { + ASSERT(slot_num != 8); // no support for mega slot 8 + ASSERT(len == 32); + 80028ce: 2e20 cmp r6, #32 + 80028d0: d002 beq.n 80028d8 + 80028d2: 481c ldr r0, [pc, #112] ; (8002944 ) + 80028d4: f7fd fd7a bl 80003cc + + // Assume 36/72-byte long slot, which will be partially written, and rest + // should be ones. + const int slot_len = (slot_num <= 7) ? 36 : 72; + 80028d8: 2d07 cmp r5, #7 + 80028da: dcf5 bgt.n 80028c8 + 80028dc: f04f 0824 mov.w r8, #36 ; 0x24 + uint8_t copy[slot_len]; + 80028e0: f108 0307 add.w r3, r8, #7 + 80028e4: f023 0307 bic.w r3, r3, #7 + 80028e8: ebad 0d03 sub.w sp, sp, r3 + 80028ec: ab02 add r3, sp, #8 + memset(copy, 0xff, slot_len); + 80028ee: 4618 mov r0, r3 + 80028f0: 4642 mov r2, r8 + 80028f2: 21ff movs r1, #255 ; 0xff + 80028f4: f003 ffec bl 80068d0 + + memcpy(copy, data, len); + 80028f8: 4632 mov r2, r6 + 80028fa: 4649 mov r1, r9 + 80028fc: f003 ffc2 bl 8006884 + + // calc expected CRC + uint8_t crc[2] = {0, 0}; + 8002900: 2200 movs r2, #0 + crc16_chain(slot_len, copy, crc); + 8002902: 4601 mov r1, r0 + memset(copy, 0xff, slot_len); + + memcpy(copy, data, len); + + // calc expected CRC + uint8_t crc[2] = {0, 0}; + 8002904: 713a strb r2, [r7, #4] + 8002906: 717a strb r2, [r7, #5] + crc16_chain(slot_len, copy, crc); + 8002908: 4640 mov r0, r8 + 800290a: 1d3a adds r2, r7, #4 + 800290c: f7ff fb6e bl 8001fec + + // do the lock + int rv = ae_send(OP_Lock, 2 | (slot_num << 2), (crc[1]<<8) | crc[0]); + 8002910: 797a ldrb r2, [r7, #5] + 8002912: 793b ldrb r3, [r7, #4] + 8002914: 00a9 lsls r1, r5, #2 + 8002916: f041 0102 orr.w r1, r1, #2 + 800291a: ea43 2202 orr.w r2, r3, r2, lsl #8 + 800291e: f001 01fe and.w r1, r1, #254 ; 0xfe + 8002922: 2017 movs r0, #23 + 8002924: f7ff fd32 bl 800238c + RET_IF_BAD(rv); + 8002928: b920 cbnz r0, 8002934 + + ae_delay(OP_Lock); + 800292a: 2017 movs r0, #23 + 800292c: f7ff fd40 bl 80023b0 + + rv = ae_read1(); + 8002930: f7ff fc7e bl 8002230 + uint8_t crc[2] = {0, 0}; + crc16_chain(slot_len, copy, crc); + + // do the lock + int rv = ae_send(OP_Lock, 2 | (slot_num << 2), (crc[1]<<8) | crc[0]); + RET_IF_BAD(rv); + 8002934: 46a5 mov sp, r4 + 8002936: e000 b.n 800293a + + rv = ae_read1(); + RET_IF_BAD(rv); + } + + return 0; + 8002938: 4620 mov r0, r4 +} + 800293a: 370c adds r7, #12 + 800293c: 46bd mov sp, r7 + 800293e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 8002942: bf00 nop + 8002944: 08006940 .word 0x08006940 + +08002948 : + +// ae_encrypted_read() +// + int +ae_encrypted_read(int data_slot, int read_kn, const uint8_t read_key[32], uint8_t *data, int len) +{ + 8002948: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 800294c: b08a sub sp, #40 ; 0x28 + 800294e: 4606 mov r6, r0 + 8002950: 9c10 ldr r4, [sp, #64] ; 0x40 + // not clear if chip supports 4-byte encrypted reads + ASSERT((len == 32) || (len == 72)); + 8002952: 2c20 cmp r4, #32 + +// ae_encrypted_read() +// + int +ae_encrypted_read(int data_slot, int read_kn, const uint8_t read_key[32], uint8_t *data, int len) +{ + 8002954: 460f mov r7, r1 + 8002956: 4690 mov r8, r2 + 8002958: 461d mov r5, r3 + // not clear if chip supports 4-byte encrypted reads + ASSERT((len == 32) || (len == 72)); + 800295a: d004 beq.n 8002966 + 800295c: 2c48 cmp r4, #72 ; 0x48 + 800295e: d002 beq.n 8002966 + 8002960: 4814 ldr r0, [pc, #80] ; (80029b4 ) + 8002962: f7fd fd33 bl 80003cc + + int rv = ae_encrypted_read32(data_slot, 0, read_kn, read_key, data); + 8002966: 9500 str r5, [sp, #0] + 8002968: 4643 mov r3, r8 + 800296a: 463a mov r2, r7 + 800296c: 2100 movs r1, #0 + 800296e: 4630 mov r0, r6 + 8002970: f7ff fe78 bl 8002664 + RET_IF_BAD(rv); + 8002974: b9d0 cbnz r0, 80029ac + + if(len == 32) return 0; + 8002976: 2c20 cmp r4, #32 + 8002978: d018 beq.n 80029ac + + rv = ae_encrypted_read32(data_slot, 1, read_kn, read_key, data+32); + 800297a: f105 0320 add.w r3, r5, #32 + 800297e: 9300 str r3, [sp, #0] + 8002980: 463a mov r2, r7 + 8002982: 4643 mov r3, r8 + 8002984: 2101 movs r1, #1 + 8002986: 4630 mov r0, r6 + 8002988: f7ff fe6c bl 8002664 + RET_IF_BAD(rv); + 800298c: b970 cbnz r0, 80029ac + + uint8_t tmp[32]; + rv = ae_encrypted_read32(data_slot, 2, read_kn, read_key, tmp); + 800298e: ac02 add r4, sp, #8 + 8002990: 4643 mov r3, r8 + 8002992: 9400 str r4, [sp, #0] + 8002994: 463a mov r2, r7 + 8002996: 2102 movs r1, #2 + 8002998: 4630 mov r0, r6 + 800299a: f7ff fe63 bl 8002664 + RET_IF_BAD(rv); + 800299e: 4603 mov r3, r0 + 80029a0: b918 cbnz r0, 80029aa + + memcpy(data+64, tmp, 72-64); + 80029a2: 4622 mov r2, r4 + 80029a4: ca03 ldmia r2!, {r0, r1} + 80029a6: 6428 str r0, [r5, #64] ; 0x40 + 80029a8: 6469 str r1, [r5, #68] ; 0x44 + 80029aa: 4618 mov r0, r3 + + return 0; +} + 80029ac: b00a add sp, #40 ; 0x28 + 80029ae: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 80029b2: bf00 nop + 80029b4: 08006940 .word 0x08006940 + +080029b8 : +// ae_encrypted_write() +// + int +ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32], + const uint8_t *data, int len) +{ + 80029b8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + // + SHA256_CTX ctx; + sha256_init(&ctx); + + uint8_t p1 = 0x80|2; // 32 bytes into a data slot + uint8_t p2_lsb = (data_slot << 3); + 80029bc: 00c0 lsls r0, r0, #3 +// ae_encrypted_write() +// + int +ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32], + const uint8_t *data, int len) +{ + 80029be: b0cf sub sp, #316 ; 0x13c + // + SHA256_CTX ctx; + sha256_init(&ctx); + + uint8_t p1 = 0x80|2; // 32 bytes into a data slot + uint8_t p2_lsb = (data_slot << 3); + 80029c0: b2c7 uxtb r7, r0 +// ae_encrypted_write() +// + int +ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32], + const uint8_t *data, int len) +{ + 80029c2: 9306 str r3, [sp, #24] + 80029c4: 9e58 ldr r6, [sp, #352] ; 0x160 + 80029c6: 9104 str r1, [sp, #16] + sha256_update(&ctx, zeros, sizeof(zeros)); + sha256_update(&ctx, data, 32); + + sha256_final(&ctx, &body[32]); + + rv = ae_send_n(OP_Write, p1, (p2_msb << 8) | p2_lsb, body, sizeof(body)); + 80029c8: b2bb uxth r3, r7 +// ae_encrypted_write() +// + int +ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32], + const uint8_t *data, int len) +{ + 80029ca: 9205 str r2, [sp, #20] + sha256_update(&ctx, zeros, sizeof(zeros)); + sha256_update(&ctx, data, 32); + + sha256_final(&ctx, &body[32]); + + rv = ae_send_n(OP_Write, p1, (p2_msb << 8) | p2_lsb, body, sizeof(body)); + 80029cc: 9303 str r3, [sp, #12] +// + int +ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32], + const uint8_t *data, int len) +{ + for(int blk=0; blk<3 && len>0; blk++, len-=32) { + 80029ce: 2500 movs r5, #0 + int here = MIN(32, len); + + // be nice and don't read past end of input buffer + uint8_t tmp[32] = { 0 }; + 80029d0: f10d 0848 add.w r8, sp, #72 ; 0x48 +// + int +ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32], + const uint8_t *data, int len) +{ + for(int blk=0; blk<3 && len>0; blk++, len-=32) { + 80029d4: 2e00 cmp r6, #0 + 80029d6: dd75 ble.n 8002ac4 + int here = MIN(32, len); + + // be nice and don't read past end of input buffer + uint8_t tmp[32] = { 0 }; + 80029d8: 2220 movs r2, #32 + 80029da: 2100 movs r1, #0 + 80029dc: 4640 mov r0, r8 + 80029de: f003 ff77 bl 80068d0 + memcpy(tmp, data+(32*blk), here); + 80029e2: 9b06 ldr r3, [sp, #24] + 80029e4: 2e20 cmp r6, #32 + 80029e6: 4632 mov r2, r6 + 80029e8: eb03 1145 add.w r1, r3, r5, lsl #5 + 80029ec: bfa8 it ge + 80029ee: 2220 movge r2, #32 + 80029f0: 4640 mov r0, r8 + 80029f2: f003 ff47 bl 8006884 +ae_encrypted_write32(int data_slot, int blk, int write_kn, + const uint8_t write_key[32], const uint8_t data[32]) +{ + uint8_t digest[32]; + + ae_keep_alive(); + 80029f6: f7ff fc11 bl 800221c + ae_pair_unlock(); + 80029fa: f7ff fe2d bl 8002658 + + // generate a hash over shared secret and rng + int rv = ae_gendig_slot(write_kn, write_key, digest); + 80029fe: aa1a add r2, sp, #104 ; 0x68 + 8002a00: 9905 ldr r1, [sp, #20] + 8002a02: 9804 ldr r0, [sp, #16] + 8002a04: f7ff fd4e bl 80024a4 + RET_IF_BAD(rv); + 8002a08: 2800 cmp r0, #0 + 8002a0a: d155 bne.n 8002ab8 + 8002a0c: 4604 mov r4, r0 + + // encrypt the data to be written, and append an authenticating MAC + uint8_t body[32 + 32]; + + for(int i=0; i<32; i++) { + body[i] = data[i] ^ digest[i]; + 8002a0e: ab1a add r3, sp, #104 ; 0x68 + 8002a10: f818 1004 ldrb.w r1, [r8, r4] + 8002a14: 5ce2 ldrb r2, [r4, r3] + 8002a16: f10d 0b88 add.w fp, sp, #136 ; 0x88 + 8002a1a: 404a eors r2, r1 + 8002a1c: f804 200b strb.w r2, [r4, fp] + RET_IF_BAD(rv); + + // encrypt the data to be written, and append an authenticating MAC + uint8_t body[32 + 32]; + + for(int i=0; i<32; i++) { + 8002a20: 3401 adds r4, #1 + 8002a22: 2c20 cmp r4, #32 + 8002a24: d1f3 bne.n 8002a0e + // + (b'\0'*25) + // + new_value) + // assert len(msg) == 32+1+1+2+1+2+25+32 + // + SHA256_CTX ctx; + sha256_init(&ctx); + 8002a26: a832 add r0, sp, #200 ; 0xc8 + 8002a28: 9307 str r3, [sp, #28] + 8002a2a: f002 fcaf bl 800538c + + uint8_t p1 = 0x80|2; // 32 bytes into a data slot + uint8_t p2_lsb = (data_slot << 3); + uint8_t p2_msb = blk; + + uint8_t args[7] = { OP_Write, p1, p2_lsb, p2_msb, 0xEE, 0x01, 0x23 }; + 8002a2e: 22ee movs r2, #238 ; 0xee + 8002a30: f88d 2028 strb.w r2, [sp, #40] ; 0x28 + 8002a34: 2201 movs r2, #1 + 8002a36: f88d 2029 strb.w r2, [sp, #41] ; 0x29 + 8002a3a: 2223 movs r2, #35 ; 0x23 + 8002a3c: f04f 0912 mov.w r9, #18 + 8002a40: f04f 0a82 mov.w sl, #130 ; 0x82 + 8002a44: f88d 202a strb.w r2, [sp, #42] ; 0x2a + uint8_t zeros[25] = { 0 }; + 8002a48: 2100 movs r1, #0 + 8002a4a: 2219 movs r2, #25 + 8002a4c: a80b add r0, sp, #44 ; 0x2c + + uint8_t p1 = 0x80|2; // 32 bytes into a data slot + uint8_t p2_lsb = (data_slot << 3); + uint8_t p2_msb = blk; + + uint8_t args[7] = { OP_Write, p1, p2_lsb, p2_msb, 0xEE, 0x01, 0x23 }; + 8002a4e: f88d 9024 strb.w r9, [sp, #36] ; 0x24 + 8002a52: f88d a025 strb.w sl, [sp, #37] ; 0x25 + 8002a56: f88d 7026 strb.w r7, [sp, #38] ; 0x26 + 8002a5a: f88d 5027 strb.w r5, [sp, #39] ; 0x27 + uint8_t zeros[25] = { 0 }; + 8002a5e: f003 ff37 bl 80068d0 + + sha256_update(&ctx, digest, 32); + 8002a62: 9b07 ldr r3, [sp, #28] + 8002a64: 4622 mov r2, r4 + 8002a66: 4619 mov r1, r3 + 8002a68: a832 add r0, sp, #200 ; 0xc8 + 8002a6a: f002 fcb9 bl 80053e0 + sha256_update(&ctx, args, sizeof(args)); + 8002a6e: 2207 movs r2, #7 + 8002a70: a909 add r1, sp, #36 ; 0x24 + 8002a72: a832 add r0, sp, #200 ; 0xc8 + 8002a74: f002 fcb4 bl 80053e0 + sha256_update(&ctx, zeros, sizeof(zeros)); + 8002a78: 2219 movs r2, #25 + 8002a7a: a90b add r1, sp, #44 ; 0x2c + 8002a7c: a832 add r0, sp, #200 ; 0xc8 + 8002a7e: f002 fcaf bl 80053e0 + sha256_update(&ctx, data, 32); + 8002a82: 4622 mov r2, r4 + 8002a84: 4641 mov r1, r8 + 8002a86: a832 add r0, sp, #200 ; 0xc8 + 8002a88: f002 fcaa bl 80053e0 + + sha256_final(&ctx, &body[32]); + 8002a8c: a92a add r1, sp, #168 ; 0xa8 + 8002a8e: a832 add r0, sp, #200 ; 0xc8 + 8002a90: f002 fcc4 bl 800541c + + rv = ae_send_n(OP_Write, p1, (p2_msb << 8) | p2_lsb, body, sizeof(body)); + 8002a94: 9903 ldr r1, [sp, #12] + 8002a96: 022a lsls r2, r5, #8 + 8002a98: 2340 movs r3, #64 ; 0x40 + 8002a9a: f402 427f and.w r2, r2, #65280 ; 0xff00 + 8002a9e: 9300 str r3, [sp, #0] + 8002aa0: 430a orrs r2, r1 + 8002aa2: 465b mov r3, fp + 8002aa4: 4651 mov r1, sl + 8002aa6: 4648 mov r0, r9 + 8002aa8: f7ff fc34 bl 8002314 + RET_IF_BAD(rv); + 8002aac: b920 cbnz r0, 8002ab8 + + ae_delay(OP_Write); + 8002aae: 4648 mov r0, r9 + 8002ab0: f7ff fc7e bl 80023b0 + + rv = ae_read1(); + 8002ab4: f7ff fbbc bl 8002230 + // be nice and don't read past end of input buffer + uint8_t tmp[32] = { 0 }; + memcpy(tmp, data+(32*blk), here); + + int rv = ae_encrypted_write32(data_slot, blk, write_kn, write_key, tmp); + RET_IF_BAD(rv); + 8002ab8: b928 cbnz r0, 8002ac6 +// + int +ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32], + const uint8_t *data, int len) +{ + for(int blk=0; blk<3 && len>0; blk++, len-=32) { + 8002aba: 3501 adds r5, #1 + 8002abc: 2d03 cmp r5, #3 + 8002abe: f1a6 0620 sub.w r6, r6, #32 + 8002ac2: d187 bne.n 80029d4 + + int rv = ae_encrypted_write32(data_slot, blk, write_kn, write_key, tmp); + RET_IF_BAD(rv); + } + + return 0; + 8002ac4: 2000 movs r0, #0 +} + 8002ac6: b04f add sp, #316 ; 0x13c + 8002ac8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +08002acc : + +// ae_read_data_slot() +// + int +ae_read_data_slot(int slot_num, uint8_t *data, int len) +{ + 8002acc: b570 push {r4, r5, r6, lr} + ASSERT((len == 4) || (len == 32) || (len == 72)); + 8002ace: 2a04 cmp r2, #4 + +// ae_read_data_slot() +// + int +ae_read_data_slot(int slot_num, uint8_t *data, int len) +{ + 8002ad0: b088 sub sp, #32 + 8002ad2: 4605 mov r5, r0 + 8002ad4: 460c mov r4, r1 + 8002ad6: 4616 mov r6, r2 + ASSERT((len == 4) || (len == 32) || (len == 72)); + 8002ad8: d007 beq.n 8002aea + 8002ada: 2a20 cmp r2, #32 + 8002adc: d040 beq.n 8002b60 + 8002ade: 2a48 cmp r2, #72 ; 0x48 + 8002ae0: d03e beq.n 8002b60 + 8002ae2: 4821 ldr r0, [pc, #132] ; (8002b68 ) + 8002ae4: f7fd fc72 bl 80003cc + 8002ae8: e03a b.n 8002b60 + + // zone => data + // only reading first block of 32 bytes. ignore the rest + int rv = ae_send(OP_Read, (len == 4 ? 0x00 : 0x80) | 2, (slot_num<<3)); + 8002aea: 2102 movs r1, #2 + 8002aec: 00ed lsls r5, r5, #3 + 8002aee: b2ad uxth r5, r5 + 8002af0: 462a mov r2, r5 + 8002af2: 2002 movs r0, #2 + 8002af4: f7ff fc4a bl 800238c + RET_IF_BAD(rv); + 8002af8: bba0 cbnz r0, 8002b64 + + ae_delay(OP_Read); + 8002afa: 2002 movs r0, #2 + 8002afc: f7ff fc58 bl 80023b0 + + rv = ae_read_n((len == 4) ? 4 : 32, data); + 8002b00: 2e04 cmp r6, #4 + 8002b02: bf0c ite eq + 8002b04: 2004 moveq r0, #4 + 8002b06: 2020 movne r0, #32 + 8002b08: 4621 mov r1, r4 + 8002b0a: f7ff fbbd bl 8002288 + RET_IF_BAD(rv); + 8002b0e: bb48 cbnz r0, 8002b64 + + if(len == 72) { + 8002b10: 2e48 cmp r6, #72 ; 0x48 + 8002b12: d127 bne.n 8002b64 + // read second block + int rv = ae_send(OP_Read, 0x82, (1<<8) | (slot_num<<3)); + 8002b14: f445 7280 orr.w r2, r5, #256 ; 0x100 + 8002b18: 2182 movs r1, #130 ; 0x82 + 8002b1a: 2002 movs r0, #2 + 8002b1c: f7ff fc36 bl 800238c + RET_IF_BAD(rv); + 8002b20: bb00 cbnz r0, 8002b64 + + ae_delay(OP_Read); + 8002b22: 2002 movs r0, #2 + 8002b24: f7ff fc44 bl 80023b0 + + rv = ae_read_n(32, data+32); + 8002b28: f104 0120 add.w r1, r4, #32 + 8002b2c: 2020 movs r0, #32 + 8002b2e: f7ff fbab bl 8002288 + RET_IF_BAD(rv); + 8002b32: b9b8 cbnz r0, 8002b64 + + // read third block, but only using part of it + uint8_t tmp[32]; + rv = ae_send(OP_Read, 0x82, (2<<8) | (slot_num<<3)); + 8002b34: f445 7200 orr.w r2, r5, #512 ; 0x200 + 8002b38: 2182 movs r1, #130 ; 0x82 + 8002b3a: 2002 movs r0, #2 + 8002b3c: f7ff fc26 bl 800238c + RET_IF_BAD(rv); + 8002b40: b980 cbnz r0, 8002b64 + + ae_delay(OP_Read); + 8002b42: 2002 movs r0, #2 + 8002b44: f7ff fc34 bl 80023b0 + + rv = ae_read_n(32, tmp); + 8002b48: 4669 mov r1, sp + 8002b4a: 2020 movs r0, #32 + 8002b4c: f7ff fb9c bl 8002288 + RET_IF_BAD(rv); + 8002b50: 4603 mov r3, r0 + 8002b52: b918 cbnz r0, 8002b5c + + memcpy(data+64, tmp, 72-64); + 8002b54: 466a mov r2, sp + 8002b56: ca03 ldmia r2!, {r0, r1} + 8002b58: 6420 str r0, [r4, #64] ; 0x40 + 8002b5a: 6461 str r1, [r4, #68] ; 0x44 + 8002b5c: 4618 mov r0, r3 + 8002b5e: e001 b.n 8002b64 +{ + ASSERT((len == 4) || (len == 32) || (len == 72)); + + // zone => data + // only reading first block of 32 bytes. ignore the rest + int rv = ae_send(OP_Read, (len == 4 ? 0x00 : 0x80) | 2, (slot_num<<3)); + 8002b60: 2182 movs r1, #130 ; 0x82 + 8002b62: e7c3 b.n 8002aec + + memcpy(data+64, tmp, 72-64); + } + + return 0; +} + 8002b64: b008 add sp, #32 + 8002b66: bd70 pop {r4, r5, r6, pc} + 8002b68: 08006940 .word 0x08006940 + +08002b6c : + +// ae_sha256() +// + int +ae_sha256(const uint8_t *msg, int msg_len, uint8_t digest[32]) +{ + 8002b6c: e92d 41f3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, lr} + 8002b70: 4616 mov r6, r2 + // setup + int rv = ae_send(OP_SHA, 0x00, 0); + 8002b72: 2200 movs r2, #0 + +// ae_sha256() +// + int +ae_sha256(const uint8_t *msg, int msg_len, uint8_t digest[32]) +{ + 8002b74: 4607 mov r7, r0 + 8002b76: 460d mov r5, r1 + // setup + int rv = ae_send(OP_SHA, 0x00, 0); + 8002b78: 2047 movs r0, #71 ; 0x47 + 8002b7a: 4611 mov r1, r2 + 8002b7c: f7ff fc06 bl 800238c + RET_IF_BAD(rv); + 8002b80: bb90 cbnz r0, 8002be8 + + ae_delay(OP_SHA); + 8002b82: 2047 movs r0, #71 ; 0x47 + 8002b84: f7ff fc14 bl 80023b0 + + rv = ae_read1(); + 8002b88: f7ff fb52 bl 8002230 + if(rv != AE_COMMAND_OK) return -1; + 8002b8c: b918 cbnz r0, 8002b96 + 8002b8e: 462c mov r4, r5 + + while(msg_len >= 64) { + rv = ae_send_n(OP_SHA, 0x01, 64, msg, 64); + 8002b90: f04f 0840 mov.w r8, #64 ; 0x40 + 8002b94: e012 b.n 8002bbc + RET_IF_BAD(rv); + + ae_delay(OP_SHA); + + rv = ae_read1(); + if(rv != AE_COMMAND_OK) return -1; + 8002b96: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff + 8002b9a: e025 b.n 8002be8 + + while(msg_len >= 64) { + rv = ae_send_n(OP_SHA, 0x01, 64, msg, 64); + 8002b9c: f8cd 8000 str.w r8, [sp] + 8002ba0: 2240 movs r2, #64 ; 0x40 + 8002ba2: 2101 movs r1, #1 + 8002ba4: 2047 movs r0, #71 ; 0x47 + 8002ba6: f7ff fbb5 bl 8002314 + RET_IF_BAD(rv); + 8002baa: b9e8 cbnz r0, 8002be8 + ae_delay(OP_SHA); + 8002bac: 2047 movs r0, #71 ; 0x47 + 8002bae: f7ff fbff bl 80023b0 + + rv = ae_read1(); + 8002bb2: f7ff fb3d bl 8002230 + if(rv != AE_COMMAND_OK) return -1; + 8002bb6: 2800 cmp r0, #0 + 8002bb8: d1ed bne.n 8002b96 + + msg += 64; + msg_len -= 64; + 8002bba: 3c40 subs r4, #64 ; 0x40 + 8002bbc: 1b2b subs r3, r5, r4 + ae_delay(OP_SHA); + + rv = ae_read1(); + if(rv != AE_COMMAND_OK) return -1; + + while(msg_len >= 64) { + 8002bbe: 2c3f cmp r4, #63 ; 0x3f + 8002bc0: 443b add r3, r7 + 8002bc2: dceb bgt.n 8002b9c + msg += 64; + msg_len -= 64; + } + + // finalize, with final 0 to 63 bytes + rv = ae_send_n(OP_SHA, 0x02, msg_len, msg, msg_len); + 8002bc4: b2e2 uxtb r2, r4 + 8002bc6: 9200 str r2, [sp, #0] + 8002bc8: 2102 movs r1, #2 + 8002bca: b2a2 uxth r2, r4 + 8002bcc: 2047 movs r0, #71 ; 0x47 + 8002bce: f7ff fba1 bl 8002314 + RET_IF_BAD(rv); + 8002bd2: b948 cbnz r0, 8002be8 + + ae_delay(OP_SHA); + 8002bd4: 2047 movs r0, #71 ; 0x47 + 8002bd6: f7ff fbeb bl 80023b0 + + rv = ae_read_n(32, digest); + 8002bda: 4631 mov r1, r6 + 8002bdc: 2020 movs r0, #32 + RET_IF_BAD(rv); + + return 0; +} + 8002bde: b002 add sp, #8 + 8002be0: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} + rv = ae_send_n(OP_SHA, 0x02, msg_len, msg, msg_len); + RET_IF_BAD(rv); + + ae_delay(OP_SHA); + + rv = ae_read_n(32, digest); + 8002be4: f7ff bb50 b.w 8002288 + RET_IF_BAD(rv); + + return 0; +} + 8002be8: b002 add sp, #8 + 8002bea: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +08002bee : + +// ae_set_gpio() +// + int +ae_set_gpio(int state) +{ + 8002bee: b513 push {r0, r1, r4, lr} + // 1=turn on green, 0=red light (if not yet configured to be secure) + int rv = ae_send(OP_Info, 3, 2 | (!!state)); + 8002bf0: 2800 cmp r0, #0 + 8002bf2: bf14 ite ne + 8002bf4: 2203 movne r2, #3 + 8002bf6: 2202 moveq r2, #2 + 8002bf8: 4604 mov r4, r0 + 8002bfa: 2103 movs r1, #3 + 8002bfc: 2030 movs r0, #48 ; 0x30 + 8002bfe: f7ff fbc5 bl 800238c + RET_IF_BAD(rv); + 8002c02: b968 cbnz r0, 8002c20 + + ae_delay(OP_Info); + 8002c04: 2030 movs r0, #48 ; 0x30 + 8002c06: f7ff fbd3 bl 80023b0 + + // "Always return the current state in the first byte followed by three bytes of 0x00" + // - simple 1/0, in LSB. + uint8_t resp[4]; + + rv = ae_read_n(4, resp); + 8002c0a: a901 add r1, sp, #4 + 8002c0c: 2004 movs r0, #4 + 8002c0e: f7ff fb3b bl 8002288 + RET_IF_BAD(rv); + 8002c12: b928 cbnz r0, 8002c20 + + return (resp[0] != state) ? -1 : 0; + 8002c14: f89d 0004 ldrb.w r0, [sp, #4] + 8002c18: 1b00 subs r0, r0, r4 + 8002c1a: bf18 it ne + 8002c1c: f04f 30ff movne.w r0, #4294967295 ; 0xffffffff +} + 8002c20: b002 add sp, #8 + 8002c22: bd10 pop {r4, pc} + +08002c24 : +// +// Set the GPIO using secure hash generated somehow already. +// + int +ae_set_gpio_secure(uint8_t digest[32]) +{ + 8002c24: b510 push {r4, lr} + 8002c26: 4604 mov r4, r0 + ae_pair_unlock(); + 8002c28: f7ff fd16 bl 8002658 + ae_checkmac(KEYNUM_firmware, digest); + 8002c2c: 4621 mov r1, r4 + 8002c2e: 200e movs r0, #14 + 8002c30: f7ff fc8e bl 8002550 + + return ae_set_gpio(1); + 8002c34: 2001 movs r0, #1 +} + 8002c36: e8bd 4010 ldmia.w sp!, {r4, lr} +ae_set_gpio_secure(uint8_t digest[32]) +{ + ae_pair_unlock(); + ae_checkmac(KEYNUM_firmware, digest); + + return ae_set_gpio(1); + 8002c3a: f7ff bfd8 b.w 8002bee + +08002c3e : +// +// Do Info(p1=3) command, and return result. +// + uint8_t +ae_get_gpio(void) +{ + 8002c3e: b507 push {r0, r1, r2, lr} + // not doing error checking here + ae_send(OP_Info, 0x3, 0); + 8002c40: 2200 movs r2, #0 + 8002c42: 2103 movs r1, #3 + 8002c44: 2030 movs r0, #48 ; 0x30 + 8002c46: f7ff fba1 bl 800238c + + ae_delay(OP_Info); + 8002c4a: 2030 movs r0, #48 ; 0x30 + 8002c4c: f7ff fbb0 bl 80023b0 + + // note: always returns 4 bytes, but most are garbage and unused. + uint8_t tmp[4]; + ae_read_n(4, tmp); + 8002c50: a901 add r1, sp, #4 + 8002c52: 2004 movs r0, #4 + 8002c54: f7ff fb18 bl 8002288 + + return tmp[0]; +} + 8002c58: f89d 0004 ldrb.w r0, [sp, #4] + 8002c5c: b003 add sp, #12 + 8002c5e: f85d fb04 ldr.w pc, [sp], #4 + +08002c62 : +// +// Read a 4-byte area from config area, or -1 if fail. +// + int +ae_read_config_word(int offset, uint8_t *dest) +{ + 8002c62: b510 push {r4, lr} + offset &= 0x7f; + + // read 32 bits (aligned) + int rv = ae_send(OP_Read, 0x00, offset/4); + 8002c64: f3c0 0284 ubfx r2, r0, #2, #5 +// +// Read a 4-byte area from config area, or -1 if fail. +// + int +ae_read_config_word(int offset, uint8_t *dest) +{ + 8002c68: 460c mov r4, r1 + offset &= 0x7f; + + // read 32 bits (aligned) + int rv = ae_send(OP_Read, 0x00, offset/4); + 8002c6a: 2002 movs r0, #2 + 8002c6c: 2100 movs r1, #0 + 8002c6e: f7ff fb8d bl 800238c + if(rv) return -1; + 8002c72: b958 cbnz r0, 8002c8c + + ae_delay(OP_Read); + 8002c74: 2002 movs r0, #2 + 8002c76: f7ff fb9b bl 80023b0 + + rv = ae_read_n(4, dest); + 8002c7a: 4621 mov r1, r4 + 8002c7c: 2004 movs r0, #4 + 8002c7e: f7ff fb03 bl 8002288 + if(rv) return -1; + 8002c82: 3000 adds r0, #0 + 8002c84: bf18 it ne + 8002c86: 2001 movne r0, #1 + 8002c88: 4240 negs r0, r0 + 8002c8a: bd10 pop {r4, pc} +{ + offset &= 0x7f; + + // read 32 bits (aligned) + int rv = ae_send(OP_Read, 0x00, offset/4); + if(rv) return -1; + 8002c8c: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff + + rv = ae_read_n(4, dest); + if(rv) return -1; + + return 0; +} + 8002c90: bd10 pop {r4, pc} + ... + +08002c94 : +// +// Read a byte from config area. +// + int +ae_read_config_byte(int offset) +{ + 8002c94: b513 push {r0, r1, r4, lr} + uint8_t tmp[4]; + + ae_read_config_word(offset, tmp); + 8002c96: a901 add r1, sp, #4 +// +// Read a byte from config area. +// + int +ae_read_config_byte(int offset) +{ + 8002c98: 4604 mov r4, r0 + uint8_t tmp[4]; + + ae_read_config_word(offset, tmp); + 8002c9a: f7ff ffe2 bl 8002c62 + + return tmp[offset % 4]; + 8002c9e: 4b07 ldr r3, [pc, #28] ; (8002cbc ) + 8002ca0: 4023 ands r3, r4 + 8002ca2: 2b00 cmp r3, #0 + 8002ca4: bfbe ittt lt + 8002ca6: f103 33ff addlt.w r3, r3, #4294967295 ; 0xffffffff + 8002caa: f063 0303 ornlt r3, r3, #3 + 8002cae: 3301 addlt r3, #1 + 8002cb0: aa02 add r2, sp, #8 + 8002cb2: 4413 add r3, r2 +} + 8002cb4: f813 0c04 ldrb.w r0, [r3, #-4] + 8002cb8: b002 add sp, #8 + 8002cba: bd10 pop {r4, pc} + 8002cbc: 80000003 .word 0x80000003 + +08002cc0 : + +// ae_destroy_key() +// + int +ae_destroy_key(int keynum) +{ + 8002cc0: b510 push {r4, lr} + 8002cc2: b090 sub sp, #64 ; 0x40 + uint8_t numin[20]; + + // Load tempkey with a known (random) nonce value + rng_buffer(numin, sizeof(numin)); + 8002cc4: 2114 movs r1, #20 + +// ae_destroy_key() +// + int +ae_destroy_key(int keynum) +{ + 8002cc6: 4604 mov r4, r0 + uint8_t numin[20]; + + // Load tempkey with a known (random) nonce value + rng_buffer(numin, sizeof(numin)); + 8002cc8: a803 add r0, sp, #12 + 8002cca: f7ff f927 bl 8001f1c + int rv = ae_send_n(OP_Nonce, 0, 0, numin, 20); + 8002cce: 2314 movs r3, #20 + 8002cd0: 2200 movs r2, #0 + 8002cd2: 9300 str r3, [sp, #0] + 8002cd4: 4611 mov r1, r2 + 8002cd6: ab03 add r3, sp, #12 + 8002cd8: 2016 movs r0, #22 + 8002cda: f7ff fb1b bl 8002314 + RET_IF_BAD(rv); + 8002cde: b9a8 cbnz r0, 8002d0c + + ae_delay(OP_Nonce); + 8002ce0: 2016 movs r0, #22 + 8002ce2: f7ff fb65 bl 80023b0 + + // Nonce command returns the RNG result, not contents of TempKey, + // but since we are destroying, no need to calculate what it is. + uint8_t randout[32]; + rv = ae_read_n(32, randout); + 8002ce6: a908 add r1, sp, #32 + 8002ce8: 2020 movs r0, #32 + 8002cea: f7ff facd bl 8002288 + RET_IF_BAD(rv); + 8002cee: b968 cbnz r0, 8002d0c + + // do a "DeriveKey" operation, based on that! + rv = ae_send(OP_DeriveKey, 0x00, keynum); + 8002cf0: 4601 mov r1, r0 + 8002cf2: b2a2 uxth r2, r4 + 8002cf4: 201c movs r0, #28 + 8002cf6: f7ff fb49 bl 800238c + if(rv) return -1; + 8002cfa: b928 cbnz r0, 8002d08 + + ae_delay(OP_DeriveKey); + 8002cfc: 201c movs r0, #28 + 8002cfe: f7ff fb57 bl 80023b0 + + return ae_read1(); + 8002d02: f7ff fa95 bl 8002230 + 8002d06: e001 b.n 8002d0c + rv = ae_read_n(32, randout); + RET_IF_BAD(rv); + + // do a "DeriveKey" operation, based on that! + rv = ae_send(OP_DeriveKey, 0x00, keynum); + if(rv) return -1; + 8002d08: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff + + ae_delay(OP_DeriveKey); + + return ae_read1(); +} + 8002d0c: b010 add sp, #64 ; 0x40 + 8002d0e: bd10 pop {r4, pc} + +08002d10 : +// us to write the (existing) pairing secret into, they would see the pairing +// secret in cleartext. They could then restore original chip and access freely. +// + int +ae_setup_config(void) +{ + 8002d10: b530 push {r4, r5, lr} + // Is data zone is locked? + // Allow rest of function to happen if it's not. + + // 0x55 = unlocked; 0x00 = locked + bool data_locked = (ae_read_config_byte(86) != 0x55); + 8002d12: 2056 movs r0, #86 ; 0x56 +// us to write the (existing) pairing secret into, they would see the pairing +// secret in cleartext. They could then restore original chip and access freely. +// + int +ae_setup_config(void) +{ + 8002d14: b0c1 sub sp, #260 ; 0x104 + // Is data zone is locked? + // Allow rest of function to happen if it's not. + + // 0x55 = unlocked; 0x00 = locked + bool data_locked = (ae_read_config_byte(86) != 0x55); + 8002d16: f7ff ffbd bl 8002c94 + if(data_locked) return 0; // basically success + 8002d1a: 2855 cmp r0, #85 ; 0x55 + 8002d1c: f040 80e2 bne.w 8002ee4 + 8002d20: 2400 movs r4, #0 + // in there, so start with some readout. + uint8_t config[4 * 32]; + + for(int blk=0; blk<4; blk++) { + // read 32 bytes (aligned) from config "zone" + int rv = ae_send(OP_Read, 0x80, blk<<3); + 8002d22: 00e2 lsls r2, r4, #3 + 8002d24: b292 uxth r2, r2 + 8002d26: 2180 movs r1, #128 ; 0x80 + 8002d28: 2002 movs r0, #2 + 8002d2a: f7ff fb2f bl 800238c + if(rv) return EIO; + 8002d2e: b108 cbz r0, 8002d34 + 8002d30: 2005 movs r0, #5 + 8002d32: e0e5 b.n 8002f00 + + ae_delay(OP_Read); + 8002d34: 2002 movs r0, #2 + 8002d36: f7ff fb3b bl 80023b0 + + rv = ae_read_n(32, &config[32*blk]); + 8002d3a: ab20 add r3, sp, #128 ; 0x80 + 8002d3c: eb03 1144 add.w r1, r3, r4, lsl #5 + 8002d40: 2020 movs r0, #32 + 8002d42: f7ff faa1 bl 8002288 + if(rv) return EIO; + 8002d46: 2800 cmp r0, #0 + 8002d48: d1f2 bne.n 8002d30 + // To lock, we need a CRC over whole thing, but we + // only set a few values... plus the serial number is + // in there, so start with some readout. + uint8_t config[4 * 32]; + + for(int blk=0; blk<4; blk++) { + 8002d4a: 3401 adds r4, #1 + 8002d4c: 2c04 cmp r4, #4 + 8002d4e: d1e8 bne.n 8002d22 + rv = ae_read_n(32, &config[32*blk]); + if(rv) return EIO; + } + + // verify some fixed values + ASSERT(config[0] == 0x01); + 8002d50: f89d 3080 ldrb.w r3, [sp, #128] ; 0x80 + 8002d54: 2b01 cmp r3, #1 + 8002d56: d002 beq.n 8002d5e + 8002d58: 486a ldr r0, [pc, #424] ; (8002f04 ) + 8002d5a: f7fd fb37 bl 80003cc + ASSERT(config[1] == 0x23); + 8002d5e: f89d 3081 ldrb.w r3, [sp, #129] ; 0x81 + 8002d62: 2b23 cmp r3, #35 ; 0x23 + 8002d64: d002 beq.n 8002d6c + 8002d66: 4867 ldr r0, [pc, #412] ; (8002f04 ) + 8002d68: f7fd fb30 bl 80003cc + ASSERT(config[12] == 0xee); + 8002d6c: f89d 308c ldrb.w r3, [sp, #140] ; 0x8c + 8002d70: 2bee cmp r3, #238 ; 0xee + 8002d72: d002 beq.n 8002d7a + 8002d74: 4863 ldr r0, [pc, #396] ; (8002f04 ) + 8002d76: f7fd fb29 bl 80003cc + + uint8_t serial[9]; + memcpy(serial, &config[0], 4); + 8002d7a: ac40 add r4, sp, #256 ; 0x100 + 8002d7c: 9b20 ldr r3, [sp, #128] ; 0x80 + 8002d7e: f844 3df4 str.w r3, [r4, #-244]! + memcpy(&serial[4], &config[8], 5); + 8002d82: ab22 add r3, sp, #136 ; 0x88 + 8002d84: e893 0003 ldmia.w r3, {r0, r1} + 8002d88: 9004 str r0, [sp, #16] + 8002d8a: f88d 1014 strb.w r1, [sp, #20] + + if(check_all_ones(rom_secrets->ae_serial_number, 9)) { + 8002d8e: 485e ldr r0, [pc, #376] ; (8002f08 ) + 8002d90: 2109 movs r1, #9 + 8002d92: f7ff f85b bl 8001e4c + 8002d96: b110 cbz r0, 8002d9e + // flash is empty; remember this serial number + flash_save_ae_serial(serial); + 8002d98: 4620 mov r0, r4 + 8002d9a: f7fe ff1f bl 8001bdc + } + + if(!check_equal(rom_secrets->ae_serial_number, serial, 9)) { + 8002d9e: 2209 movs r2, #9 + 8002da0: 4621 mov r1, r4 + 8002da2: 4859 ldr r0, [pc, #356] ; (8002f08 ) + 8002da4: f7ff f86a bl 8001e7c + 8002da8: 2800 cmp r0, #0 + 8002daa: f000 80a5 beq.w 8002ef8 + // - pick RNG value for words secret (and forget it) + // - set all PIN values to known value (zeros) + // - set all money secrets to knonw value (zeros) + // - lock the data zone + + if(config[87] == 0x55) { + 8002dae: f89d 30d7 ldrb.w r3, [sp, #215] ; 0xd7 + 8002db2: 2b55 cmp r3, #85 ; 0x55 + 8002db4: d14f bne.n 8002e56 + static const uint8_t config_2[] = AE_CHIP_CONFIG_2; + + STATIC_ASSERT(sizeof(config_1) == 84-16); + STATIC_ASSERT(sizeof(config_2) == 128-90); + + memcpy(&config[16], config_1, sizeof(config_1)); + 8002db6: 2244 movs r2, #68 ; 0x44 + 8002db8: 4954 ldr r1, [pc, #336] ; (8002f0c ) + 8002dba: a824 add r0, sp, #144 ; 0x90 + 8002dbc: f003 fd62 bl 8006884 + memcpy(&config[90], config_2, sizeof(config_2)); + 8002dc0: 4b53 ldr r3, [pc, #332] ; (8002f10 ) + 8002dc2: f10d 02da add.w r2, sp, #218 ; 0xda + 8002dc6: f103 0124 add.w r1, r3, #36 ; 0x24 + 8002dca: f853 0b04 ldr.w r0, [r3], #4 + 8002dce: f842 0b04 str.w r0, [r2], #4 + 8002dd2: 428b cmp r3, r1 + 8002dd4: d1f9 bne.n 8002dca + 8002dd6: 881b ldrh r3, [r3, #0] + 8002dd8: 8013 strh r3, [r2, #0] +// + static int +ae_config_write(const uint8_t config[128]) +{ + // send all 128 bytes, less some that can't be written. + for(int n=16; n<128; n+= 4) { + 8002dda: 2410 movs r4, #16 + } + + // Must work on words, since can't write to most of the complete blocks. + // args = write_params(block=n//32, offset=n//4, is_config=True) + // p2 = (block << 3) | offset + int rv = ae_send_n(OP_Write, 0, n/4, &config[n], 4); + 8002ddc: 2504 movs r5, #4 + static int +ae_config_write(const uint8_t config[128]) +{ + // send all 128 bytes, less some that can't be written. + for(int n=16; n<128; n+= 4) { + if((n >= 84) && (n < 90)) { + 8002dde: f1a4 0354 sub.w r3, r4, #84 ; 0x54 + 8002de2: 2b05 cmp r3, #5 + 8002de4: d803 bhi.n 8002dee +// + static int +ae_config_write(const uint8_t config[128]) +{ + // send all 128 bytes, less some that can't be written. + for(int n=16; n<128; n+= 4) { + 8002de6: 3404 adds r4, #4 + 8002de8: 2c80 cmp r4, #128 ; 0x80 + 8002dea: d1f8 bne.n 8002dde + 8002dec: e013 b.n 8002e16 + } + + // Must work on words, since can't write to most of the complete blocks. + // args = write_params(block=n//32, offset=n//4, is_config=True) + // p2 = (block << 3) | offset + int rv = ae_send_n(OP_Write, 0, n/4, &config[n], 4); + 8002dee: ab20 add r3, sp, #128 ; 0x80 + 8002df0: 9500 str r5, [sp, #0] + 8002df2: 4423 add r3, r4 + 8002df4: f3c4 028f ubfx r2, r4, #2, #16 + 8002df8: 2100 movs r1, #0 + 8002dfa: 2012 movs r0, #18 + 8002dfc: f7ff fa8a bl 8002314 + RET_IF_BAD(rv); + 8002e00: b930 cbnz r0, 8002e10 + + ae_delay(OP_Write); + 8002e02: 2012 movs r0, #18 + 8002e04: f7ff fad4 bl 80023b0 + + rv = ae_read1(); + 8002e08: f7ff fa12 bl 8002230 + if(rv) return rv; + 8002e0c: 2800 cmp r0, #0 + 8002e0e: d0ea beq.n 8002de6 + memcpy(&config[16], config_1, sizeof(config_1)); + memcpy(&config[90], config_2, sizeof(config_2)); + + // write it. + if(ae_config_write(config)) { + INCONSISTENT("conf wr"); + 8002e10: 4840 ldr r0, [pc, #256] ; (8002f14 ) + 8002e12: f7fd fadb bl 80003cc + } + + ae_keep_alive(); + 8002e16: f7ff fa01 bl 800221c +// + static int +ae_lock_config_zone(const uint8_t config[128]) +{ + // calc expected CRC + uint8_t crc[2] = {0, 0}; + 8002e1a: 2400 movs r4, #0 + + crc16_chain(128, config, crc); + 8002e1c: aa0e add r2, sp, #56 ; 0x38 + 8002e1e: a920 add r1, sp, #128 ; 0x80 + 8002e20: 2080 movs r0, #128 ; 0x80 +// + static int +ae_lock_config_zone(const uint8_t config[128]) +{ + // calc expected CRC + uint8_t crc[2] = {0, 0}; + 8002e22: f88d 4038 strb.w r4, [sp, #56] ; 0x38 + 8002e26: f88d 4039 strb.w r4, [sp, #57] ; 0x39 + + crc16_chain(128, config, crc); + 8002e2a: f7ff f8df bl 8001fec + + // do the lock: mode=0 + int rv = ae_send(OP_Lock, 0x0, (crc[1]<<8) | crc[0]); + 8002e2e: f89d 2039 ldrb.w r2, [sp, #57] ; 0x39 + 8002e32: f89d 3038 ldrb.w r3, [sp, #56] ; 0x38 + 8002e36: 4621 mov r1, r4 + 8002e38: ea43 2202 orr.w r2, r3, r2, lsl #8 + 8002e3c: 2017 movs r0, #23 + 8002e3e: f7ff faa5 bl 800238c + RET_IF_BAD(rv); + 8002e42: b920 cbnz r0, 8002e4e + + ae_delay(OP_Lock); + 8002e44: 2017 movs r0, #23 + 8002e46: f7ff fab3 bl 80023b0 + + return ae_read1(); + 8002e4a: f7ff f9f1 bl 8002230 + } + + ae_keep_alive(); + + // lock config zone + if(ae_lock_config_zone(config)) { + 8002e4e: b110 cbz r0, 8002e56 + INCONSISTENT("conf lock"); + 8002e50: 4830 ldr r0, [pc, #192] ; (8002f14 ) + 8002e52: f7fd fabb bl 80003cc + // The datazone still unlocked, so no encryption needed (nor possible). + + + // will use zeros for all PIN codes, and secret starting values + uint8_t zeros[72]; + memset(zeros, 0, sizeof(zeros)); + 8002e56: 2248 movs r2, #72 ; 0x48 + 8002e58: 2100 movs r1, #0 + 8002e5a: a80e add r0, sp, #56 ; 0x38 + 8002e5c: f003 fd38 bl 80068d0 + + for(int kn=0; kn<16; kn++) { + 8002e60: 2400 movs r4, #0 + ae_keep_alive(); + 8002e62: f7ff f9db bl 800221c + 8002e66: 1c65 adds r5, r4, #1 + + switch(kn) { + 8002e68: 2c0e cmp r4, #14 + 8002e6a: d82d bhi.n 8002ec8 + 8002e6c: e8df f004 tbb [pc, r4] + 8002e70: 1f100827 .word 0x1f100827 + 8002e74: 1f1f1f1f .word 0x1f1f1f1f + 8002e78: 2222221f .word 0x2222221f + 8002e7c: 1f22 .short 0x1f22 + 8002e7e: 1f .byte 0x1f + 8002e7f: 00 .byte 0x00 + default: + case 15: break; + + case KEYNUM_pairing: + if(ae_write_data_slot(kn, rom_secrets->pairing_secret, 32, false)) { + 8002e80: 4925 ldr r1, [pc, #148] ; (8002f18 ) + 8002e82: 2300 movs r3, #0 + 8002e84: 2220 movs r2, #32 + 8002e86: 2001 movs r0, #1 + 8002e88: f7ff fce2 bl 8002850 + 8002e8c: b3b0 cbz r0, 8002efc + 8002e8e: e00a b.n 8002ea6 + + + case KEYNUM_words: { + // - hmac key for phishing words (and then we forget it) + uint8_t tmp[32]; + rng_buffer(tmp, sizeof(tmp)); + 8002e90: 2120 movs r1, #32 + 8002e92: a806 add r0, sp, #24 + 8002e94: f7ff f842 bl 8001f1c + + if(ae_write_data_slot(kn, tmp, 32, true)) { + 8002e98: 2301 movs r3, #1 + 8002e9a: 2220 movs r2, #32 + 8002e9c: a906 add r1, sp, #24 + 8002e9e: 2002 movs r0, #2 + 8002ea0: f7ff fcd6 bl 8002850 + 8002ea4: b180 cbz r0, 8002ec8 + INCONSISTENT("wr word"); + 8002ea6: 481b ldr r0, [pc, #108] ; (8002f14 ) + 8002ea8: f7fd fa90 bl 80003cc + } + } + break; + 8002eac: e00c b.n 8002ec8 + case KEYNUM_pin_4: + case KEYNUM_lastgood_1: + case KEYNUM_lastgood_2: + case KEYNUM_brickme: + case KEYNUM_firmware: + if(ae_write_data_slot(kn, zeros, 32, false)) { + 8002eae: 2300 movs r3, #0 + 8002eb0: 2220 movs r2, #32 + 8002eb2: e001 b.n 8002eb8 + + case KEYNUM_secret_1: + case KEYNUM_secret_2: + case KEYNUM_secret_3: + case KEYNUM_secret_4: + if(ae_write_data_slot(kn, zeros, 72, false)) { + 8002eb4: 2300 movs r3, #0 + 8002eb6: 2248 movs r2, #72 ; 0x48 + 8002eb8: a90e add r1, sp, #56 ; 0x38 + 8002eba: 4620 mov r0, r4 + 8002ebc: e7f0 b.n 8002ea0 + INCONSISTENT("wr blk 72"); + } + break; + + case 0: + if(ae_write_data_slot(kn, (const uint8_t *)copyright_msg, 32, true)) { + 8002ebe: 2301 movs r3, #1 + 8002ec0: 2220 movs r2, #32 + 8002ec2: 4916 ldr r1, [pc, #88] ; (8002f1c ) + 8002ec4: 2000 movs r0, #0 + 8002ec6: e7df b.n 8002e88 + + // will use zeros for all PIN codes, and secret starting values + uint8_t zeros[72]; + memset(zeros, 0, sizeof(zeros)); + + for(int kn=0; kn<16; kn++) { + 8002ec8: 2d10 cmp r5, #16 + 8002eca: 462c mov r4, r5 + 8002ecc: d1c9 bne.n 8002e62 + break; + } + } + + // lock the data zone and effectively enter normal operation. + ae_keep_alive(); + 8002ece: f7ff f9a5 bl 800221c +ae_lock_data_zone(void) +{ + // NOTE: I haven't been able to calc CRC right, so not using it. + + // do the lock: mode=1 (datazone) + 0x80 (no CRC check) + int rv = ae_send(OP_Lock, 0x81, 0x0000); + 8002ed2: 2200 movs r2, #0 + 8002ed4: 2181 movs r1, #129 ; 0x81 + 8002ed6: 2017 movs r0, #23 + 8002ed8: f7ff fa58 bl 800238c + RET_IF_BAD(rv); + 8002edc: b120 cbz r0, 8002ee8 + } + + // lock the data zone and effectively enter normal operation. + ae_keep_alive(); + if(ae_lock_data_zone()) { + INCONSISTENT("data lock"); + 8002ede: 480d ldr r0, [pc, #52] ; (8002f14 ) + 8002ee0: f7fd fa74 bl 80003cc + } + + return 0; + 8002ee4: 2000 movs r0, #0 + 8002ee6: e00b b.n 8002f00 + + // do the lock: mode=1 (datazone) + 0x80 (no CRC check) + int rv = ae_send(OP_Lock, 0x81, 0x0000); + RET_IF_BAD(rv); + + ae_delay(OP_Lock); + 8002ee8: 2017 movs r0, #23 + 8002eea: f7ff fa61 bl 80023b0 + + return ae_read1(); + 8002eee: f7ff f99f bl 8002230 + } + } + + // lock the data zone and effectively enter normal operation. + ae_keep_alive(); + if(ae_lock_data_zone()) { + 8002ef2: 2800 cmp r0, #0 + 8002ef4: d0f6 beq.n 8002ee4 + 8002ef6: e7f2 b.n 8002ede + } + + if(!check_equal(rom_secrets->ae_serial_number, serial, 9)) { + // write failed? + // we're already linked to a different chip? Write failed? + return EPERM; + 8002ef8: 2001 movs r0, #1 + 8002efa: e001 b.n 8002f00 + + // will use zeros for all PIN codes, and secret starting values + uint8_t zeros[72]; + memset(zeros, 0, sizeof(zeros)); + + for(int kn=0; kn<16; kn++) { + 8002efc: 462c mov r4, r5 + 8002efe: e7b0 b.n 8002e62 + if(ae_lock_data_zone()) { + INCONSISTENT("data lock"); + } + + return 0; +} + 8002f00: b041 add sp, #260 ; 0x104 + 8002f02: bd30 pop {r4, r5, pc} + 8002f04: 08006940 .word 0x08006940 + 8002f08: 08007840 .word 0x08007840 + 8002f0c: 0800725f .word 0x0800725f + 8002f10: 080072d1 .word 0x080072d1 + 8002f14: 08007210 .word 0x08007210 + 8002f18: 08007800 .word 0x08007800 + 8002f1c: 080072a3 .word 0x080072a3 + +08002f20 : +// + void +delay_ms(int ms) +{ + // Clear the COUNTFLAG and reset value to zero + SysTick->VAL = 0; + 8002f20: 4b05 ldr r3, [pc, #20] ; (8002f38 ) + 8002f22: 2200 movs r2, #0 + 8002f24: 609a str r2, [r3, #8] + //SysTick->CTRL; + + // Wait for ticks to happen + while(ms > 0) { + 8002f26: 2800 cmp r0, #0 + 8002f28: dd05 ble.n 8002f36 + if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) { + 8002f2a: 681a ldr r2, [r3, #0] + 8002f2c: 03d2 lsls r2, r2, #15 + ms--; + 8002f2e: bf48 it mi + 8002f30: f100 30ff addmi.w r0, r0, #4294967295 ; 0xffffffff + 8002f34: e7f7 b.n 8002f26 + } + } +} + 8002f36: 4770 bx lr + 8002f38: e000e010 .word 0xe000e010 + +08002f3c : +// delay_us() +// + void +delay_us(int us) +{ + if(us > 1000) { + 8002f3c: f5b0 7f7a cmp.w r0, #1000 ; 0x3e8 + +// delay_us() +// + void +delay_us(int us) +{ + 8002f40: b507 push {r0, r1, r2, lr} + if(us > 1000) { + 8002f42: dd08 ble.n 8002f56 + // big round up + delay_ms((us + 500) / 1000); + 8002f44: f44f 737a mov.w r3, #1000 ; 0x3e8 + 8002f48: f500 70fa add.w r0, r0, #500 ; 0x1f4 + 8002f4c: fb90 f0f3 sdiv r0, r0, r3 + 8002f50: f7ff ffe6 bl 8002f20 + 8002f54: e00c b.n 8002f70 + + } else { + // XXX calibrate this + for(volatile int i=0; i<(10000*us); i++) { + 8002f56: 2300 movs r3, #0 + 8002f58: 9301 str r3, [sp, #4] + 8002f5a: f242 7310 movw r3, #10000 ; 0x2710 + 8002f5e: 4358 muls r0, r3 + 8002f60: 9b01 ldr r3, [sp, #4] + 8002f62: 4298 cmp r0, r3 + 8002f64: dd04 ble.n 8002f70 + 8002f66: bf00 nop + 8002f68: 9b01 ldr r3, [sp, #4] + 8002f6a: 3301 adds r3, #1 + 8002f6c: 9301 str r3, [sp, #4] + 8002f6e: e7f7 b.n 8002f60 + __NOP(); + } + } +} + 8002f70: b003 add sp, #12 + 8002f72: f85d fb04 ldr.w pc, [sp], #4 + ... + +08002f78 : + // NOTES: + // - try not to limit PCB changes for future revs; leave unused unchanged. + // - oled_setup() uses pins on PA6 thru PA8 + + // enable clock to that part of chip + __HAL_RCC_GPIOA_CLK_ENABLE(); + 8002f78: 4b16 ldr r3, [pc, #88] ; (8002fd4 ) + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_LOW, + .Alternate = 0, + }; + + HAL_GPIO_Init(DFU_BTN_PORT, &setup); + 8002f7a: 4817 ldr r0, [pc, #92] ; (8002fd8 ) + // NOTES: + // - try not to limit PCB changes for future revs; leave unused unchanged. + // - oled_setup() uses pins on PA6 thru PA8 + + // enable clock to that part of chip + __HAL_RCC_GPIOA_CLK_ENABLE(); + 8002f7c: 6cda ldr r2, [r3, #76] ; 0x4c +// +// set directions, lock critical ones, etc. +// + void +gpio_setup(void) +{ + 8002f7e: b530 push {r4, r5, lr} + // NOTES: + // - try not to limit PCB changes for future revs; leave unused unchanged. + // - oled_setup() uses pins on PA6 thru PA8 + + // enable clock to that part of chip + __HAL_RCC_GPIOA_CLK_ENABLE(); + 8002f80: f042 0201 orr.w r2, r2, #1 + 8002f84: 64da str r2, [r3, #76] ; 0x4c + 8002f86: 6cda ldr r2, [r3, #76] ; 0x4c + + HAL_GPIO_Init(DFU_BTN_PORT, &setup); + } + + { // Onewire bus pin used for ATECC508A comms + GPIO_InitTypeDef setup = { + 8002f88: 4d14 ldr r5, [pc, #80] ; (8002fdc ) +// +// set directions, lock critical ones, etc. +// + void +gpio_setup(void) +{ + 8002f8a: b089 sub sp, #36 ; 0x24 + // NOTES: + // - try not to limit PCB changes for future revs; leave unused unchanged. + // - oled_setup() uses pins on PA6 thru PA8 + + // enable clock to that part of chip + __HAL_RCC_GPIOA_CLK_ENABLE(); + 8002f8c: f002 0201 and.w r2, r2, #1 + 8002f90: 9201 str r2, [sp, #4] + 8002f92: 9a01 ldr r2, [sp, #4] + __HAL_RCC_GPIOB_CLK_ENABLE(); + 8002f94: 6cda ldr r2, [r3, #76] ; 0x4c + 8002f96: f042 0202 orr.w r2, r2, #2 + 8002f9a: 64da str r2, [r3, #76] ; 0x4c + 8002f9c: 6cdb ldr r3, [r3, #76] ; 0x4c + 8002f9e: f003 0302 and.w r3, r3, #2 + 8002fa2: 9302 str r3, [sp, #8] + 8002fa4: 9b02 ldr r3, [sp, #8] + + { // DFU button + GPIO_InitTypeDef setup = { + 8002fa6: f44f 7380 mov.w r3, #256 ; 0x100 + 8002faa: 9303 str r3, [sp, #12] + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_LOW, + .Alternate = 0, + }; + + HAL_GPIO_Init(DFU_BTN_PORT, &setup); + 8002fac: a903 add r1, sp, #12 + // enable clock to that part of chip + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + { // DFU button + GPIO_InitTypeDef setup = { + 8002fae: 2300 movs r3, #0 + 8002fb0: 9304 str r3, [sp, #16] + 8002fb2: 9305 str r3, [sp, #20] + 8002fb4: 9306 str r3, [sp, #24] + 8002fb6: 9307 str r3, [sp, #28] + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_LOW, + .Alternate = 0, + }; + + HAL_GPIO_Init(DFU_BTN_PORT, &setup); + 8002fb8: f7fd fefe bl 8000db8 + } + + { // Onewire bus pin used for ATECC508A comms + GPIO_InitTypeDef setup = { + 8002fbc: cd0f ldmia r5!, {r0, r1, r2, r3} + 8002fbe: ac03 add r4, sp, #12 + 8002fc0: c40f stmia r4!, {r0, r1, r2, r3} + 8002fc2: 682b ldr r3, [r5, #0] + 8002fc4: 6023 str r3, [r4, #0] + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_MEDIUM, + .Alternate = GPIO_AF8_UART4, + }; + + HAL_GPIO_Init(ONEWIRE_PORT, &setup); + 8002fc6: a903 add r1, sp, #12 + 8002fc8: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + 8002fcc: f7fd fef4 bl 8000db8 + + // elsewhere... + //HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 1); + //HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 0); +#endif +} + 8002fd0: b009 add sp, #36 ; 0x24 + 8002fd2: bd30 pop {r4, r5, pc} + 8002fd4: 40021000 .word 0x40021000 + 8002fd8: 48000400 .word 0x48000400 + 8002fdc: 080072f8 .word 0x080072f8 + +08002fe0 : +// +// sample the DFU button +// + bool +dfu_button_pressed(void) +{ + 8002fe0: b508 push {r3, lr} + return (HAL_GPIO_ReadPin(DFU_BTN_PORT, DFU_BTN_PIN) == GPIO_PIN_SET); + 8002fe2: f44f 7180 mov.w r1, #256 ; 0x100 + 8002fe6: 4803 ldr r0, [pc, #12] ; (8002ff4 ) + 8002fe8: f7fe f85e bl 80010a8 +} + 8002fec: 1e43 subs r3, r0, #1 + 8002fee: 4258 negs r0, r3 + 8002ff0: 4158 adcs r0, r3 + 8002ff2: bd08 pop {r3, pc} + 8002ff4: 48000400 .word 0x48000400 + +08002ff8 <_hmac_attempt>: +// +// Maybe should be proper HMAC from fips std? Can be changed later. +// + static void +_hmac_attempt(const pinAttempt_t *args, uint8_t result[32]) +{ + 8002ff8: b530 push {r4, r5, lr} + 8002ffa: b09d sub sp, #116 ; 0x74 + 8002ffc: 4605 mov r5, r0 + extern uint8_t reboot_seed_base[32]; // constant per-boot + + SHA256_CTX ctx; + + sha256_init(&ctx); + 8002ffe: 4668 mov r0, sp +// +// Maybe should be proper HMAC from fips std? Can be changed later. +// + static void +_hmac_attempt(const pinAttempt_t *args, uint8_t result[32]) +{ + 8003000: 460c mov r4, r1 + extern uint8_t reboot_seed_base[32]; // constant per-boot + + SHA256_CTX ctx; + + sha256_init(&ctx); + 8003002: f002 f9c3 bl 800538c + sha256_update(&ctx, rom_secrets->pairing_secret, 32); + 8003006: 4668 mov r0, sp + 8003008: 2220 movs r2, #32 + 800300a: 490f ldr r1, [pc, #60] ; (8003048 <_hmac_attempt+0x50>) + 800300c: f002 f9e8 bl 80053e0 + sha256_update(&ctx, reboot_seed_base, 32); + 8003010: 4668 mov r0, sp + 8003012: 2220 movs r2, #32 + 8003014: 490d ldr r1, [pc, #52] ; (800304c <_hmac_attempt+0x54>) + 8003016: f002 f9e3 bl 80053e0 + sha256_update(&ctx, (uint8_t *)args, offsetof(pinAttempt_t, hmac)); + 800301a: 2244 movs r2, #68 ; 0x44 + 800301c: 4629 mov r1, r5 + 800301e: 4668 mov r0, sp + 8003020: f002 f9de bl 80053e0 + sha256_final(&ctx, result); + 8003024: 4621 mov r1, r4 + 8003026: 4668 mov r0, sp + 8003028: f002 f9f8 bl 800541c + + // and a second-sha256 on that, just in case. + sha256_init(&ctx); + 800302c: 4668 mov r0, sp + 800302e: f002 f9ad bl 800538c + sha256_update(&ctx, result, 32); + 8003032: 2220 movs r2, #32 + 8003034: 4621 mov r1, r4 + 8003036: 4668 mov r0, sp + 8003038: f002 f9d2 bl 80053e0 + sha256_final(&ctx, result); + 800303c: 4621 mov r1, r4 + 800303e: 4668 mov r0, sp + 8003040: f002 f9ec bl 800541c +} + 8003044: b01d add sp, #116 ; 0x74 + 8003046: bd30 pop {r4, r5, pc} + 8003048: 08007800 .word 0x08007800 + 800304c: 10007c00 .word 0x10007c00 + +08003050 <_sign_attempt>: +// Provide our "signature" validating struct contents as coming from us. +// + static void +_sign_attempt(pinAttempt_t *args) +{ + args->magic_value = PA_MAGIC; + 8003050: 4601 mov r1, r0 + 8003052: 4b02 ldr r3, [pc, #8] ; (800305c <_sign_attempt+0xc>) + 8003054: f841 3b44 str.w r3, [r1], #68 + + _hmac_attempt(args, args->hmac); + 8003058: f7ff bfce b.w 8002ff8 <_hmac_attempt> + 800305c: 2eaf6311 .word 0x2eaf6311 + +08003060 <_validate_attempt>: + +// _validate_attempt() +// + static int +_validate_attempt(pinAttempt_t *args, bool first_time) +{ + 8003060: b530 push {r4, r5, lr} + 8003062: 4604 mov r4, r0 + 8003064: b089 sub sp, #36 ; 0x24 + if(first_time) { + 8003066: 460d mov r5, r1 + 8003068: b961 cbnz r1, 8003084 <_validate_attempt+0x24> + // no hmac needed for setup call + } else { + // if hmac is defined, better be right. + uint8_t actual[32]; + + _hmac_attempt(args, actual); + 800306a: 4669 mov r1, sp + 800306c: f7ff ffc4 bl 8002ff8 <_hmac_attempt> + + if(!check_equal(actual, args->hmac, 32)) { + 8003070: 2220 movs r2, #32 + 8003072: f104 0144 add.w r1, r4, #68 ; 0x44 + 8003076: 4668 mov r0, sp + 8003078: f7fe ff00 bl 8001e7c + 800307c: b910 cbnz r0, 8003084 <_validate_attempt+0x24> + // hmac is wrong? + return EPIN_HMAC_FAIL; + 800307e: f06f 0063 mvn.w r0, #99 ; 0x63 + 8003082: e021 b.n 80030c8 <_validate_attempt+0x68> + } + } + + // check fields. + if(args->magic_value != PA_MAGIC) { + 8003084: 6823 ldr r3, [r4, #0] + 8003086: 4a11 ldr r2, [pc, #68] ; (80030cc <_validate_attempt+0x6c>) + 8003088: 4293 cmp r3, r2 + 800308a: d001 beq.n 8003090 <_validate_attempt+0x30> + if(first_time && args->magic_value == 0) { + 800308c: b1bd cbz r5, 80030be <_validate_attempt+0x5e> + 800308e: b9b3 cbnz r3, 80030be <_validate_attempt+0x5e> + return EPIN_BAD_MAGIC; + } + } + + // check fields + if(args->pin_len > MAX_PIN_LEN) return EPIN_RANGE_ERR; + 8003090: 6aa3 ldr r3, [r4, #40] ; 0x28 + 8003092: 2b20 cmp r3, #32 + 8003094: dc16 bgt.n 80030c4 <_validate_attempt+0x64> + if(args->old_pin_len > MAX_PIN_LEN) return EPIN_RANGE_ERR; + 8003096: f8d4 3088 ldr.w r3, [r4, #136] ; 0x88 + 800309a: 2b20 cmp r3, #32 + 800309c: dc12 bgt.n 80030c4 <_validate_attempt+0x64> + if(args->new_pin_len > MAX_PIN_LEN) return EPIN_RANGE_ERR; + 800309e: f8d4 30ac ldr.w r3, [r4, #172] ; 0xac + 80030a2: 2b20 cmp r3, #32 + 80030a4: dc0e bgt.n 80030c4 <_validate_attempt+0x64> + if((args->change_flags & CHANGE__MASK) != args->change_flags) return EPIN_RANGE_ERR; + 80030a6: 6e63 ldr r3, [r4, #100] ; 0x64 + 80030a8: f033 033f bics.w r3, r3, #63 ; 0x3f + 80030ac: d10a bne.n 80030c4 <_validate_attempt+0x64> + + if((args->is_secondary & 0x1) != args->is_secondary) return EPIN_RANGE_ERR; + 80030ae: 6863 ldr r3, [r4, #4] + + return 0; + 80030b0: f033 0301 bics.w r3, r3, #1 + 80030b4: bf14 ite ne + 80030b6: f06f 0066 mvnne.w r0, #102 ; 0x66 + 80030ba: 2000 moveq r0, #0 + 80030bc: e004 b.n 80030c8 <_validate_attempt+0x68> + // check fields. + if(args->magic_value != PA_MAGIC) { + if(first_time && args->magic_value == 0) { + // allow it if first time + } else { + return EPIN_BAD_MAGIC; + 80030be: f06f 0065 mvn.w r0, #101 ; 0x65 + 80030c2: e001 b.n 80030c8 <_validate_attempt+0x68> + } + } + + // check fields + if(args->pin_len > MAX_PIN_LEN) return EPIN_RANGE_ERR; + 80030c4: f06f 0066 mvn.w r0, #102 ; 0x66 + if((args->change_flags & CHANGE__MASK) != args->change_flags) return EPIN_RANGE_ERR; + + if((args->is_secondary & 0x1) != args->is_secondary) return EPIN_RANGE_ERR; + + return 0; +} + 80030c8: b009 add sp, #36 ; 0x24 + 80030ca: bd30 pop {r4, r5, pc} + 80030cc: 2eaf6311 .word 0x2eaf6311 + +080030d0 : + +// warmup_ae() +// + static int +warmup_ae(void) +{ + 80030d0: b510 push {r4, lr} + ae_setup(); + 80030d2: f7ff f867 bl 80021a4 + 80030d6: 2405 movs r4, #5 + + for(int retry=0; retry<5; retry++) { + if(!ae_probe()) break; + 80030d8: f7ff fb7c bl 80027d4 + 80030dc: b108 cbz r0, 80030e2 + static int +warmup_ae(void) +{ + ae_setup(); + + for(int retry=0; retry<5; retry++) { + 80030de: 3c01 subs r4, #1 + 80030e0: d1fa bne.n 80030d8 + if(!ae_probe()) break; + } + + if(ae_pair_unlock()) return -1; + 80030e2: f7ff fab9 bl 8002658 + 80030e6: 3000 adds r0, #0 + 80030e8: bf18 it ne + 80030ea: 2001 movne r0, #1 + + return 0; +} + 80030ec: 4240 negs r0, r0 + 80030ee: bd10 pop {r4, pc} + +080030f0 : +// +// Is a specific PIN defined already? Not safe to expose this directly to callers! +// + static bool +pin_is_blank(whichPin_t which) +{ + 80030f0: b510 push {r4, lr} + 80030f2: b088 sub sp, #32 + int keynum = -1; + + switch(which) { + 80030f4: 2804 cmp r0, #4 + 80030f6: d80c bhi.n 8003112 + 80030f8: e8df f000 tbb [pc, r0] + 80030fc: 07050311 .word 0x07050311 + 8003100: 09 .byte 0x09 + 8003101: 00 .byte 0x00 + case PIN_primary: + keynum = KEYNUM_pin_1; + break; + + case PIN_secondary: + keynum = KEYNUM_pin_2; + 8003102: 2404 movs r4, #4 + 8003104: e00c b.n 8003120 + break; + + case PIN_primary_duress: + keynum = KEYNUM_pin_3; + 8003106: 2407 movs r4, #7 + break; + 8003108: e00a b.n 8003120 + + case PIN_secondary_duress: + keynum = KEYNUM_pin_4; + 800310a: 2408 movs r4, #8 + break; + 800310c: e008 b.n 8003120 + + case PIN_brickme: + keynum = KEYNUM_brickme; + 800310e: 240d movs r4, #13 + break; + 8003110: e006 b.n 8003120 + + default: + INCONSISTENT("kn"); + 8003112: 480e ldr r0, [pc, #56] ; (800314c ) + 8003114: f7fd f95a bl 80003cc +// Is a specific PIN defined already? Not safe to expose this directly to callers! +// + static bool +pin_is_blank(whichPin_t which) +{ + int keynum = -1; + 8003118: f04f 34ff mov.w r4, #4294967295 ; 0xffffffff + 800311c: e000 b.n 8003120 + + switch(which) { + case PIN_primary: + keynum = KEYNUM_pin_1; + 800311e: 2403 movs r4, #3 + default: + INCONSISTENT("kn"); + } + + uint8_t blank[32]; + memset(blank, 0, sizeof(blank)); + 8003120: 2220 movs r2, #32 + 8003122: 2100 movs r1, #0 + 8003124: 4668 mov r0, sp + 8003126: f003 fbd3 bl 80068d0 + + ae_reset_chip(); + 800312a: f7ff f82d bl 8002188 + ae_pair_unlock(); + 800312e: f7ff fa93 bl 8002658 + + // passing this check with zeros, means it was blank. + int is_blank = (ae_checkmac(keynum, blank) == 0); + 8003132: 4669 mov r1, sp + 8003134: b2e0 uxtb r0, r4 + 8003136: f7ff fa0b bl 8002550 + 800313a: 4604 mov r4, r0 + + // CAUTION? We've unlocked something maybe, but it's blank, so... + ae_reset_chip(); + 800313c: f7ff f824 bl 8002188 + + return is_blank; +} + 8003140: fab4 f084 clz r0, r4 + 8003144: 0940 lsrs r0, r0, #5 + 8003146: b008 add sp, #32 + 8003148: bd10 pop {r4, pc} + 800314a: bf00 nop + 800314c: 08007210 .word 0x08007210 + +08003150 : +// +// Hash up a string of digits in 32-byte goodness. +// + static void +pin_hash(const char *pin, int pin_len, uint8_t result[32], uint32_t purpose) +{ + 8003150: b570 push {r4, r5, r6, lr} + 8003152: b09e sub sp, #120 ; 0x78 + ASSERT(pin_len <= MAX_PIN_LEN); + 8003154: 2920 cmp r1, #32 +// +// Hash up a string of digits in 32-byte goodness. +// + static void +pin_hash(const char *pin, int pin_len, uint8_t result[32], uint32_t purpose) +{ + 8003156: 4606 mov r6, r0 + 8003158: 460d mov r5, r1 + 800315a: 4614 mov r4, r2 + 800315c: 9301 str r3, [sp, #4] + ASSERT(pin_len <= MAX_PIN_LEN); + 800315e: dd03 ble.n 8003168 + 8003160: 4817 ldr r0, [pc, #92] ; (80031c0 ) + 8003162: f7fd f933 bl 80003cc + 8003166: e005 b.n 8003174 + + if(pin_len == 0) { + 8003168: b921 cbnz r1, 8003174 + // zero-length PIN is considered the "blank" one: all zero + memset(result, 0, 32); + 800316a: 2220 movs r2, #32 + 800316c: 4620 mov r0, r4 + 800316e: f003 fbaf bl 80068d0 + 8003172: e022 b.n 80031ba + + return; + } + + SHA256_CTX ctx; + sha256_init(&ctx); + 8003174: a802 add r0, sp, #8 + 8003176: f002 f909 bl 800538c + + sha256_update(&ctx, rom_secrets->pairing_secret, 32); + 800317a: 2220 movs r2, #32 + 800317c: 4911 ldr r1, [pc, #68] ; (80031c4 ) + 800317e: a802 add r0, sp, #8 + 8003180: f002 f92e bl 80053e0 + sha256_update(&ctx, (uint8_t *)&purpose, 4); + 8003184: 2204 movs r2, #4 + 8003186: eb0d 0102 add.w r1, sp, r2 + 800318a: a802 add r0, sp, #8 + 800318c: f002 f928 bl 80053e0 + sha256_update(&ctx, (uint8_t *)pin, pin_len); + 8003190: 462a mov r2, r5 + 8003192: 4631 mov r1, r6 + 8003194: a802 add r0, sp, #8 + 8003196: f002 f923 bl 80053e0 + + sha256_final(&ctx, result); + 800319a: 4621 mov r1, r4 + 800319c: a802 add r0, sp, #8 + 800319e: f002 f93d bl 800541c + + // and a second-sha256 on that, just in case. + sha256_init(&ctx); + 80031a2: a802 add r0, sp, #8 + 80031a4: f002 f8f2 bl 800538c + sha256_update(&ctx, result, 32); + 80031a8: 4621 mov r1, r4 + 80031aa: a802 add r0, sp, #8 + 80031ac: 2220 movs r2, #32 + 80031ae: f002 f917 bl 80053e0 + sha256_final(&ctx, result); + 80031b2: 4621 mov r1, r4 + 80031b4: a802 add r0, sp, #8 + 80031b6: f002 f931 bl 800541c +} + 80031ba: b01e add sp, #120 ; 0x78 + 80031bc: bd70 pop {r4, r5, r6, pc} + 80031be: bf00 nop + 80031c0: 08006940 .word 0x08006940 + 80031c4: 08007800 .word 0x08007800 + +080031c8 : + +// is_duress_pin() +// + static bool +is_duress_pin(bool is_secondary, const uint8_t digest[32], bool is_blank, int *pin_kn) +{ + 80031c8: b570 push {r4, r5, r6, lr} + 80031ca: 460e mov r6, r1 + 80031cc: 461d mov r5, r3 + // duress PIN can never be blank; that means it wasn't set yet + if(is_blank) return false; + 80031ce: b10a cbz r2, 80031d4 + 80031d0: 2000 movs r0, #0 + 80031d2: bd70 pop {r4, r5, r6, pc} + + int kn = is_secondary ? KEYNUM_pin_4 : KEYNUM_pin_3; + 80031d4: 2800 cmp r0, #0 + 80031d6: bf14 ite ne + 80031d8: 2408 movne r4, #8 + 80031da: 2407 moveq r4, #7 + + ae_reset_chip(); + 80031dc: f7fe ffd4 bl 8002188 + ae_pair_unlock(); + 80031e0: f7ff fa3a bl 8002658 + if(ae_checkmac(kn, digest) == 0) { + 80031e4: 4631 mov r1, r6 + 80031e6: 4620 mov r0, r4 + 80031e8: f7ff f9b2 bl 8002550 + 80031ec: 2800 cmp r0, #0 + 80031ee: d1ef bne.n 80031d0 + *pin_kn = kn; + 80031f0: 602c str r4, [r5, #0] + + return true; + 80031f2: 2001 movs r0, #1 + } + + return false; +} + 80031f4: bd70 pop {r4, r5, r6, pc} + ... + +080031f8 : +// works, immediately destroy the pairing secret so that we become +// a useless brick. +// + static int +maybe_brick_myself(const char *pin, int pin_len) +{ + 80031f8: b510 push {r4, lr} + uint8_t digest[32]; + int rv = 0; + + if(!pin_len) return 0; + 80031fa: 460c mov r4, r1 +// works, immediately destroy the pairing secret so that we become +// a useless brick. +// + static int +maybe_brick_myself(const char *pin, int pin_len) +{ + 80031fc: b088 sub sp, #32 + uint8_t digest[32]; + int rv = 0; + + if(!pin_len) return 0; + 80031fe: b1a1 cbz r1, 800322a + + pin_hash(pin, pin_len, digest, PIN_PURPOSE_NORMAL); + 8003200: 4b0b ldr r3, [pc, #44] ; (8003230 ) + 8003202: 466a mov r2, sp + 8003204: f7ff ffa4 bl 8003150 + + ae_reset_chip(); + 8003208: f7fe ffbe bl 8002188 + + ae_pair_unlock(); + 800320c: f7ff fa24 bl 8002658 + + if(ae_checkmac(KEYNUM_brickme, digest) == 0) { + 8003210: 4669 mov r1, sp + 8003212: 200d movs r0, #13 + 8003214: f7ff f99c bl 8002550 + 8003218: b920 cbnz r0, 8003224 + // success... kinda: brick time. + ae_destroy_key(KEYNUM_pairing); + 800321a: 2001 movs r0, #1 + 800321c: f7ff fd50 bl 8002cc0 + + rv = 1; + 8003220: 2401 movs r4, #1 + 8003222: e000 b.n 8003226 +// + static int +maybe_brick_myself(const char *pin, int pin_len) +{ + uint8_t digest[32]; + int rv = 0; + 8003224: 2400 movs r4, #0 + ae_destroy_key(KEYNUM_pairing); + + rv = 1; + } + + ae_reset_chip(); + 8003226: f7fe ffaf bl 8002188 +maybe_brick_myself(const char *pin, int pin_len) +{ + uint8_t digest[32]; + int rv = 0; + + if(!pin_len) return 0; + 800322a: 4620 mov r0, r4 + } + + ae_reset_chip(); + + return rv; +} + 800322c: b008 add sp, #32 + 800322e: bd10 pop {r4, pc} + 8003230: 334d1858 .word 0x334d1858 + +08003234 : +// Map from PIN keynum to corresponding secret/last good counter. +// + static void +lookup_secret_lastgood(int kn, int *secret_kn, int *lastgood_kn) +{ + switch(kn) { + 8003234: 3803 subs r0, #3 + 8003236: 2805 cmp r0, #5 + 8003238: d814 bhi.n 8003264 + 800323a: e8df f000 tbb [pc, r0] + 800323e: 0703 .short 0x0703 + 8003240: 0d0b1313 .word 0x0d0b1313 + case KEYNUM_pin_1: + *secret_kn = KEYNUM_secret_1; + 8003244: 2309 movs r3, #9 + 8003246: 600b str r3, [r1, #0] + *lastgood_kn = KEYNUM_lastgood_1; + 8003248: 2305 movs r3, #5 + 800324a: e009 b.n 8003260 + break; + + case KEYNUM_pin_2: + *secret_kn = KEYNUM_secret_2; + 800324c: 230a movs r3, #10 + 800324e: 600b str r3, [r1, #0] + *lastgood_kn = KEYNUM_lastgood_2; + 8003250: 2306 movs r3, #6 + 8003252: e005 b.n 8003260 + break; + + case KEYNUM_pin_3: + *secret_kn = KEYNUM_secret_3; + 8003254: 230b movs r3, #11 + 8003256: e000 b.n 800325a + *lastgood_kn = -1; + break; + + case KEYNUM_pin_4: + *secret_kn = KEYNUM_secret_4; + 8003258: 230c movs r3, #12 + 800325a: 600b str r3, [r1, #0] + *lastgood_kn = -1; + 800325c: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 8003260: 6013 str r3, [r2, #0] + 8003262: 4770 bx lr + break; + + default: + INCONSISTENT("kn"); + 8003264: 4801 ldr r0, [pc, #4] ; (800326c ) + 8003266: f7fd b8b1 b.w 80003cc + 800326a: bf00 nop + 800326c: 08007210 .word 0x08007210 + +08003270 : +// - should be rate-limited (or liked to PIN code rate-limiting somehow) +// - hash generated here is shown plaintext on bus (for HMAC operation). +// + int +pin_prefix_words(const char *pin_prefix, int prefix_len, uint32_t *result) +{ + 8003270: b530 push {r4, r5, lr} + 8003272: b091 sub sp, #68 ; 0x44 + uint8_t tmp[32]; + uint8_t digest[32]; + + // hash it up real good + pin_hash(pin_prefix, prefix_len, tmp, PIN_PURPOSE_WORDS); + 8003274: 4b18 ldr r3, [pc, #96] ; (80032d8 ) +// - should be rate-limited (or liked to PIN code rate-limiting somehow) +// - hash generated here is shown plaintext on bus (for HMAC operation). +// + int +pin_prefix_words(const char *pin_prefix, int prefix_len, uint32_t *result) +{ + 8003276: 4615 mov r5, r2 + uint8_t tmp[32]; + uint8_t digest[32]; + + // hash it up real good + pin_hash(pin_prefix, prefix_len, tmp, PIN_PURPOSE_WORDS); + 8003278: 466a mov r2, sp + 800327a: f7ff ff69 bl 8003150 + + // some very weak rate limiting... + uint32_t count = backup_data_get(IDX_WORD_LOOKUPS_USED); + 800327e: 2000 movs r0, #0 + 8003280: f7fe fd88 bl 8001d94 + 8003284: 4604 mov r4, r0 + backup_data_set(IDX_WORD_LOOKUPS_USED, count+1); + 8003286: 1c41 adds r1, r0, #1 + 8003288: 2000 movs r0, #0 + 800328a: f7fe fd93 bl 8001db4 + + if(count > 25) { + 800328e: 2c19 cmp r4, #25 + 8003290: d905 bls.n 800329e + // there is hacking. no human does this many. + INCONSISTENT("prefix attempts"); + 8003292: 4812 ldr r0, [pc, #72] ; (80032dc ) + 8003294: f7fd f89a bl 80003cc + } + + delay_ms((count < 10) ? 150 : 2500); + 8003298: f640 10c4 movw r0, #2500 ; 0x9c4 + 800329c: e004 b.n 80032a8 + 800329e: 2c0a cmp r4, #10 + 80032a0: f640 10c4 movw r0, #2500 ; 0x9c4 + 80032a4: bf38 it cc + 80032a6: 2096 movcc r0, #150 ; 0x96 + 80032a8: f7ff fe3a bl 8002f20 + + // bounce it off chip in HMAC mode, using dedicated key for that purpose. + ae_setup(); + 80032ac: f7fe ff7a bl 80021a4 + ae_pair_unlock(); + 80032b0: f7ff f9d2 bl 8002658 + int rv = ae_hmac32(KEYNUM_words, tmp, digest); + 80032b4: aa08 add r2, sp, #32 + 80032b6: 4669 mov r1, sp + 80032b8: 2002 movs r0, #2 + 80032ba: f7ff fa45 bl 8002748 + 80032be: 4604 mov r4, r0 + ae_reset_chip(); + 80032c0: f7fe ff62 bl 8002188 + + if(rv) return -1; + 80032c4: b91c cbnz r4, 80032ce + + memcpy(result, digest, 4); + 80032c6: 9808 ldr r0, [sp, #32] + 80032c8: 6028 str r0, [r5, #0] + + return 0; + 80032ca: 4620 mov r0, r4 + 80032cc: e001 b.n 80032d2 + ae_setup(); + ae_pair_unlock(); + int rv = ae_hmac32(KEYNUM_words, tmp, digest); + ae_reset_chip(); + + if(rv) return -1; + 80032ce: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff + + memcpy(result, digest, 4); + + return 0; +} + 80032d2: b011 add sp, #68 ; 0x44 + 80032d4: bd30 pop {r4, r5, pc} + 80032d6: bf00 nop + 80032d8: 2e6d6773 .word 0x2e6d6773 + 80032dc: 08007210 .word 0x08007210 + +080032e0 <_calc_delay_required>: + +// _calc_delay_required() +// + uint32_t +_calc_delay_required(int num_fails) +{ + 80032e0: 2831 cmp r0, #49 ; 0x31 + 80032e2: bf9a itte ls + 80032e4: 4b02 ldrls r3, [pc, #8] ; (80032f0 <_calc_delay_required+0x10>) + 80032e6: f833 0010 ldrhls.w r0, [r3, r0, lsl #1] + 80032ea: f44f 4061 movhi.w r0, #57600 ; 0xe100 + case 20 ... 49: return MINUTES(120); + default: return MINUTES(8*60); + } +#undef SECONDS +#undef MINUTES +} + 80032ee: 4770 bx lr + 80032f0: 0800730c .word 0x0800730c + +080032f4 : +// Get number of failed attempts on a PIN, since last success. Calculate +// required delay, and setup initial struct for later attempts. +// + int +pin_setup_attempt(pinAttempt_t *args) +{ + 80032f4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + STATIC_ASSERT(sizeof(pinAttempt_t) == PIN_ATTEMPT_SIZE); + + int rv = _validate_attempt(args, true); + 80032f8: 2101 movs r1, #1 +// Get number of failed attempts on a PIN, since last success. Calculate +// required delay, and setup initial struct for later attempts. +// + int +pin_setup_attempt(pinAttempt_t *args) +{ + 80032fa: b08a sub sp, #40 ; 0x28 + 80032fc: 4604 mov r4, r0 + STATIC_ASSERT(sizeof(pinAttempt_t) == PIN_ATTEMPT_SIZE); + + int rv = _validate_attempt(args, true); + 80032fe: f7ff feaf bl 8003060 <_validate_attempt> + if(rv) return rv; + 8003302: 4605 mov r5, r0 + 8003304: 2800 cmp r0, #0 + 8003306: d171 bne.n 80033ec + // but not allowed to test for those cases even existing. + + // wipe most of struct, keep only what we expect and want! + int is_secondary = args->is_secondary; + char pin_copy[MAX_PIN_LEN]; + int pin_len = args->pin_len; + 8003308: 6aa7 ldr r7, [r4, #40] ; 0x28 + // NOTE: Can only attempt primary and secondary pins. If it happens to + // match duress or brickme pins, then perhaps something happens, + // but not allowed to test for those cases even existing. + + // wipe most of struct, keep only what we expect and want! + int is_secondary = args->is_secondary; + 800330a: f8d4 8004 ldr.w r8, [r4, #4] + char pin_copy[MAX_PIN_LEN]; + int pin_len = args->pin_len; + memcpy(pin_copy, args->pin, pin_len); + 800330e: f104 0608 add.w r6, r4, #8 + 8003312: 463a mov r2, r7 + 8003314: 4631 mov r1, r6 + 8003316: a802 add r0, sp, #8 + 8003318: f003 fab4 bl 8006884 + + memset(args, 0, sizeof(pinAttempt_t)); + 800331c: 22f8 movs r2, #248 ; 0xf8 + 800331e: 4629 mov r1, r5 + 8003320: 4620 mov r0, r4 + 8003322: f003 fad5 bl 80068d0 + + args->magic_value = PA_MAGIC; + 8003326: 4b33 ldr r3, [pc, #204] ; (80033f4 ) + args->is_secondary = is_secondary; + args->pin_len = pin_len; + 8003328: 62a7 str r7, [r4, #40] ; 0x28 + memcpy(pin_copy, args->pin, pin_len); + + memset(args, 0, sizeof(pinAttempt_t)); + + args->magic_value = PA_MAGIC; + args->is_secondary = is_secondary; + 800332a: e884 0108 stmia.w r4, {r3, r8} + args->pin_len = pin_len; + memcpy(args->pin, pin_copy, pin_len); + 800332e: 463a mov r2, r7 + 8003330: a902 add r1, sp, #8 + 8003332: 4630 mov r0, r6 + 8003334: f003 faa6 bl 8006884 + + // unlock the AE chip + if(warmup_ae()) return EPIN_I_AM_BRICK; + 8003338: f7ff feca bl 80030d0 + 800333c: b110 cbz r0, 8003344 + 800333e: f06f 0568 mvn.w r5, #104 ; 0x68 + 8003342: e053 b.n 80033ec + + if(args->pin_len) { + 8003344: 6aa1 ldr r1, [r4, #40] ; 0x28 + 8003346: b981 cbnz r1, 800336a + if(maybe_brick_myself(args->pin, args->pin_len)) { + return EPIN_I_AM_BRICK; + } + } + + uint32_t count = 0, last_good = 0; + 8003348: 2300 movs r3, #0 + 800334a: 9300 str r3, [sp, #0] + if(get_last_success(args->is_secondary, &count, &last_good)) { + 800334c: 6863 ldr r3, [r4, #4] + int kn = is_secondary ? KEYNUM_lastgood_2 : KEYNUM_lastgood_1; + + uint32_t tmp; + + // use first 32-bits only + if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1; + 800334e: 2204 movs r2, #4 + return EPIN_I_AM_BRICK; + } + } + + uint32_t count = 0, last_good = 0; + if(get_last_success(args->is_secondary, &count, &last_good)) { + 8003350: 2b00 cmp r3, #0 + int kn = is_secondary ? KEYNUM_lastgood_2 : KEYNUM_lastgood_1; + + uint32_t tmp; + + // use first 32-bits only + if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1; + 8003352: eb0d 0102 add.w r1, sp, r2 + 8003356: bf15 itete ne + 8003358: 2006 movne r0, #6 + 800335a: 2005 moveq r0, #5 + return EPIN_I_AM_BRICK; + } + } + + uint32_t count = 0, last_good = 0; + if(get_last_success(args->is_secondary, &count, &last_good)) { + 800335c: 2501 movne r5, #1 + 800335e: 2500 moveq r5, #0 + int kn = is_secondary ? KEYNUM_lastgood_2 : KEYNUM_lastgood_1; + + uint32_t tmp; + + // use first 32-bits only + if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1; + 8003360: f7ff fbb4 bl 8002acc + 8003364: 4602 mov r2, r0 + 8003366: b130 cbz r0, 8003376 + 8003368: e00f b.n 800338a + if(warmup_ae()) return EPIN_I_AM_BRICK; + + if(args->pin_len) { + // Implement the brickme feature here, nice and early: Immediate brickage if + // provided PIN matches that special PIN. + if(maybe_brick_myself(args->pin, args->pin_len)) { + 800336a: 4630 mov r0, r6 + 800336c: f7ff ff44 bl 80031f8 + 8003370: 2800 cmp r0, #0 + 8003372: d0e9 beq.n 8003348 + 8003374: e7e3 b.n 800333e + // use first 32-bits only + if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1; + + *lastgood = tmp; + + int rv = ae_get_counter(counter, is_secondary ? 1 : 0, false); + 8003376: 4629 mov r1, r5 + 8003378: 4668 mov r0, sp + uint32_t tmp; + + // use first 32-bits only + if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1; + + *lastgood = tmp; + 800337a: 9e01 ldr r6, [sp, #4] + + int rv = ae_get_counter(counter, is_secondary ? 1 : 0, false); + 800337c: f7ff f9bd bl 80026fa + if(rv) return -1; + 8003380: 3000 adds r0, #0 + 8003382: bf18 it ne + 8003384: 2001 movne r0, #1 + 8003386: 4245 negs r5, r0 + return EPIN_I_AM_BRICK; + } + } + + uint32_t count = 0, last_good = 0; + if(get_last_success(args->is_secondary, &count, &last_good)) { + 8003388: b125 cbz r5, 8003394 + ae_reset_chip(); + 800338a: f7fe fefd bl 8002188 + + return EPIN_AE_FAIL; + 800338e: f06f 0569 mvn.w r5, #105 ; 0x69 + 8003392: e02b b.n 80033ec + } + + ae_reset_chip(); + 8003394: f7fe fef8 bl 8002188 + + args->attempt_target = count+1; + 8003398: 9b00 ldr r3, [sp, #0] + + if(last_good > count) { + 800339a: 42b3 cmp r3, r6 + return EPIN_AE_FAIL; + } + + ae_reset_chip(); + + args->attempt_target = count+1; + 800339c: f103 0201 add.w r2, r3, #1 + + if(last_good > count) { + // huh? monkey business + args->num_fails = 99; + 80033a0: bf34 ite cc + 80033a2: 2363 movcc r3, #99 ; 0x63 + } else { + args->num_fails = count - last_good; + 80033a4: 1b9b subcs r3, r3, r6 + 80033a6: 6363 str r3, [r4, #52] ; 0x34 + } + + // has the duress pin (this wallet) been used this power cycle? + uint32_t fake_lastgood = backup_data_get(args->is_secondary + 80033a8: 6863 ldr r3, [r4, #4] + return EPIN_AE_FAIL; + } + + ae_reset_chip(); + + args->attempt_target = count+1; + 80033aa: 63a2 str r2, [r4, #56] ; 0x38 + } else { + args->num_fails = count - last_good; + } + + // has the duress pin (this wallet) been used this power cycle? + uint32_t fake_lastgood = backup_data_get(args->is_secondary + 80033ac: 2b00 cmp r3, #0 + 80033ae: bf14 ite ne + 80033b0: 2002 movne r0, #2 + 80033b2: 2001 moveq r0, #1 + 80033b4: f7fe fcee bl 8001d94 + ? IDX_DURESS_LASTGOOD_2 : IDX_DURESS_LASTGOOD_1); + if(fake_lastgood) { + 80033b8: b108 cbz r0, 80033be + // lie about # of failures, but keep the pin-rate limiting + args->num_fails = 0; + 80033ba: 2300 movs r3, #0 + 80033bc: 6363 str r3, [r4, #52] ; 0x34 + } + + args->delay_required = _calc_delay_required(args->num_fails); + 80033be: 6b63 ldr r3, [r4, #52] ; 0x34 + // tell the caller that, so we can present as empty device. + } +#endif + + // need to know if we are blank/unused device + if(pin_is_blank(args->is_secondary ? PIN_secondary : PIN_primary)) { + 80033c0: 6860 ldr r0, [r4, #4] + 80033c2: 2b31 cmp r3, #49 ; 0x31 + 80033c4: bf96 itet ls + 80033c6: 4a0c ldrls r2, [pc, #48] ; (80033f8 ) + if(fake_lastgood) { + // lie about # of failures, but keep the pin-rate limiting + args->num_fails = 0; + } + + args->delay_required = _calc_delay_required(args->num_fails); + 80033c8: f44f 4361 movhi.w r3, #57600 ; 0xe100 + 80033cc: f832 3013 ldrhls.w r3, [r2, r3, lsl #1] + 80033d0: 6323 str r3, [r4, #48] ; 0x30 + args->delay_achieved = 0; + 80033d2: 2300 movs r3, #0 + // tell the caller that, so we can present as empty device. + } +#endif + + // need to know if we are blank/unused device + if(pin_is_blank(args->is_secondary ? PIN_secondary : PIN_primary)) { + 80033d4: 1ac0 subs r0, r0, r3 + 80033d6: bf18 it ne + 80033d8: 2001 movne r0, #1 + // lie about # of failures, but keep the pin-rate limiting + args->num_fails = 0; + } + + args->delay_required = _calc_delay_required(args->num_fails); + args->delay_achieved = 0; + 80033da: 62e3 str r3, [r4, #44] ; 0x2c + // tell the caller that, so we can present as empty device. + } +#endif + + // need to know if we are blank/unused device + if(pin_is_blank(args->is_secondary ? PIN_secondary : PIN_primary)) { + 80033dc: f7ff fe88 bl 80030f0 + 80033e0: b108 cbz r0, 80033e6 + args->state_flags = PA_SUCCESSFUL | PA_IS_BLANK; + 80033e2: 2303 movs r3, #3 + 80033e4: 63e3 str r3, [r4, #60] ; 0x3c + } + + _sign_attempt(args); + 80033e6: 4620 mov r0, r4 + 80033e8: f7ff fe32 bl 8003050 <_sign_attempt> + + return 0; +} + 80033ec: 4628 mov r0, r5 + 80033ee: b00a add sp, #40 ; 0x28 + 80033f0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 80033f4: 2eaf6311 .word 0x2eaf6311 + 80033f8: 0800730c .word 0x0800730c + +080033fc : +// +// Delay for one time unit, and prove it. Doesn't check PIN value itself. +// + int +pin_delay(pinAttempt_t *args) +{ + 80033fc: b538 push {r3, r4, r5, lr} + int rv = _validate_attempt(args, false); + 80033fe: 2100 movs r1, #0 +// +// Delay for one time unit, and prove it. Doesn't check PIN value itself. +// + int +pin_delay(pinAttempt_t *args) +{ + 8003400: 4604 mov r4, r0 + int rv = _validate_attempt(args, false); + 8003402: f7ff fe2d bl 8003060 <_validate_attempt> + if(rv) return rv; + 8003406: 4605 mov r5, r0 + 8003408: b958 cbnz r0, 8003422 + + // prevent any monkey business w/ systick rate + systick_setup(); + 800340a: f7fe fa6d bl 80018e8 + + delay_ms(500); + 800340e: f44f 70fa mov.w r0, #500 ; 0x1f4 + 8003412: f7ff fd85 bl 8002f20 + + args->delay_achieved += 1; + 8003416: 6ae3 ldr r3, [r4, #44] ; 0x2c + 8003418: 3301 adds r3, #1 + 800341a: 62e3 str r3, [r4, #44] ; 0x2c + + _sign_attempt(args); + 800341c: 4620 mov r0, r4 + 800341e: f7ff fe17 bl 8003050 <_sign_attempt> + + return 0; +} + 8003422: 4628 mov r0, r5 + 8003424: bd38 pop {r3, r4, r5, pc} + ... + +08003428 : +// +// Do the PIN check, and return a value. Or fail. +// + int +pin_login_attempt(pinAttempt_t *args) +{ + 8003428: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + int rv = _validate_attempt(args, false); + 800342c: 2100 movs r1, #0 +// +// Do the PIN check, and return a value. Or fail. +// + int +pin_login_attempt(pinAttempt_t *args) +{ + 800342e: b0a0 sub sp, #128 ; 0x80 + 8003430: 4604 mov r4, r0 + int rv = _validate_attempt(args, false); + 8003432: f7ff fe15 bl 8003060 <_validate_attempt> + if(rv) return rv; + 8003436: 2800 cmp r0, #0 + 8003438: f040 80af bne.w 800359a + + // did they wait long enough? + if(args->delay_achieved < args->delay_required) { + 800343c: 6ae2 ldr r2, [r4, #44] ; 0x2c + 800343e: 6b23 ldr r3, [r4, #48] ; 0x30 + 8003440: 429a cmp r2, r3 + 8003442: f0c0 80ac bcc.w 800359e + return EPIN_MUST_WAIT; + } + + if(args->state_flags & PA_SUCCESSFUL) { + 8003446: 6be3 ldr r3, [r4, #60] ; 0x3c + 8003448: 07da lsls r2, r3, #31 + 800344a: f100 80ab bmi.w 80035a4 + // already worked, or is blank + return EPIN_WRONG_SUCCESS; + } + + // unlock the AE chip + if(warmup_ae()) return EPIN_I_AM_BRICK; + 800344e: f7ff fe3f bl 80030d0 + 8003452: 4605 mov r5, r0 + 8003454: 2800 cmp r0, #0 + 8003456: f040 80a8 bne.w 80035aa + + int pin_kn = -1; + 800345a: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 800345e: 9302 str r3, [sp, #8] + bool is_duress = false; + + // hash up the pin now. + uint32_t new_count = ~0; + 8003460: 9303 str r3, [sp, #12] + uint8_t digest[32]; + pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL); + 8003462: aa06 add r2, sp, #24 + 8003464: 4b58 ldr r3, [pc, #352] ; (80035c8 ) + 8003466: 6aa1 ldr r1, [r4, #40] ; 0x28 + 8003468: f104 0008 add.w r0, r4, #8 + 800346c: f7ff fe70 bl 8003150 + + if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) { + 8003470: 6aa2 ldr r2, [r4, #40] ; 0x28 + 8003472: 6860 ldr r0, [r4, #4] + 8003474: fab2 f282 clz r2, r2 + 8003478: 3000 adds r0, #0 + 800347a: a906 add r1, sp, #24 + 800347c: ab02 add r3, sp, #8 + 800347e: ea4f 1252 mov.w r2, r2, lsr #5 + 8003482: bf18 it ne + 8003484: 2001 movne r0, #1 + 8003486: f7ff fe9f bl 80031c8 + 800348a: 6861 ldr r1, [r4, #4] + 800348c: b158 cbz r0, 80034a6 + // they gave the duress PIN for this wallet... try to continue w/o any indication + is_duress = true; + + // record this! + backup_data_set(args->is_secondary ? IDX_DURESS_LASTGOOD_2 : IDX_DURESS_LASTGOOD_1, + 800348e: 2900 cmp r1, #0 + 8003490: 6ba1 ldr r1, [r4, #56] ; 0x38 + 8003492: bf18 it ne + 8003494: 2002 movne r0, #2 + 8003496: f101 0101 add.w r1, r1, #1 + 800349a: bf08 it eq + 800349c: 2001 moveq r0, #1 + 800349e: f7fe fc89 bl 8001db4 + uint8_t digest[32]; + pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL); + + if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) { + // they gave the duress PIN for this wallet... try to continue w/o any indication + is_duress = true; + 80034a2: 2601 movs r6, #1 + 80034a4: e01d b.n 80034e2 + } else { + // Assume it's the real PIN, and register as an attempt on that. + + // Is this attempt for the right count? Also, increament it. + + rv = ae_get_counter(&new_count, args->is_secondary ? 1 : 0, true); + 80034a6: 3100 adds r1, #0 + 80034a8: bf18 it ne + 80034aa: 2101 movne r1, #1 + 80034ac: 2201 movs r2, #1 + 80034ae: a803 add r0, sp, #12 + 80034b0: f7ff f923 bl 80026fa + if(rv) return EPIN_AE_FAIL; + 80034b4: 2800 cmp r0, #0 + 80034b6: d17b bne.n 80035b0 + + if(args->attempt_target != new_count) { + 80034b8: 6ba2 ldr r2, [r4, #56] ; 0x38 + 80034ba: 9b03 ldr r3, [sp, #12] + 80034bc: 429a cmp r2, r3 + 80034be: d17a bne.n 80035b6 +// Important that every code path leading here is rate-limited, and also incr the counter. +// + static bool +is_real_pin(bool is_secondary, const uint8_t digest[32], bool is_blank, int *pin_kn) +{ + int kn = is_secondary ? KEYNUM_pin_2 : KEYNUM_pin_1; + 80034c0: 6863 ldr r3, [r4, #4] + 80034c2: 2b00 cmp r3, #0 + 80034c4: bf14 ite ne + 80034c6: 2604 movne r6, #4 + 80034c8: 2603 moveq r6, #3 + + ae_reset_chip(); + 80034ca: f7fe fe5d bl 8002188 + ae_pair_unlock(); + 80034ce: f7ff f8c3 bl 8002658 + + if(ae_checkmac(kn, digest) == 0) { + 80034d2: a906 add r1, sp, #24 + 80034d4: 4630 mov r0, r6 + 80034d6: f7ff f83b bl 8002550 + 80034da: 2800 cmp r0, #0 + 80034dc: d16e bne.n 80035bc + *pin_kn = kn; + 80034de: 9602 str r6, [sp, #8] + + // unlock the AE chip + if(warmup_ae()) return EPIN_I_AM_BRICK; + + int pin_kn = -1; + bool is_duress = false; + 80034e0: 462e mov r6, r5 + } + + // SUCCESS! "digest" holds a working value. + + // reset rate-limiting on word lookups + backup_data_set(IDX_WORD_LOOKUPS_USED, 0); + 80034e2: 2100 movs r1, #0 + 80034e4: 4608 mov r0, r1 + 80034e6: f7fe fc65 bl 8001db4 + + // ASIDE: even if they above was bypassed, the following code will + // fail when it tries to read/update the corresponding slots in the 508a. + + int secret_kn = -1, lastgood_kn = -1; + 80034ea: aa20 add r2, sp, #128 ; 0x80 + 80034ec: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 80034f0: f842 3d6c str.w r3, [r2, #-108]! + lookup_secret_lastgood(pin_kn, &secret_kn, &lastgood_kn); + 80034f4: a904 add r1, sp, #16 + 80034f6: 9802 ldr r0, [sp, #8] + backup_data_set(IDX_WORD_LOOKUPS_USED, 0); + + // ASIDE: even if they above was bypassed, the following code will + // fail when it tries to read/update the corresponding slots in the 508a. + + int secret_kn = -1, lastgood_kn = -1; + 80034f8: 9304 str r3, [sp, #16] + lookup_secret_lastgood(pin_kn, &secret_kn, &lastgood_kn); + 80034fa: f7ff fe9b bl 8003234 + + if(lastgood_kn != -1) { + 80034fe: 9f05 ldr r7, [sp, #20] + 8003500: 1c7b adds r3, r7, #1 + 8003502: d011 beq.n 8003528 + + // update the "last good" counter + uint32_t tmp[32/4] = {0}; + 8003504: f04f 0820 mov.w r8, #32 + 8003508: 4642 mov r2, r8 + 800350a: 2100 movs r1, #0 + 800350c: a80e add r0, sp, #56 ; 0x38 + 800350e: f003 f9df bl 80068d0 + tmp[0] = new_count; + 8003512: 9b03 ldr r3, [sp, #12] + 8003514: 930e str r3, [sp, #56] ; 0x38 + + rv = ae_encrypted_write(lastgood_kn, pin_kn, digest, (void *)tmp, 32); + 8003516: f8cd 8000 str.w r8, [sp] + 800351a: ab0e add r3, sp, #56 ; 0x38 + 800351c: aa06 add r2, sp, #24 + 800351e: 9902 ldr r1, [sp, #8] + 8003520: 4638 mov r0, r7 + 8003522: f7ff fa49 bl 80029b8 + if(rv) { + 8003526: b950 cbnz r0, 800353e + return EPIN_AE_FAIL; + } + } + + // mark as success + args->state_flags = PA_SUCCESSFUL; + 8003528: 2301 movs r3, #1 + // I used to always read the secret, since it's so hard to get to this point, + // but now just indicating if zero or non-zero so that we don't contaminate the + // caller w/ sensitive data that they may not want yet. + { uint8_t ts[AE_SECRET_LEN]; + + rv = ae_encrypted_read(secret_kn, pin_kn, digest, ts, AE_SECRET_LEN); + 800352a: 2748 movs r7, #72 ; 0x48 + return EPIN_AE_FAIL; + } + } + + // mark as success + args->state_flags = PA_SUCCESSFUL; + 800352c: 63e3 str r3, [r4, #60] ; 0x3c + // I used to always read the secret, since it's so hard to get to this point, + // but now just indicating if zero or non-zero so that we don't contaminate the + // caller w/ sensitive data that they may not want yet. + { uint8_t ts[AE_SECRET_LEN]; + + rv = ae_encrypted_read(secret_kn, pin_kn, digest, ts, AE_SECRET_LEN); + 800352e: 9700 str r7, [sp, #0] + 8003530: ab0e add r3, sp, #56 ; 0x38 + 8003532: aa06 add r2, sp, #24 + 8003534: 9902 ldr r1, [sp, #8] + 8003536: 9804 ldr r0, [sp, #16] + 8003538: f7ff fa06 bl 8002948 + if(rv) { + 800353c: b110 cbz r0, 8003544 + ae_reset_chip(); + 800353e: f7fe fe23 bl 8002188 + 8003542: e035 b.n 80035b0 + + return EPIN_AE_FAIL; + } + ae_reset_chip(); + 8003544: f7fe fe20 bl 8002188 + + if(check_all_zeros(ts, AE_SECRET_LEN)) { + 8003548: 4639 mov r1, r7 + 800354a: a80e add r0, sp, #56 ; 0x38 + 800354c: f7fe fc8a bl 8001e64 + 8003550: b118 cbz r0, 800355a + args->state_flags |= PA_ZERO_SECRET; + 8003552: 6be3 ldr r3, [r4, #60] ; 0x3c + 8003554: f043 0310 orr.w r3, r3, #16 + 8003558: 63e3 str r3, [r4, #60] ; 0x3c + } + } + + + // indicate what featurs already enabled/non-blank + if(is_duress) { + 800355a: b11e cbz r6, 8003564 + // provide false answers to status of duress and brickme + args->state_flags |= (PA_HAS_DURESS | PA_HAS_BRICKME); + 800355c: 6be3 ldr r3, [r4, #60] ; 0x3c + 800355e: f043 030c orr.w r3, r3, #12 + 8003562: e012 b.n 800358a + } else { + // do we have duress password? + if(!pin_is_blank(args->is_secondary ? PIN_secondary_duress : PIN_primary_duress)) { + 8003564: 6863 ldr r3, [r4, #4] + 8003566: 2b00 cmp r3, #0 + 8003568: bf14 ite ne + 800356a: 2003 movne r0, #3 + 800356c: 2002 moveq r0, #2 + 800356e: f7ff fdbf bl 80030f0 + 8003572: b918 cbnz r0, 800357c + args->state_flags |= PA_HAS_DURESS; + 8003574: 6be3 ldr r3, [r4, #60] ; 0x3c + 8003576: f043 0304 orr.w r3, r3, #4 + 800357a: 63e3 str r3, [r4, #60] ; 0x3c + } + + // do we have brickme set? + if(!pin_is_blank(PIN_brickme)) { + 800357c: 2004 movs r0, #4 + 800357e: f7ff fdb7 bl 80030f0 + 8003582: b918 cbnz r0, 800358c + args->state_flags |= PA_HAS_BRICKME; + 8003584: 6be3 ldr r3, [r4, #60] ; 0x3c + 8003586: f043 0308 orr.w r3, r3, #8 + 800358a: 63e3 str r3, [r4, #60] ; 0x3c + } + + // I was thinking of maybe storing duress flag into private state, + // but no real need. Preserve for future usage and make sure upper + // layers preserve it. + args->private_state = rng_sample(); + 800358c: f7fe fc86 bl 8001e9c + 8003590: 6420 str r0, [r4, #64] ; 0x40 + + _sign_attempt(args); + 8003592: 4620 mov r0, r4 + 8003594: f7ff fd5c bl 8003050 <_sign_attempt> + + return 0; + 8003598: e012 b.n 80035c0 + 800359a: 4605 mov r5, r0 + 800359c: e010 b.n 80035c0 + int rv = _validate_attempt(args, false); + if(rv) return rv; + + // did they wait long enough? + if(args->delay_achieved < args->delay_required) { + return EPIN_MUST_WAIT; + 800359e: f06f 056a mvn.w r5, #106 ; 0x6a + 80035a2: e00d b.n 80035c0 + } + + if(args->state_flags & PA_SUCCESSFUL) { + // already worked, or is blank + return EPIN_WRONG_SUCCESS; + 80035a4: f06f 056c mvn.w r5, #108 ; 0x6c + 80035a8: e00a b.n 80035c0 + } + + // unlock the AE chip + if(warmup_ae()) return EPIN_I_AM_BRICK; + 80035aa: f06f 0568 mvn.w r5, #104 ; 0x68 + 80035ae: e007 b.n 80035c0 + // Assume it's the real PIN, and register as an attempt on that. + + // Is this attempt for the right count? Also, increament it. + + rv = ae_get_counter(&new_count, args->is_secondary ? 1 : 0, true); + if(rv) return EPIN_AE_FAIL; + 80035b0: f06f 0569 mvn.w r5, #105 ; 0x69 + 80035b4: e004 b.n 80035c0 + + if(args->attempt_target != new_count) { + // they just cost themselves an attempt too! (only hackers would come here) + return EPIN_OLD_ATTEMPT; + 80035b6: f06f 056d mvn.w r5, #109 ; 0x6d + 80035ba: e001 b.n 80035c0 + } + + // try it out / and determine if we should proceed under duress + if(!is_real_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) { + // code is just wrong. + return EPIN_AUTH_FAIL; + 80035bc: f06f 056f mvn.w r5, #111 ; 0x6f + args->private_state = rng_sample(); + + _sign_attempt(args); + + return 0; +} + 80035c0: 4628 mov r0, r5 + 80035c2: b020 add sp, #128 ; 0x80 + 80035c4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 80035c8: 334d1858 .word 0x334d1858 + +080035cc : +// +// Change the PIN and/or secrets (must also know the value, or it must be blank) +// + int +pin_change(pinAttempt_t *args) +{ + 80035cc: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + // Validate args and signature + int rv = _validate_attempt(args, false); + 80035d0: 2100 movs r1, #0 +// +// Change the PIN and/or secrets (must also know the value, or it must be blank) +// + int +pin_change(pinAttempt_t *args) +{ + 80035d2: b09d sub sp, #116 ; 0x74 + 80035d4: 4604 mov r4, r0 + // Validate args and signature + int rv = _validate_attempt(args, false); + 80035d6: f7ff fd43 bl 8003060 <_validate_attempt> + if(rv) return rv; + 80035da: 2800 cmp r0, #0 + 80035dc: f040 80ef bne.w 80037be + + if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) { + 80035e0: 6be3 ldr r3, [r4, #60] ; 0x3c + 80035e2: 07d9 lsls r1, r3, #31 + 80035e4: f140 80ed bpl.w 80037c2 + // must come here with a successful PIN login (so it's rate limited nicely) + return EPIN_WRONG_SUCCESS; + } + + if(args->state_flags & PA_IS_BLANK) { + 80035e8: 079a lsls r2, r3, #30 + 80035ea: d504 bpl.n 80035f6 + // if blank, must provide blank value + if(args->pin_len) return EPIN_RANGE_ERR; + 80035ec: 6aa3 ldr r3, [r4, #40] ; 0x28 + 80035ee: b113 cbz r3, 80035f6 + 80035f0: f06f 0566 mvn.w r5, #102 ; 0x66 + 80035f4: e0ed b.n 80037d2 + } + + // Look at change flags. + + const uint32_t cf = args->change_flags; + 80035f6: 6e67 ldr r7, [r4, #100] ; 0x64 + + // must be here to do something. + if(cf == 0) return EPIN_RANGE_ERR; + 80035f8: 2f00 cmp r7, #0 + 80035fa: d0f9 beq.n 80035f0 + + if(cf & CHANGE_BRICKME_PIN) { + 80035fc: f017 0804 ands.w r8, r7, #4 + 8003600: d006 beq.n 8003610 + if(args->is_secondary) { + 8003602: 6863 ldr r3, [r4, #4] + 8003604: 2b00 cmp r3, #0 + 8003606: f040 80df bne.w 80037c8 + // only main PIN holder can define brickme PIN + return EPIN_PRIMARY_ONLY; + } + if(cf != CHANGE_BRICKME_PIN) { + 800360a: 2f04 cmp r7, #4 + 800360c: f040 80df bne.w 80037ce + // only pin can be changed, nothing else. + return EPIN_BAD_REQUEST; + } + } + if((cf & CHANGE_DURESS_SECRET) && (cf & CHANGE_SECRET)) { + 8003610: f007 0918 and.w r9, r7, #24 + 8003614: f1b9 0f18 cmp.w r9, #24 + 8003618: f000 80d9 beq.w 80037ce + // can't change two secrets at once. + return EPIN_BAD_REQUEST; + } + + if(cf & CHANGE_SECONDARY_WALLET_PIN) { + 800361c: f017 0620 ands.w r6, r7, #32 + 8003620: d006 beq.n 8003630 + if(args->is_secondary) { + 8003622: 6863 ldr r3, [r4, #4] + 8003624: 2b00 cmp r3, #0 + 8003626: f040 80d2 bne.w 80037ce + // only main user uses this call + return EPIN_BAD_REQUEST; + } + if(cf != CHANGE_SECONDARY_WALLET_PIN) { + 800362a: 2f20 cmp r7, #32 + 800362c: f040 80cf bne.w 80037ce + // pin up to this point ... none of the others. + // That's why we need old_pin fields. + + // hash it up real good + uint8_t digest[32]; + pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL); + 8003630: 4b6a ldr r3, [pc, #424] ; (80037dc ) + 8003632: 6aa1 ldr r1, [r4, #40] ; 0x28 + 8003634: aa04 add r2, sp, #16 + 8003636: f104 0008 add.w r0, r4, #8 + 800363a: f7ff fd89 bl 8003150 + + // unlock the AE chip + if(warmup_ae()) return EPIN_I_AM_BRICK; + 800363e: f7ff fd47 bl 80030d0 + 8003642: 4605 mov r5, r0 + 8003644: b110 cbz r0, 800364c + 8003646: f06f 0568 mvn.w r5, #104 ; 0x68 + 800364a: e0c2 b.n 80037d2 + // But if they try to change duress wallet PIN, we can't actually work. + // Same for brickme PIN. + + // SO ... we need to know if they started w/ a duress wallet. + + int pin_kn = -1; + 800364c: ab1c add r3, sp, #112 ; 0x70 + 800364e: f04f 32ff mov.w r2, #4294967295 ; 0xffffffff + 8003652: f843 2d68 str.w r2, [r3, #-104]! + bool is_duress = false; + if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) { + 8003656: 6860 ldr r0, [r4, #4] + 8003658: 6aa2 ldr r2, [r4, #40] ; 0x28 + 800365a: 3000 adds r0, #0 + 800365c: fab2 f282 clz r2, r2 + 8003660: bf18 it ne + 8003662: 2001 movne r0, #1 + 8003664: 0952 lsrs r2, r2, #5 + 8003666: a904 add r1, sp, #16 + 8003668: f7ff fdae bl 80031c8 + 800366c: b948 cbnz r0, 8003682 + is_duress = true; + } else { + // no real need to re-prove PIN knowledge. + // if they tricked us, doesn't matter as below the 580a validates it all again + pin_kn = (args->is_secondary || (cf & CHANGE_SECONDARY_WALLET_PIN)) + ? KEYNUM_pin_2 : KEYNUM_pin_1; + 800366e: 6863 ldr r3, [r4, #4] + 8003670: b923 cbnz r3, 800367c + 8003672: 2e00 cmp r6, #0 + 8003674: bf0c ite eq + 8003676: 2303 moveq r3, #3 + 8003678: 2304 movne r3, #4 + 800367a: e000 b.n 800367e + 800367c: 2304 movs r3, #4 + if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) { + is_duress = true; + } else { + // no real need to re-prove PIN knowledge. + // if they tricked us, doesn't matter as below the 580a validates it all again + pin_kn = (args->is_secondary || (cf & CHANGE_SECONDARY_WALLET_PIN)) + 800367e: 9302 str r3, [sp, #8] + 8003680: e012 b.n 80036a8 + + if(is_duress) { + // user is a thug.. limit what they can do + + // check for brickme pin on everything here. + if(maybe_brick_myself(args->old_pin, args->old_pin_len) + 8003682: f8d4 1088 ldr.w r1, [r4, #136] ; 0x88 + 8003686: f104 0068 add.w r0, r4, #104 ; 0x68 + 800368a: f7ff fdb5 bl 80031f8 + 800368e: 2800 cmp r0, #0 + 8003690: d1d9 bne.n 8003646 + || maybe_brick_myself(args->new_pin, args->new_pin_len) + 8003692: f8d4 10ac ldr.w r1, [r4, #172] ; 0xac + 8003696: f104 008c add.w r0, r4, #140 ; 0x8c + 800369a: f7ff fdad bl 80031f8 + 800369e: 2800 cmp r0, #0 + 80036a0: d1d1 bne.n 8003646 + ) { + return EPIN_I_AM_BRICK; + } + + // - pretend they got the validating PIN wrong + if((cf & (CHANGE_WALLET_PIN | CHANGE_SECRET)) != cf) { + 80036a2: f037 0309 bics.w r3, r7, #9 + 80036a6: d129 bne.n 80036fc + + return EPIN_OLD_AUTH_FAIL; + } + } + + if(cf & (CHANGE_WALLET_PIN | CHANGE_SECRET | CHANGE_SECONDARY_WALLET_PIN)) { + 80036a8: f017 0f29 tst.w r7, #41 ; 0x29 + 80036ac: d002 beq.n 80036b4 + target_kn = pin_kn; + 80036ae: f8dd 8008 ldr.w r8, [sp, #8] + 80036b2: e00f b.n 80036d4 + } else if(cf & (CHANGE_DURESS_PIN | CHANGE_DURESS_SECRET)) { + 80036b4: f017 0f12 tst.w r7, #18 + 80036b8: d007 beq.n 80036ca + target_kn = args->is_secondary ? KEYNUM_pin_4 : KEYNUM_pin_3; + 80036ba: 6863 ldr r3, [r4, #4] + 80036bc: 2b00 cmp r3, #0 + 80036be: bf14 ite ne + 80036c0: f04f 0808 movne.w r8, #8 + 80036c4: f04f 0807 moveq.w r8, #7 + 80036c8: e004 b.n 80036d4 + } else if(cf & CHANGE_BRICKME_PIN) { + 80036ca: f1b8 0f00 cmp.w r8, #0 + 80036ce: d08f beq.n 80035f0 + target_kn = KEYNUM_brickme; + 80036d0: f04f 080d mov.w r8, #13 + return EPIN_RANGE_ERR; + } + + // Determine the hash protecting the secret/pin to be changed. + uint8_t target_digest[32]; + if((target_kn != pin_kn) || (cf & CHANGE_SECONDARY_WALLET_PIN)) { + 80036d4: 9b02 ldr r3, [sp, #8] + 80036d6: 4598 cmp r8, r3 + 80036d8: d100 bne.n 80036dc + 80036da: b1a6 cbz r6, 8003706 + pin_hash(args->old_pin, args->old_pin_len, target_digest, PIN_PURPOSE_NORMAL); + 80036dc: f8d4 1088 ldr.w r1, [r4, #136] ; 0x88 + 80036e0: 4b3e ldr r3, [pc, #248] ; (80037dc ) + 80036e2: aa0c add r2, sp, #48 ; 0x30 + 80036e4: f104 0068 add.w r0, r4, #104 ; 0x68 + 80036e8: f7ff fd32 bl 8003150 + + // Check the old pin is right. + ae_pair_unlock(); + 80036ec: f7fe ffb4 bl 8002658 + if(ae_checkmac(target_kn, target_digest)) { + 80036f0: a90c add r1, sp, #48 ; 0x30 + 80036f2: fa5f f088 uxtb.w r0, r8 + 80036f6: f7fe ff2b bl 8002550 + 80036fa: b170 cbz r0, 800371a + return EPIN_I_AM_BRICK; + } + + // - pretend they got the validating PIN wrong + if((cf & (CHANGE_WALLET_PIN | CHANGE_SECRET)) != cf) { + ae_reset_chip(); + 80036fc: f7fe fd44 bl 8002188 + + return EPIN_OLD_AUTH_FAIL; + 8003700: f06f 0570 mvn.w r5, #112 ; 0x70 + 8003704: e065 b.n 80037d2 + ae_reset_chip(); + + return EPIN_OLD_AUTH_FAIL; + } + } else { + memcpy(target_digest, digest, 32); + 8003706: f10d 0e10 add.w lr, sp, #16 + 800370a: e8be 000f ldmia.w lr!, {r0, r1, r2, r3} + 800370e: ae0c add r6, sp, #48 ; 0x30 + 8003710: c60f stmia r6!, {r0, r1, r2, r3} + 8003712: e89e 000f ldmia.w lr, {r0, r1, r2, r3} + 8003716: e886 000f stmia.w r6, {r0, r1, r2, r3} + } + + // Record new PIN value. + if(cf & (CHANGE_WALLET_PIN | CHANGE_DURESS_PIN + 800371a: f017 0f27 tst.w r7, #39 ; 0x27 + 800371e: d01b beq.n 8003758 + | CHANGE_BRICKME_PIN | CHANGE_SECONDARY_WALLET_PIN)) { + + uint8_t new_digest[32]; + pin_hash(args->new_pin, args->new_pin_len, new_digest, PIN_PURPOSE_NORMAL); + 8003720: 4b2e ldr r3, [pc, #184] ; (80037dc ) + 8003722: f8d4 10ac ldr.w r1, [r4, #172] ; 0xac + 8003726: aa14 add r2, sp, #80 ; 0x50 + 8003728: f104 008c add.w r0, r4, #140 ; 0x8c + 800372c: f7ff fd10 bl 8003150 + + if(ae_encrypted_write(target_kn, target_kn, target_digest, new_digest, 32)) { + 8003730: 2320 movs r3, #32 + 8003732: 9300 str r3, [sp, #0] + 8003734: aa0c add r2, sp, #48 ; 0x30 + 8003736: ab14 add r3, sp, #80 ; 0x50 + 8003738: 4641 mov r1, r8 + 800373a: 4640 mov r0, r8 + 800373c: f7ff f93c bl 80029b8 + 8003740: 2800 cmp r0, #0 + 8003742: d137 bne.n 80037b4 + goto ae_fail; + } + + memcpy(target_digest, new_digest, 32); + 8003744: ae14 add r6, sp, #80 ; 0x50 + 8003746: ce0f ldmia r6!, {r0, r1, r2, r3} + 8003748: f10d 0e30 add.w lr, sp, #48 ; 0x30 + 800374c: e8ae 000f stmia.w lr!, {r0, r1, r2, r3} + 8003750: e896 000f ldmia.w r6, {r0, r1, r2, r3} + 8003754: e88e 000f stmia.w lr, {r0, r1, r2, r3} + } + + // Record new secret. + // Note the digest might have just changed above. + if(cf & (CHANGE_SECRET | CHANGE_DURESS_SECRET)) { + 8003758: f1b9 0f00 cmp.w r9, #0 + 800375c: d027 beq.n 80037ae + int secret_kn = -1, lastgood_kn = -1; + 800375e: aa1c add r2, sp, #112 ; 0x70 + 8003760: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 8003764: f842 3d20 str.w r3, [r2, #-32]! + lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn); + 8003768: a903 add r1, sp, #12 + 800376a: 4640 mov r0, r8 + + if(ae_encrypted_write(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN)){ + 800376c: f104 06b0 add.w r6, r4, #176 ; 0xb0 + 8003770: f04f 0948 mov.w r9, #72 ; 0x48 + } + + // Record new secret. + // Note the digest might have just changed above. + if(cf & (CHANGE_SECRET | CHANGE_DURESS_SECRET)) { + int secret_kn = -1, lastgood_kn = -1; + 8003774: 9303 str r3, [sp, #12] + lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn); + 8003776: f7ff fd5d bl 8003234 + + if(ae_encrypted_write(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN)){ + 800377a: f8cd 9000 str.w r9, [sp] + 800377e: 4633 mov r3, r6 + 8003780: aa0c add r2, sp, #48 ; 0x30 + 8003782: 4641 mov r1, r8 + 8003784: 9803 ldr r0, [sp, #12] + 8003786: f7ff f917 bl 80029b8 + 800378a: b998 cbnz r0, 80037b4 + goto ae_fail; + } + + // update the zero-secret flag to be correct. + if(cf & CHANGE_SECRET) { + 800378c: 073b lsls r3, r7, #28 + 800378e: d50e bpl.n 80037ae + if(check_all_zeros(args->secret, AE_SECRET_LEN)) { + 8003790: 4649 mov r1, r9 + 8003792: 4630 mov r0, r6 + 8003794: f7fe fb66 bl 8001e64 + 8003798: 6be3 ldr r3, [r4, #60] ; 0x3c + 800379a: b110 cbz r0, 80037a2 + args->state_flags |= PA_ZERO_SECRET; + 800379c: f043 0310 orr.w r3, r3, #16 + 80037a0: e001 b.n 80037a6 + } else { + args->state_flags &= ~PA_ZERO_SECRET; + 80037a2: f023 0310 bic.w r3, r3, #16 + 80037a6: 63e3 str r3, [r4, #60] ; 0x3c + } + _sign_attempt(args); + 80037a8: 4620 mov r0, r4 + 80037aa: f7ff fc51 bl 8003050 <_sign_attempt> + } + } + + ae_reset_chip(); + 80037ae: f7fe fceb bl 8002188 + + // NOTE: do **not** update args here, definately not with success or something! + + return 0; + 80037b2: e00e b.n 80037d2 + +ae_fail: + ae_reset_chip(); + 80037b4: f7fe fce8 bl 8002188 + + return EPIN_AE_FAIL; + 80037b8: f06f 0569 mvn.w r5, #105 ; 0x69 + 80037bc: e009 b.n 80037d2 + 80037be: 4605 mov r5, r0 + 80037c0: e007 b.n 80037d2 + int rv = _validate_attempt(args, false); + if(rv) return rv; + + if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) { + // must come here with a successful PIN login (so it's rate limited nicely) + return EPIN_WRONG_SUCCESS; + 80037c2: f06f 056c mvn.w r5, #108 ; 0x6c + 80037c6: e004 b.n 80037d2 + if(cf == 0) return EPIN_RANGE_ERR; + + if(cf & CHANGE_BRICKME_PIN) { + if(args->is_secondary) { + // only main PIN holder can define brickme PIN + return EPIN_PRIMARY_ONLY; + 80037c8: f06f 0571 mvn.w r5, #113 ; 0x71 + 80037cc: e001 b.n 80037d2 + } + if(cf != CHANGE_BRICKME_PIN) { + // only pin can be changed, nothing else. + return EPIN_BAD_REQUEST; + 80037ce: f06f 0567 mvn.w r5, #103 ; 0x67 + +ae_fail: + ae_reset_chip(); + + return EPIN_AE_FAIL; +} + 80037d2: 4628 mov r0, r5 + 80037d4: b01d add sp, #116 ; 0x74 + 80037d6: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 80037da: bf00 nop + 80037dc: 334d1858 .word 0x334d1858 + +080037e0 : +// To encourage not keeping the secret in memory, a way to fetch it after already +// have proven you know the PIN. +// + int +pin_fetch_secret(pinAttempt_t *args) +{ + 80037e0: b530 push {r4, r5, lr} + // Validate args and signature + int rv = _validate_attempt(args, false); + 80037e2: 2100 movs r1, #0 +// To encourage not keeping the secret in memory, a way to fetch it after already +// have proven you know the PIN. +// + int +pin_fetch_secret(pinAttempt_t *args) +{ + 80037e4: b097 sub sp, #92 ; 0x5c + 80037e6: 4604 mov r4, r0 + // Validate args and signature + int rv = _validate_attempt(args, false); + 80037e8: f7ff fc3a bl 8003060 <_validate_attempt> + if(rv) return rv; + 80037ec: 2800 cmp r0, #0 + 80037ee: d179 bne.n 80038e4 + + if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) { + 80037f0: 6be3 ldr r3, [r4, #60] ; 0x3c + 80037f2: 07da lsls r2, r3, #31 + 80037f4: d571 bpl.n 80038da + // must come here with a successful PIN login (so it's rate limited nicely) + return EPIN_WRONG_SUCCESS; + } + + // just in case? covered already by successful state_flags + if(args->delay_achieved < args->delay_required) { + 80037f6: 6ae2 ldr r2, [r4, #44] ; 0x2c + 80037f8: 6b23 ldr r3, [r4, #48] ; 0x30 + 80037fa: 429a cmp r2, r3 + 80037fc: d370 bcc.n 80038e0 + return EPIN_MUST_WAIT; + } + + // hash up the pin now. + uint8_t digest[32]; + pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL); + 80037fe: 4b3a ldr r3, [pc, #232] ; (80038e8 ) + 8003800: 6aa1 ldr r1, [r4, #40] ; 0x28 + 8003802: aa06 add r2, sp, #24 + 8003804: f104 0008 add.w r0, r4, #8 + 8003808: f7ff fca2 bl 8003150 + + // try it out / and determine if we should proceed under duress + int pin_kn = -1; + 800380c: ab16 add r3, sp, #88 ; 0x58 + 800380e: f04f 32ff mov.w r2, #4294967295 ; 0xffffffff + 8003812: f843 2d4c str.w r2, [r3, #-76]! + bool is_duress = false; + if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) { + 8003816: 6860 ldr r0, [r4, #4] + 8003818: 6aa2 ldr r2, [r4, #40] ; 0x28 + 800381a: 3000 adds r0, #0 + 800381c: fab2 f282 clz r2, r2 + 8003820: bf18 it ne + 8003822: 2001 movne r0, #1 + 8003824: 0952 lsrs r2, r2, #5 + 8003826: a906 add r1, sp, #24 + 8003828: f7ff fcce bl 80031c8 + 800382c: b930 cbnz r0, 800383c + is_duress = true; + } else { + // no real need to re-prove PIN knowledge. + // if they tricked us, doesn't matter as below the 580a validates it all again + pin_kn = args->is_secondary ? KEYNUM_pin_2 : KEYNUM_pin_1; + 800382e: 6863 ldr r3, [r4, #4] + 8003830: 2b00 cmp r3, #0 + 8003832: bf14 ite ne + 8003834: 2304 movne r3, #4 + 8003836: 2303 moveq r3, #3 + 8003838: 9303 str r3, [sp, #12] + 800383a: e000 b.n 800383e + + // try it out / and determine if we should proceed under duress + int pin_kn = -1; + bool is_duress = false; + if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) { + is_duress = true; + 800383c: 2001 movs r0, #1 + // no real need to re-prove PIN knowledge. + // if they tricked us, doesn't matter as below the 580a validates it all again + pin_kn = args->is_secondary ? KEYNUM_pin_2 : KEYNUM_pin_1; + } + + if(args->change_flags & CHANGE_DURESS_SECRET) { + 800383e: 6e63 ldr r3, [r4, #100] ; 0x64 + 8003840: 06db lsls r3, r3, #27 + 8003842: d52c bpl.n 800389e + // let them know the duress secret, iff: they are logged into + // corresponding primary pin (not duress) and they know the duress + // pin as well. + // LATER: this feature not being used since we only write the duress secret + if(is_duress) return EPIN_AUTH_FAIL; + 8003844: bb40 cbnz r0, 8003898 + + int target_kn = args->is_secondary ? KEYNUM_pin_4 : KEYNUM_pin_3; + 8003846: 6863 ldr r3, [r4, #4] + + uint8_t target_digest[32]; + pin_hash(args->old_pin, args->old_pin_len, target_digest, PIN_PURPOSE_NORMAL); + 8003848: f8d4 1088 ldr.w r1, [r4, #136] ; 0x88 + // corresponding primary pin (not duress) and they know the duress + // pin as well. + // LATER: this feature not being used since we only write the duress secret + if(is_duress) return EPIN_AUTH_FAIL; + + int target_kn = args->is_secondary ? KEYNUM_pin_4 : KEYNUM_pin_3; + 800384c: 2b00 cmp r3, #0 + 800384e: bf14 ite ne + 8003850: 2508 movne r5, #8 + 8003852: 2507 moveq r5, #7 + + uint8_t target_digest[32]; + pin_hash(args->old_pin, args->old_pin_len, target_digest, PIN_PURPOSE_NORMAL); + 8003854: 4b24 ldr r3, [pc, #144] ; (80038e8 ) + 8003856: aa0e add r2, sp, #56 ; 0x38 + 8003858: f104 0068 add.w r0, r4, #104 ; 0x68 + 800385c: f7ff fc78 bl 8003150 + + // Check the that pin is right (optional, but if wrong, encrypted read gives garb) + ae_pair_unlock(); + 8003860: f7fe fefa bl 8002658 + if(ae_checkmac(target_kn, target_digest)) { + 8003864: a90e add r1, sp, #56 ; 0x38 + 8003866: 4628 mov r0, r5 + 8003868: f7fe fe72 bl 8002550 + 800386c: b110 cbz r0, 8003874 + // they got old PIN wrong, we won't be able to help them + ae_reset_chip(); + 800386e: f7fe fc8b bl 8002188 + + return EPIN_AUTH_FAIL; + 8003872: e011 b.n 8003898 + } + + int secret_kn = -1, lastgood_kn = -1; + 8003874: aa16 add r2, sp, #88 ; 0x58 + 8003876: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 800387a: f842 3d44 str.w r3, [r2, #-68]! + lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn); + 800387e: a904 add r1, sp, #16 + 8003880: 4628 mov r0, r5 + ae_reset_chip(); + + return EPIN_AUTH_FAIL; + } + + int secret_kn = -1, lastgood_kn = -1; + 8003882: 9304 str r3, [sp, #16] + lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn); + 8003884: f7ff fcd6 bl 8003234 + + rv = ae_encrypted_read(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN); + 8003888: 2348 movs r3, #72 ; 0x48 + 800388a: 9300 str r3, [sp, #0] + 800388c: aa0e add r2, sp, #56 ; 0x38 + 800388e: f104 03b0 add.w r3, r4, #176 ; 0xb0 + 8003892: 4629 mov r1, r5 + 8003894: 9804 ldr r0, [sp, #16] + 8003896: e013 b.n 80038c0 + if(args->change_flags & CHANGE_DURESS_SECRET) { + // let them know the duress secret, iff: they are logged into + // corresponding primary pin (not duress) and they know the duress + // pin as well. + // LATER: this feature not being used since we only write the duress secret + if(is_duress) return EPIN_AUTH_FAIL; + 8003898: f06f 006f mvn.w r0, #111 ; 0x6f + 800389c: e022 b.n 80038e4 + int secret_kn = -1, lastgood_kn = -1; + lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn); + + rv = ae_encrypted_read(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN); + } else { + int secret_kn = -1, lastgood_kn = -1; + 800389e: aa16 add r2, sp, #88 ; 0x58 + 80038a0: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 80038a4: f842 3d20 str.w r3, [r2, #-32]! + lookup_secret_lastgood(pin_kn, &secret_kn, &lastgood_kn); + 80038a8: a905 add r1, sp, #20 + 80038aa: 9803 ldr r0, [sp, #12] + int secret_kn = -1, lastgood_kn = -1; + lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn); + + rv = ae_encrypted_read(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN); + } else { + int secret_kn = -1, lastgood_kn = -1; + 80038ac: 9305 str r3, [sp, #20] + lookup_secret_lastgood(pin_kn, &secret_kn, &lastgood_kn); + 80038ae: f7ff fcc1 bl 8003234 + + // read out the secret that corresponds to that pin + rv = ae_encrypted_read(secret_kn, pin_kn, digest, args->secret, AE_SECRET_LEN); + 80038b2: 2348 movs r3, #72 ; 0x48 + 80038b4: 9903 ldr r1, [sp, #12] + 80038b6: 9805 ldr r0, [sp, #20] + 80038b8: 9300 str r3, [sp, #0] + 80038ba: aa06 add r2, sp, #24 + 80038bc: f104 03b0 add.w r3, r4, #176 ; 0xb0 + 80038c0: f7ff f842 bl 8002948 + 80038c4: 4604 mov r4, r0 + } + + if(rv) { + 80038c6: b120 cbz r0, 80038d2 + ae_reset_chip(); + 80038c8: f7fe fc5e bl 8002188 + + return EPIN_AE_FAIL; + 80038cc: f06f 0069 mvn.w r0, #105 ; 0x69 + 80038d0: e008 b.n 80038e4 + } + + ae_reset_chip(); + 80038d2: f7fe fc59 bl 8002188 + + return 0; + 80038d6: 4620 mov r0, r4 + 80038d8: e004 b.n 80038e4 + int rv = _validate_attempt(args, false); + if(rv) return rv; + + if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) { + // must come here with a successful PIN login (so it's rate limited nicely) + return EPIN_WRONG_SUCCESS; + 80038da: f06f 006c mvn.w r0, #108 ; 0x6c + 80038de: e001 b.n 80038e4 + } + + // just in case? covered already by successful state_flags + if(args->delay_achieved < args->delay_required) { + return EPIN_MUST_WAIT; + 80038e0: f06f 006a mvn.w r0, #106 ; 0x6a + } + + ae_reset_chip(); + + return 0; +} + 80038e4: b017 add sp, #92 ; 0x5c + 80038e6: bd30 pop {r4, r5, pc} + 80038e8: 334d1858 .word 0x334d1858 + +080038ec : +// +// Record current flash checksum and make green light go on. +// + int +pin_firmware_greenlight(pinAttempt_t *args) +{ + 80038ec: b510 push {r4, lr} + // Validate args and signature + int rv = _validate_attempt(args, false); + 80038ee: 2100 movs r1, #0 +// +// Record current flash checksum and make green light go on. +// + int +pin_firmware_greenlight(pinAttempt_t *args) +{ + 80038f0: b09a sub sp, #104 ; 0x68 + 80038f2: 4604 mov r4, r0 + // Validate args and signature + int rv = _validate_attempt(args, false); + 80038f4: f7ff fbb4 bl 8003060 <_validate_attempt> + if(rv) return rv; + 80038f8: bb50 cbnz r0, 8003950 + + if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) { + 80038fa: 6be3 ldr r3, [r4, #60] ; 0x3c + 80038fc: 07db lsls r3, r3, #31 + 80038fe: d529 bpl.n 8003954 + // must come here with a successful PIN login (so it's rate limited nicely) + return EPIN_WRONG_SUCCESS; + } + + if(args->is_secondary) { + 8003900: 6863 ldr r3, [r4, #4] + 8003902: bb53 cbnz r3, 800395a + // only main PIN holder can do this + return EPIN_PRIMARY_ONLY; + } + + // just in case? + if(args->delay_achieved < args->delay_required) { + 8003904: 6ae2 ldr r2, [r4, #44] ; 0x2c + 8003906: 6b23 ldr r3, [r4, #48] ; 0x30 + 8003908: 429a cmp r2, r3 + 800390a: d329 bcc.n 8003960 + return EPIN_MUST_WAIT; + } + + // step 1: calc the value to use + uint8_t fw_check[32], world_check[32]; + checksum_flash(fw_check, world_check); + 800390c: a90a add r1, sp, #40 ; 0x28 + 800390e: a802 add r0, sp, #8 + 8003910: f7fd feb6 bl 8001680 + + // re-calc correct PIN + uint8_t digest[32]; + pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL); + 8003914: 6aa1 ldr r1, [r4, #40] ; 0x28 + 8003916: 4b16 ldr r3, [pc, #88] ; (8003970 ) + 8003918: f104 0008 add.w r0, r4, #8 + 800391c: aa12 add r2, sp, #72 ; 0x48 + 800391e: f7ff fc17 bl 8003150 + + // write it out to chip. + if(warmup_ae()) return EPIN_I_AM_BRICK; + 8003922: f7ff fbd5 bl 80030d0 + 8003926: 4604 mov r4, r0 + 8003928: b9e8 cbnz r0, 8003966 + + rv = ae_encrypted_write(KEYNUM_firmware, KEYNUM_pin_1, digest, world_check, 32); + 800392a: 2320 movs r3, #32 + 800392c: 9300 str r3, [sp, #0] + 800392e: aa12 add r2, sp, #72 ; 0x48 + 8003930: ab0a add r3, sp, #40 ; 0x28 + 8003932: 2103 movs r1, #3 + 8003934: 200e movs r0, #14 + 8003936: f7ff f83f bl 80029b8 + if(rv) { + 800393a: b120 cbz r0, 8003946 + ae_reset_chip(); + 800393c: f7fe fc24 bl 8002188 + + return EPIN_AE_FAIL; + 8003940: f06f 0469 mvn.w r4, #105 ; 0x69 + 8003944: e011 b.n 800396a + } + + // turn on light + rv = ae_set_gpio_secure(world_check); + 8003946: a80a add r0, sp, #40 ; 0x28 + 8003948: f7ff f96c bl 8002c24 + if(rv) { + 800394c: b168 cbz r0, 800396a + 800394e: e7f5 b.n 800393c + 8003950: 4604 mov r4, r0 + 8003952: e00a b.n 800396a + int rv = _validate_attempt(args, false); + if(rv) return rv; + + if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) { + // must come here with a successful PIN login (so it's rate limited nicely) + return EPIN_WRONG_SUCCESS; + 8003954: f06f 046c mvn.w r4, #108 ; 0x6c + 8003958: e007 b.n 800396a + } + + if(args->is_secondary) { + // only main PIN holder can do this + return EPIN_PRIMARY_ONLY; + 800395a: f06f 0471 mvn.w r4, #113 ; 0x71 + 800395e: e004 b.n 800396a + } + + // just in case? + if(args->delay_achieved < args->delay_required) { + return EPIN_MUST_WAIT; + 8003960: f06f 046a mvn.w r4, #106 ; 0x6a + 8003964: e001 b.n 800396a + // re-calc correct PIN + uint8_t digest[32]; + pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL); + + // write it out to chip. + if(warmup_ae()) return EPIN_I_AM_BRICK; + 8003966: f06f 0468 mvn.w r4, #104 ; 0x68 + + return EPIN_AE_FAIL; + } + + return 0; +} + 800396a: 4620 mov r0, r4 + 800396c: b01a add sp, #104 ; 0x68 + 800396e: bd10 pop {r4, pc} + 8003970: 334d1858 .word 0x334d1858 + +08003974 : + +// sf_read_bytes() +// + static HAL_StatusTypeDef +sf_read(uint32_t addr, int len, uint8_t *buf) +{ + 8003974: b573 push {r0, r1, r4, r5, r6, lr} + // send via SPI(1) + uint8_t pkt[5] = { CMD_FAST_READ, + 8003976: 230b movs r3, #11 + 8003978: f88d 3000 strb.w r3, [sp] + 800397c: 0c03 lsrs r3, r0, #16 + 800397e: f88d 3001 strb.w r3, [sp, #1] + 8003982: f88d 0003 strb.w r0, [sp, #3] + 8003986: 0a03 lsrs r3, r0, #8 + +// sf_read_bytes() +// + static HAL_StatusTypeDef +sf_read(uint32_t addr, int len, uint8_t *buf) +{ + 8003988: 460e mov r6, r1 + // send via SPI(1) + uint8_t pkt[5] = { CMD_FAST_READ, + (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, + 0x0 }; // for fast-read case + + CS_LOW(); + 800398a: 4812 ldr r0, [pc, #72] ; (80039d4 ) +// + static HAL_StatusTypeDef +sf_read(uint32_t addr, int len, uint8_t *buf) +{ + // send via SPI(1) + uint8_t pkt[5] = { CMD_FAST_READ, + 800398c: f88d 3002 strb.w r3, [sp, #2] + (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, + 0x0 }; // for fast-read case + + CS_LOW(); + 8003990: f44f 7100 mov.w r1, #512 ; 0x200 + +// sf_read_bytes() +// + static HAL_StatusTypeDef +sf_read(uint32_t addr, int len, uint8_t *buf) +{ + 8003994: 4615 mov r5, r2 + // send via SPI(1) + uint8_t pkt[5] = { CMD_FAST_READ, + 8003996: 2200 movs r2, #0 + 8003998: f88d 2004 strb.w r2, [sp, #4] + (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, + 0x0 }; // for fast-read case + + CS_LOW(); + 800399c: f7fd fb8a bl 80010b4 + + HAL_StatusTypeDef rv = HAL_SPI_Transmit(&sf_spi_port, pkt, sizeof(pkt), HAL_MAX_DELAY); + 80039a0: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 80039a4: 2205 movs r2, #5 + 80039a6: 4669 mov r1, sp + 80039a8: 480b ldr r0, [pc, #44] ; (80039d8 ) + 80039aa: f7fd fc0e bl 80011ca + if(rv == HAL_OK) { + 80039ae: 4604 mov r4, r0 + 80039b0: b938 cbnz r0, 80039c2 + rv = HAL_SPI_Receive(&sf_spi_port, buf, len, HAL_MAX_DELAY); + 80039b2: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 80039b6: b2b2 uxth r2, r6 + 80039b8: 4629 mov r1, r5 + 80039ba: 4807 ldr r0, [pc, #28] ; (80039d8 ) + 80039bc: f7fd fd84 bl 80014c8 + 80039c0: 4604 mov r4, r0 + } + + CS_HIGH(); + 80039c2: 2201 movs r2, #1 + 80039c4: f44f 7100 mov.w r1, #512 ; 0x200 + 80039c8: 4802 ldr r0, [pc, #8] ; (80039d4 ) + 80039ca: f7fd fb73 bl 80010b4 + + return rv; +} + 80039ce: 4620 mov r0, r4 + 80039d0: b002 add sp, #8 + 80039d2: bd70 pop {r4, r5, r6, pc} + 80039d4: 48000400 .word 0x48000400 + 80039d8: 100062e0 .word 0x100062e0 + +080039dc : +} + +// sf_write() +// + static HAL_StatusTypeDef +sf_write(uint32_t addr, int len, const uint8_t *buf) + 80039dc: b5f7 push {r0, r1, r2, r4, r5, r6, r7, lr} +// sf_write_enable() +// + static HAL_StatusTypeDef +sf_write_enable(void) +{ + uint8_t pkt = CMD_WREN; + 80039de: ad02 add r5, sp, #8 + 80039e0: 2306 movs r3, #6 + 80039e2: f805 3d04 strb.w r3, [r5, #-4]! + + CS_LOW(); + 80039e6: 2200 movs r2, #0 +} + +// sf_write() +// + static HAL_StatusTypeDef +sf_write(uint32_t addr, int len, const uint8_t *buf) + 80039e8: 4606 mov r6, r0 + 80039ea: 460f mov r7, r1 + static HAL_StatusTypeDef +sf_write_enable(void) +{ + uint8_t pkt = CMD_WREN; + + CS_LOW(); + 80039ec: 4834 ldr r0, [pc, #208] ; (8003ac0 ) + 80039ee: f44f 7100 mov.w r1, #512 ; 0x200 + 80039f2: f7fd fb5f bl 80010b4 + + HAL_StatusTypeDef rv = HAL_SPI_Transmit(&sf_spi_port, &pkt, 1, HAL_MAX_DELAY); + 80039f6: 2201 movs r2, #1 + 80039f8: 4629 mov r1, r5 + 80039fa: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 80039fe: 4831 ldr r0, [pc, #196] ; (8003ac4 ) + 8003a00: f7fd fbe3 bl 80011ca + + CS_HIGH(); + 8003a04: 2201 movs r2, #1 +{ + uint8_t pkt = CMD_WREN; + + CS_LOW(); + + HAL_StatusTypeDef rv = HAL_SPI_Transmit(&sf_spi_port, &pkt, 1, HAL_MAX_DELAY); + 8003a06: 4604 mov r4, r0 + + CS_HIGH(); + 8003a08: f44f 7100 mov.w r1, #512 ; 0x200 + 8003a0c: 482c ldr r0, [pc, #176] ; (8003ac0 ) + 8003a0e: f7fd fb51 bl 80010b4 + static HAL_StatusTypeDef +sf_write(uint32_t addr, int len, const uint8_t *buf) +{ + // enable writing + HAL_StatusTypeDef rv = sf_write_enable(); + if(rv) return rv; + 8003a12: 2c00 cmp r4, #0 + 8003a14: d151 bne.n 8003aba + + // do a "PAGE Program" aka. write + uint8_t pkt[4] = { CMD_WRITE, + 8003a16: 2302 movs r3, #2 + 8003a18: f88d 3004 strb.w r3, [sp, #4] + 8003a1c: 0c33 lsrs r3, r6, #16 + (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff + }; + + CS_LOW(); + 8003a1e: 4622 mov r2, r4 + // enable writing + HAL_StatusTypeDef rv = sf_write_enable(); + if(rv) return rv; + + // do a "PAGE Program" aka. write + uint8_t pkt[4] = { CMD_WRITE, + 8003a20: f88d 3005 strb.w r3, [sp, #5] + (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff + }; + + CS_LOW(); + 8003a24: f44f 7100 mov.w r1, #512 ; 0x200 + // enable writing + HAL_StatusTypeDef rv = sf_write_enable(); + if(rv) return rv; + + // do a "PAGE Program" aka. write + uint8_t pkt[4] = { CMD_WRITE, + 8003a28: 0a33 lsrs r3, r6, #8 + (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff + }; + + CS_LOW(); + 8003a2a: 4825 ldr r0, [pc, #148] ; (8003ac0 ) + // enable writing + HAL_StatusTypeDef rv = sf_write_enable(); + if(rv) return rv; + + // do a "PAGE Program" aka. write + uint8_t pkt[4] = { CMD_WRITE, + 8003a2c: f88d 3006 strb.w r3, [sp, #6] + 8003a30: f88d 6007 strb.w r6, [sp, #7] + (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff + }; + + CS_LOW(); + 8003a34: f7fd fb3e bl 80010b4 + + rv = HAL_SPI_Transmit(&sf_spi_port, pkt, sizeof(pkt), HAL_MAX_DELAY); + 8003a38: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 8003a3c: 2204 movs r2, #4 + 8003a3e: 4629 mov r1, r5 + 8003a40: 4820 ldr r0, [pc, #128] ; (8003ac4 ) + 8003a42: f7fd fbc2 bl 80011ca + if(rv == HAL_OK) { + 8003a46: 4604 mov r4, r0 + 8003a48: b938 cbnz r0, 8003a5a + rv = HAL_SPI_Transmit(&sf_spi_port, (uint8_t *)buf, len, HAL_MAX_DELAY); + 8003a4a: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 8003a4e: 2280 movs r2, #128 ; 0x80 + 8003a50: 4639 mov r1, r7 + 8003a52: 481c ldr r0, [pc, #112] ; (8003ac4 ) + 8003a54: f7fd fbb9 bl 80011ca + 8003a58: 4604 mov r4, r0 + } + + CS_HIGH(); + 8003a5a: 2201 movs r2, #1 + 8003a5c: f44f 7100 mov.w r1, #512 ; 0x200 + 8003a60: 4817 ldr r0, [pc, #92] ; (8003ac0 ) + 8003a62: f7fd fb27 bl 80010b4 + + if(rv == HAL_OK) { + 8003a66: bb44 cbnz r4, 8003aba +sf_wait_wip_done() +{ + // read RDSR (status register) and busy-wait until + // the write operation is done + while(1) { + uint8_t pkt = CMD_RDSR, stat = 0; + 8003a68: 2305 movs r3, #5 + 8003a6a: 2200 movs r2, #0 + + CS_LOW(); + 8003a6c: f44f 7100 mov.w r1, #512 ; 0x200 + 8003a70: 4813 ldr r0, [pc, #76] ; (8003ac0 ) +sf_wait_wip_done() +{ + // read RDSR (status register) and busy-wait until + // the write operation is done + while(1) { + uint8_t pkt = CMD_RDSR, stat = 0; + 8003a72: f88d 3002 strb.w r3, [sp, #2] + 8003a76: f88d 2003 strb.w r2, [sp, #3] + + CS_LOW(); + 8003a7a: f7fd fb1b bl 80010b4 + + HAL_StatusTypeDef rv = HAL_SPI_Transmit(&sf_spi_port, &pkt, 1, HAL_MAX_DELAY); + 8003a7e: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 8003a82: 2201 movs r2, #1 + 8003a84: f10d 0102 add.w r1, sp, #2 + 8003a88: 480e ldr r0, [pc, #56] ; (8003ac4 ) + 8003a8a: f7fd fb9e bl 80011ca + + if(rv == HAL_OK) { + 8003a8e: 4604 mov r4, r0 + 8003a90: b940 cbnz r0, 8003aa4 + rv = HAL_SPI_Receive(&sf_spi_port, &stat, 1, HAL_MAX_DELAY); + 8003a92: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 8003a96: 2201 movs r2, #1 + 8003a98: f10d 0103 add.w r1, sp, #3 + 8003a9c: 4809 ldr r0, [pc, #36] ; (8003ac4 ) + 8003a9e: f7fd fd13 bl 80014c8 + 8003aa2: 4604 mov r4, r0 + } + + CS_HIGH(); + 8003aa4: 2201 movs r2, #1 + 8003aa6: f44f 7100 mov.w r1, #512 ; 0x200 + 8003aaa: 4805 ldr r0, [pc, #20] ; (8003ac0 ) + 8003aac: f7fd fb02 bl 80010b4 + + if(rv != HAL_OK) return rv; + 8003ab0: b91c cbnz r4, 8003aba + + if(stat & 0x01) continue; + 8003ab2: f89d 3003 ldrb.w r3, [sp, #3] + 8003ab6: 07db lsls r3, r3, #31 + 8003ab8: d4d6 bmi.n 8003a68 + static HAL_StatusTypeDef +sf_write(uint32_t addr, int len, const uint8_t *buf) +{ + // enable writing + HAL_StatusTypeDef rv = sf_write_enable(); + if(rv) return rv; + 8003aba: 4620 mov r0, r4 + if(rv == HAL_OK) { + rv = sf_wait_wip_done(); + } + + return rv; +} + 8003abc: b003 add sp, #12 + 8003abe: bdf0 pop {r4, r5, r6, r7, pc} + 8003ac0: 48000400 .word 0x48000400 + 8003ac4: 100062e0 .word 0x100062e0 + +08003ac8 : +sf_setup(void) +{ + HAL_StatusTypeDef rv; + + // enable some internal clocks + __HAL_RCC_GPIOB_CLK_ENABLE(); + 8003ac8: 4b2d ldr r3, [pc, #180] ; (8003b80 ) +// +// Ok to call this lots. +// + void +sf_setup(void) +{ + 8003aca: b530 push {r4, r5, lr} + HAL_StatusTypeDef rv; + + // enable some internal clocks + __HAL_RCC_GPIOB_CLK_ENABLE(); + 8003acc: 6cda ldr r2, [r3, #76] ; 0x4c + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_SPI2_CLK_ENABLE(); + + // simple pins + GPIO_InitTypeDef setup = { + 8003ace: 4d2d ldr r5, [pc, #180] ; (8003b84 ) +sf_setup(void) +{ + HAL_StatusTypeDef rv; + + // enable some internal clocks + __HAL_RCC_GPIOB_CLK_ENABLE(); + 8003ad0: f042 0202 orr.w r2, r2, #2 + 8003ad4: 64da str r2, [r3, #76] ; 0x4c + 8003ad6: 6cda ldr r2, [r3, #76] ; 0x4c +// +// Ok to call this lots. +// + void +sf_setup(void) +{ + 8003ad8: b089 sub sp, #36 ; 0x24 + HAL_StatusTypeDef rv; + + // enable some internal clocks + __HAL_RCC_GPIOB_CLK_ENABLE(); + 8003ada: f002 0202 and.w r2, r2, #2 + 8003ade: 9200 str r2, [sp, #0] + 8003ae0: 9a00 ldr r2, [sp, #0] + __HAL_RCC_GPIOC_CLK_ENABLE(); + 8003ae2: 6cda ldr r2, [r3, #76] ; 0x4c + 8003ae4: f042 0204 orr.w r2, r2, #4 + 8003ae8: 64da str r2, [r3, #76] ; 0x4c + 8003aea: 6cda ldr r2, [r3, #76] ; 0x4c + 8003aec: f002 0204 and.w r2, r2, #4 + 8003af0: 9201 str r2, [sp, #4] + 8003af2: 9a01 ldr r2, [sp, #4] + __HAL_RCC_SPI2_CLK_ENABLE(); + 8003af4: 6d9a ldr r2, [r3, #88] ; 0x58 + 8003af6: f442 4280 orr.w r2, r2, #16384 ; 0x4000 + 8003afa: 659a str r2, [r3, #88] ; 0x58 + 8003afc: 6d9b ldr r3, [r3, #88] ; 0x58 + 8003afe: f403 4380 and.w r3, r3, #16384 ; 0x4000 + 8003b02: 9302 str r3, [sp, #8] + 8003b04: 9b02 ldr r3, [sp, #8] + + // simple pins + GPIO_InitTypeDef setup = { + 8003b06: cd0f ldmia r5!, {r0, r1, r2, r3} + 8003b08: ac03 add r4, sp, #12 + 8003b0a: c40f stmia r4!, {r0, r1, r2, r3} + 8003b0c: 682b ldr r3, [r5, #0] + .Mode = GPIO_MODE_OUTPUT_PP, + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_MEDIUM, + .Alternate = 0, + }; + HAL_GPIO_Init(GPIOB, &setup); + 8003b0e: 481e ldr r0, [pc, #120] ; (8003b88 ) + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_SPI2_CLK_ENABLE(); + + // simple pins + GPIO_InitTypeDef setup = { + 8003b10: 6023 str r3, [r4, #0] + .Mode = GPIO_MODE_OUTPUT_PP, + .Pull = GPIO_NOPULL, + .Speed = GPIO_SPEED_FREQ_MEDIUM, + .Alternate = 0, + }; + HAL_GPIO_Init(GPIOB, &setup); + 8003b12: a903 add r1, sp, #12 + 8003b14: f7fd f950 bl 8000db8 + + // starting value: high + HAL_GPIO_WritePin(GPIOB, SF_CS_PIN, 1); + 8003b18: 2201 movs r2, #1 + 8003b1a: f44f 7100 mov.w r1, #512 ; 0x200 + 8003b1e: 481a ldr r0, [pc, #104] ; (8003b88 ) + HAL_GPIO_Init(GPIOB, &setup); + + setup.Pin = SF_SPI_MOSI | SF_SPI_MISO; + HAL_GPIO_Init(GPIOC, &setup); + + memset(&sf_spi_port, 0, sizeof(sf_spi_port)); + 8003b20: 4c1a ldr r4, [pc, #104] ; (8003b8c ) + .Alternate = 0, + }; + HAL_GPIO_Init(GPIOB, &setup); + + // starting value: high + HAL_GPIO_WritePin(GPIOB, SF_CS_PIN, 1); + 8003b22: f7fd fac7 bl 80010b4 + + // SPI pins, on various ports + setup.Pin = SF_SPI_SCK; + 8003b26: f44f 6380 mov.w r3, #1024 ; 0x400 + 8003b2a: 9303 str r3, [sp, #12] + setup.Mode = GPIO_MODE_AF_PP; + 8003b2c: 2302 movs r3, #2 + 8003b2e: 9304 str r3, [sp, #16] + setup.Alternate = GPIO_AF5_SPI2; + HAL_GPIO_Init(GPIOB, &setup); + 8003b30: a903 add r1, sp, #12 + HAL_GPIO_WritePin(GPIOB, SF_CS_PIN, 1); + + // SPI pins, on various ports + setup.Pin = SF_SPI_SCK; + setup.Mode = GPIO_MODE_AF_PP; + setup.Alternate = GPIO_AF5_SPI2; + 8003b32: 2305 movs r3, #5 + HAL_GPIO_Init(GPIOB, &setup); + 8003b34: 4814 ldr r0, [pc, #80] ; (8003b88 ) + HAL_GPIO_WritePin(GPIOB, SF_CS_PIN, 1); + + // SPI pins, on various ports + setup.Pin = SF_SPI_SCK; + setup.Mode = GPIO_MODE_AF_PP; + setup.Alternate = GPIO_AF5_SPI2; + 8003b36: 9307 str r3, [sp, #28] + HAL_GPIO_Init(GPIOB, &setup); + 8003b38: f7fd f93e bl 8000db8 + + setup.Pin = SF_SPI_MOSI | SF_SPI_MISO; + 8003b3c: 230c movs r3, #12 + HAL_GPIO_Init(GPIOC, &setup); + 8003b3e: eb0d 0103 add.w r1, sp, r3 + 8003b42: 4813 ldr r0, [pc, #76] ; (8003b90 ) + setup.Pin = SF_SPI_SCK; + setup.Mode = GPIO_MODE_AF_PP; + setup.Alternate = GPIO_AF5_SPI2; + HAL_GPIO_Init(GPIOB, &setup); + + setup.Pin = SF_SPI_MOSI | SF_SPI_MISO; + 8003b44: 9303 str r3, [sp, #12] + HAL_GPIO_Init(GPIOC, &setup); + 8003b46: f7fd f937 bl 8000db8 + + memset(&sf_spi_port, 0, sizeof(sf_spi_port)); + 8003b4a: 2264 movs r2, #100 ; 0x64 + 8003b4c: 2100 movs r1, #0 + 8003b4e: 4620 mov r0, r4 + 8003b50: f002 febe bl 80068d0 + + sf_spi_port.Instance = SPI2; + + // see SPI_InitTypeDef + sf_spi_port.Init.Mode = SPI_MODE_MASTER; + 8003b54: 4a0f ldr r2, [pc, #60] ; (8003b94 ) + 8003b56: f44f 7382 mov.w r3, #260 ; 0x104 + 8003b5a: e884 000c stmia.w r4, {r2, r3} + sf_spi_port.Init.Direction = SPI_DIRECTION_2LINES; + sf_spi_port.Init.DataSize = SPI_DATASIZE_8BIT; + 8003b5e: f44f 63e0 mov.w r3, #1792 ; 0x700 + 8003b62: 60e3 str r3, [r4, #12] + sf_spi_port.Init.CLKPolarity = SPI_POLARITY_LOW; + sf_spi_port.Init.CLKPhase = SPI_PHASE_1EDGE; + sf_spi_port.Init.NSS = SPI_NSS_SOFT; + 8003b64: f44f 7300 mov.w r3, #512 ; 0x200 + 8003b68: 61a3 str r3, [r4, #24] + sf_spi_port.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // conservative + sf_spi_port.Init.FirstBit = SPI_FIRSTBIT_MSB; + sf_spi_port.Init.TIMode = SPI_TIMODE_DISABLED; + sf_spi_port.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; + + rv = HAL_SPI_Init(&sf_spi_port); + 8003b6a: 4620 mov r0, r4 + sf_spi_port.Init.Direction = SPI_DIRECTION_2LINES; + sf_spi_port.Init.DataSize = SPI_DATASIZE_8BIT; + sf_spi_port.Init.CLKPolarity = SPI_POLARITY_LOW; + sf_spi_port.Init.CLKPhase = SPI_PHASE_1EDGE; + sf_spi_port.Init.NSS = SPI_NSS_SOFT; + sf_spi_port.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // conservative + 8003b6c: 2318 movs r3, #24 + 8003b6e: 61e3 str r3, [r4, #28] + sf_spi_port.Init.FirstBit = SPI_FIRSTBIT_MSB; + sf_spi_port.Init.TIMode = SPI_TIMODE_DISABLED; + sf_spi_port.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; + + rv = HAL_SPI_Init(&sf_spi_port); + 8003b70: f7fd fae4 bl 800113c + ASSERT(!rv); + 8003b74: b110 cbz r0, 8003b7c + 8003b76: 4808 ldr r0, [pc, #32] ; (8003b98 ) + 8003b78: f7fc fc28 bl 80003cc +} + 8003b7c: b009 add sp, #36 ; 0x24 + 8003b7e: bd30 pop {r4, r5, pc} + 8003b80: 40021000 .word 0x40021000 + 8003b84: 080073a0 .word 0x080073a0 + 8003b88: 48000400 .word 0x48000400 + 8003b8c: 100062e0 .word 0x100062e0 + 8003b90: 48000800 .word 0x48000800 + 8003b94: 40003800 .word 0x40003800 + 8003b98: 08006940 .word 0x08006940 + +08003b9c : +// in SPI flash. Similar to checksum_flash() in verify.c except only +// concerned with firmware, not the rest of flash. +// + void +sf_calc_checksum(const coldcardFirmwareHeader_t *hdr, uint8_t fw_digest[32]) +{ + 8003b9c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 8003ba0: b0bd sub sp, #244 ; 0xf4 + + SHA256_CTX ctx; + uint32_t total_len = hdr->firmware_length; + 8003ba2: f8d0 8018 ldr.w r8, [r0, #24] +// in SPI flash. Similar to checksum_flash() in verify.c except only +// concerned with firmware, not the rest of flash. +// + void +sf_calc_checksum(const coldcardFirmwareHeader_t *hdr, uint8_t fw_digest[32]) +{ + 8003ba6: 4607 mov r7, r0 + + SHA256_CTX ctx; + uint32_t total_len = hdr->firmware_length; + + sha256_init(&ctx); + 8003ba8: 4668 mov r0, sp +// in SPI flash. Similar to checksum_flash() in verify.c except only +// concerned with firmware, not the rest of flash. +// + void +sf_calc_checksum(const coldcardFirmwareHeader_t *hdr, uint8_t fw_digest[32]) +{ + 8003baa: 460e mov r6, r1 + + SHA256_CTX ctx; + uint32_t total_len = hdr->firmware_length; + + sha256_init(&ctx); + 8003bac: f001 fbee bl 800538c + + uint32_t pos = 0; + uint8_t buf[128]; + STATIC_ASSERT(FW_HEADER_OFFSET % sizeof(buf) == 0); + + oled_show_progress(screen_verify, 1); + 8003bb0: 2101 movs r1, #1 + 8003bb2: 482c ldr r0, [pc, #176] ; (8003c64 ) + 8003bb4: f7fd f880 bl 8000cb8 + SHA256_CTX ctx; + uint32_t total_len = hdr->firmware_length; + + sha256_init(&ctx); + + uint32_t pos = 0; + 8003bb8: 2400 movs r4, #0 + + oled_show_progress(screen_verify, 1); + + // do part up to header. + for(; pos < FW_HEADER_OFFSET; pos += sizeof(buf)) { + if(sf_read(pos, sizeof(buf), buf) != HAL_OK) { + 8003bba: aa1c add r2, sp, #112 ; 0x70 + 8003bbc: 2180 movs r1, #128 ; 0x80 + 8003bbe: 4620 mov r0, r4 + 8003bc0: f7ff fed8 bl 8003974 + 8003bc4: 4605 mov r5, r0 + 8003bc6: b138 cbz r0, 8003bd8 + fail: + // fail for sure with bad signature; user can try again + memset(fw_digest, 0, 32); + 8003bc8: 2220 movs r2, #32 + 8003bca: 2100 movs r1, #0 + 8003bcc: 4630 mov r0, r6 + + // double SHA256 + sha256_init(&ctx); + sha256_update(&ctx, fw_digest, 32); + sha256_final(&ctx, fw_digest); +} + 8003bce: b03d add sp, #244 ; 0xf4 + 8003bd0: e8bd 43f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, lr} + // do part up to header. + for(; pos < FW_HEADER_OFFSET; pos += sizeof(buf)) { + if(sf_read(pos, sizeof(buf), buf) != HAL_OK) { + fail: + // fail for sure with bad signature; user can try again + memset(fw_digest, 0, 32); + 8003bd4: f002 be7c b.w 80068d0 + return; + } + + sha256_update(&ctx, buf, sizeof(buf)); + 8003bd8: 2280 movs r2, #128 ; 0x80 + 8003bda: a91c add r1, sp, #112 ; 0x70 + 8003bdc: 4668 mov r0, sp + STATIC_ASSERT(FW_HEADER_OFFSET % sizeof(buf) == 0); + + oled_show_progress(screen_verify, 1); + + // do part up to header. + for(; pos < FW_HEADER_OFFSET; pos += sizeof(buf)) { + 8003bde: 3480 adds r4, #128 ; 0x80 + // fail for sure with bad signature; user can try again + memset(fw_digest, 0, 32); + return; + } + + sha256_update(&ctx, buf, sizeof(buf)); + 8003be0: f001 fbfe bl 80053e0 + STATIC_ASSERT(FW_HEADER_OFFSET % sizeof(buf) == 0); + + oled_show_progress(screen_verify, 1); + + // do part up to header. + for(; pos < FW_HEADER_OFFSET; pos += sizeof(buf)) { + 8003be4: f5b4 5f7e cmp.w r4, #16256 ; 0x3f80 + 8003be8: d1e7 bne.n 8003bba + sha256_update(&ctx, buf, sizeof(buf)); + } + + // include file header (but not the signature) + ASSERT(pos == FW_HEADER_OFFSET); + sha256_update(&ctx, (const uint8_t *)hdr, FW_HEADER_SIZE - 64); + 8003bea: 2240 movs r2, #64 ; 0x40 + 8003bec: 4639 mov r1, r7 + 8003bee: 4668 mov r0, sp + 8003bf0: f001 fbf6 bl 80053e0 + + // then the rest after the 'header' ... the useful firmware + pos += FW_HEADER_SIZE; + 8003bf4: f44f 4480 mov.w r4, #16384 ; 0x4000 + } + sha256_update(&ctx, buf, sizeof(buf)); + + if((count % 16) == 0) { + int percent = (pos * 100) / total_len; + oled_show_progress(screen_verify, percent); + 8003bf8: f04f 0964 mov.w r9, #100 ; 0x64 + sha256_update(&ctx, (const uint8_t *)hdr, FW_HEADER_SIZE - 64); + + // then the rest after the 'header' ... the useful firmware + pos += FW_HEADER_SIZE; + + for(int count=0; pos < total_len; pos += sizeof(buf), count++) { + 8003bfc: 4544 cmp r4, r8 + 8003bfe: d217 bcs.n 8003c30 + if(sf_read(pos, sizeof(buf), buf) != HAL_OK) { + 8003c00: aa1c add r2, sp, #112 ; 0x70 + 8003c02: 2180 movs r1, #128 ; 0x80 + 8003c04: 4620 mov r0, r4 + 8003c06: f7ff feb5 bl 8003974 + 8003c0a: 2800 cmp r0, #0 + 8003c0c: d1dc bne.n 8003bc8 + goto fail; + } + sha256_update(&ctx, buf, sizeof(buf)); + 8003c0e: 2280 movs r2, #128 ; 0x80 + 8003c10: a91c add r1, sp, #112 ; 0x70 + 8003c12: 4668 mov r0, sp + 8003c14: f001 fbe4 bl 80053e0 + + if((count % 16) == 0) { + 8003c18: 072b lsls r3, r5, #28 + 8003c1a: d106 bne.n 8003c2a + int percent = (pos * 100) / total_len; + oled_show_progress(screen_verify, percent); + 8003c1c: fb09 f104 mul.w r1, r9, r4 + 8003c20: 4810 ldr r0, [pc, #64] ; (8003c64 ) + 8003c22: fbb1 f1f8 udiv r1, r1, r8 + 8003c26: f7fd f847 bl 8000cb8 + sha256_update(&ctx, (const uint8_t *)hdr, FW_HEADER_SIZE - 64); + + // then the rest after the 'header' ... the useful firmware + pos += FW_HEADER_SIZE; + + for(int count=0; pos < total_len; pos += sizeof(buf), count++) { + 8003c2a: 3480 adds r4, #128 ; 0x80 + 8003c2c: 3501 adds r5, #1 + 8003c2e: e7e5 b.n 8003bfc + int percent = (pos * 100) / total_len; + oled_show_progress(screen_verify, percent); + } + } + + ASSERT(pos == hdr->firmware_length); + 8003c30: 69bb ldr r3, [r7, #24] + 8003c32: 429c cmp r4, r3 + 8003c34: d002 beq.n 8003c3c + 8003c36: 480c ldr r0, [pc, #48] ; (8003c68 ) + 8003c38: f7fc fbc8 bl 80003cc + + sha256_final(&ctx, fw_digest); + 8003c3c: 4631 mov r1, r6 + 8003c3e: 4668 mov r0, sp + 8003c40: f001 fbec bl 800541c + + // double SHA256 + sha256_init(&ctx); + 8003c44: 4668 mov r0, sp + 8003c46: f001 fba1 bl 800538c + sha256_update(&ctx, fw_digest, 32); + 8003c4a: 2220 movs r2, #32 + 8003c4c: 4631 mov r1, r6 + 8003c4e: 4668 mov r0, sp + 8003c50: f001 fbc6 bl 80053e0 + sha256_final(&ctx, fw_digest); + 8003c54: 4631 mov r1, r6 + 8003c56: 4668 mov r0, sp + 8003c58: f001 fbe0 bl 800541c +} + 8003c5c: b03d add sp, #244 ; 0xf4 + 8003c5e: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 8003c62: bf00 nop + 8003c64: 08006ab6 .word 0x08006ab6 + 8003c68: 08006940 .word 0x08006940 + +08003c6c : +// +// maybe upgrade to a firmware image found in sflash +// + void +sf_firmware_upgrade(void) +{ + 8003c6c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 8003c70: f5ad 7d09 sub.w sp, sp, #548 ; 0x224 + coldcardFirmwareHeader_t hdr = {}; + 8003c74: 2280 movs r2, #128 ; 0x80 + 8003c76: 2100 movs r1, #0 + 8003c78: a808 add r0, sp, #32 + 8003c7a: f002 fe29 bl 80068d0 + + // simple: just read in right spot to see header. + sf_setup(); + 8003c7e: f7ff ff23 bl 8003ac8 + + if(sf_read(FW_HEADER_OFFSET, sizeof(hdr), (void *)&hdr) != HAL_OK) { + 8003c82: aa08 add r2, sp, #32 + 8003c84: 2180 movs r1, #128 ; 0x80 + 8003c86: f44f 507e mov.w r0, #16256 ; 0x3f80 + 8003c8a: f7ff fe73 bl 8003974 + 8003c8e: 4604 mov r4, r0 + 8003c90: 2800 cmp r0, #0 + 8003c92: f040 809e bne.w 8003dd2 + // hardware issues, keep going + return; + } + + if(!verify_header(&hdr)) { + 8003c96: a808 add r0, sp, #32 + 8003c98: f7fd fdc2 bl 8001820 + 8003c9c: 2800 cmp r0, #0 + 8003c9e: f000 8098 beq.w 8003dd2 + // + // Solution: Look for a duplicated header at end of file. Will always write that last, + // and even do a checksum over the data uploaded into the sflash before writing final + // header out. + // + uint32_t off = hdr.firmware_length; + 8003ca2: 9f0e ldr r7, [sp, #56] ; 0x38 + + coldcardFirmwareHeader_t hdr2 = {}; + 8003ca4: 2280 movs r2, #128 ; 0x80 + 8003ca6: 4621 mov r1, r4 + 8003ca8: a828 add r0, sp, #160 ; 0xa0 + 8003caa: f002 fe11 bl 80068d0 + if(sf_read(off, sizeof(hdr2), (void *)&hdr2) != HAL_OK) { + 8003cae: aa28 add r2, sp, #160 ; 0xa0 + 8003cb0: 2180 movs r1, #128 ; 0x80 + 8003cb2: 4638 mov r0, r7 + 8003cb4: f7ff fe5e bl 8003974 + 8003cb8: 2800 cmp r0, #0 + 8003cba: f040 808a bne.w 8003dd2 + // Huh??? Hardware issue? + return; + } + + if(memcmp(&hdr, &hdr2, sizeof(hdr)) != 0) { + 8003cbe: 2280 movs r2, #128 ; 0x80 + 8003cc0: a928 add r1, sp, #160 ; 0xa0 + 8003cc2: a808 add r0, sp, #32 + 8003cc4: f002 fdcf bl 8006866 + 8003cc8: 2800 cmp r0, #0 + 8003cca: f040 8082 bne.w 8003dd2 + // even tho we have enough data (from SPI) to complete upgrade successfully. + // So only clear flash once we've comlpeted successfully, or determined it + // cannot work (bad signature, etc). + + // Check for downgrade attack: show warning and stop. + if(check_is_downgrade(hdr.timestamp)) { + 8003cce: a809 add r0, sp, #36 ; 0x24 + 8003cd0: f7fd fd88 bl 80017e4 + 8003cd4: b168 cbz r0, 8003cf2 + oled_show(screen_downgrade); + 8003cd6: 4841 ldr r0, [pc, #260] ; (8003ddc ) + 8003cd8: f7fc ffae bl 8000c38 + + fail:{ + // prevent second attempts. pointless + uint8_t zeros[128] = { 0 }; + 8003cdc: 2100 movs r1, #0 + 8003cde: 2280 movs r2, #128 ; 0x80 + 8003ce0: a848 add r0, sp, #288 ; 0x120 + 8003ce2: f002 fdf5 bl 80068d0 + sf_write(off, sizeof(zeros), zeros); + 8003ce6: a948 add r1, sp, #288 ; 0x120 + 8003ce8: 4638 mov r0, r7 + 8003cea: f7ff fe77 bl 80039dc + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); + 8003cee: bf30 wfi + 8003cf0: e7fd b.n 8003cee + LOCKUP_FOREVER(); + } + + // Check the firmware signature before changing main flash at all. + uint8_t fw_digest[32]; + sf_calc_checksum(&hdr, fw_digest); + 8003cf2: 4669 mov r1, sp + 8003cf4: a808 add r0, sp, #32 + 8003cf6: f7ff ff51 bl 8003b9c + + bool ok = verify_signature(&hdr, fw_digest); + 8003cfa: 4669 mov r1, sp + 8003cfc: a808 add r0, sp, #32 + 8003cfe: f7fd fdab bl 8001858 + if(!ok) { + 8003d02: b908 cbnz r0, 8003d08 + // Bad signature over SPI contents; might be corruption or bad signature + // We would not run the resulting firmware in main flash, so don't erase + // what we have there now and abort. + oled_show(screen_corrupt); + 8003d04: 4836 ldr r0, [pc, #216] ; (8003de0 ) + 8003d06: e7e7 b.n 8003cd8 + + goto fail; + } + + // Start the upgrade ... takes about a minute. + sf_do_upgrade(hdr.firmware_length); + 8003d08: f8dd 8038 ldr.w r8, [sp, #56] ; 0x38 +// Copy from SPI flash to real flash, at final executable location. +// + static void +sf_do_upgrade(uint32_t size) +{ + ASSERT(size >= FW_MIN_LENGTH); + 8003d0c: f5b8 2f80 cmp.w r8, #262144 ; 0x40000 + 8003d10: d202 bcs.n 8003d18 + 8003d12: 4834 ldr r0, [pc, #208] ; (8003de4 ) + 8003d14: f7fc fb5a bl 80003cc + + flash_setup0(); + 8003d18: f7fd fec2 bl 8001aa0 + flash_unlock(); + 8003d1c: f7fd fee4 bl 8001ae8 + + uint8_t tmp[256] __attribute__((aligned(8))); + + for(uint32_t pos=0; pos + // show some progress + if((pos % 4096) == 0) { + 8003d26: f3c4 030b ubfx r3, r4, #0, #12 + 8003d2a: b933 cbnz r3, 8003d3a + oled_show_progress(screen_upgrading, pos*100/size); + 8003d2c: 2164 movs r1, #100 ; 0x64 + 8003d2e: 4361 muls r1, r4 + 8003d30: 482d ldr r0, [pc, #180] ; (8003de8 ) + 8003d32: fbb1 f1f8 udiv r1, r1, r8 + 8003d36: f7fc ffbf bl 8000cb8 + } + + if(sf_read(pos, sizeof(tmp), tmp) != HAL_OK) { + 8003d3a: aa48 add r2, sp, #288 ; 0x120 + 8003d3c: f44f 7180 mov.w r1, #256 ; 0x100 + 8003d40: 4620 mov r0, r4 + 8003d42: f7ff fe17 bl 8003974 + 8003d46: b110 cbz r0, 8003d4e + INCONSISTENT(); + 8003d48: 4828 ldr r0, [pc, #160] ; (8003dec ) + 8003d4a: f7fc fb3f bl 80003cc + 8003d4e: f104 6300 add.w r3, r4, #134217728 ; 0x8000000 + 8003d52: f503 4500 add.w r5, r3, #32768 ; 0x8000 + 8003d56: f50d 798c add.w r9, sp, #280 ; 0x118 + 8003d5a: f503 4601 add.w r6, r3, #33024 ; 0x8100 + } + + uint32_t addr = FIRMWARE_START + pos; + uint64_t *b = (uint64_t *)tmp; + + for(int i=0; i + int rv; + + if(addr % FLASH_PAGE_SIZE == 0) { + 8003d62: f3c5 030a ubfx r3, r5, #0, #11 + 8003d66: b933 cbnz r3, 8003d76 + rv = flash_page_erase(addr); + 8003d68: 4628 mov r0, r5 + 8003d6a: f002 fde1 bl 8006930 <__flash_page_erase_veneer> + ASSERT(rv == 0); + 8003d6e: b110 cbz r0, 8003d76 + 8003d70: 481c ldr r0, [pc, #112] ; (8003de4 ) + 8003d72: f7fc fb2b bl 80003cc + } + + rv = flash_burn(addr, *(b++)); + 8003d76: e9f9 2302 ldrd r2, r3, [r9, #8]! + 8003d7a: 4628 mov r0, r5 + 8003d7c: f002 fdd0 bl 8006920 <__flash_burn_veneer> + ASSERT(rv == 0); + 8003d80: b110 cbz r0, 8003d88 + 8003d82: 4818 ldr r0, [pc, #96] ; (8003de4 ) + 8003d84: f7fc fb22 bl 80003cc + addr += sizeof(uint64_t); + 8003d88: 3508 adds r5, #8 + 8003d8a: e7e8 b.n 8003d5e + } + + if(dfu_button_pressed() && !flash_is_security_level2()) { + 8003d8c: f7ff f928 bl 8002fe0 + 8003d90: b140 cbz r0, 8003da4 + 8003d92: 4b17 ldr r3, [pc, #92] ; (8003df0 ) + 8003d94: 6a1b ldr r3, [r3, #32] + 8003d96: b2db uxtb r3, r3 + 8003d98: 2bcc cmp r3, #204 ; 0xcc + 8003d9a: d003 beq.n 8003da4 + flash_lock(); + 8003d9c: f7fd fe9c bl 8001ad8 + + dfu_by_request(); + 8003da0: f7fc fbb2 bl 8000508 + flash_setup0(); + flash_unlock(); + + uint8_t tmp[256] __attribute__((aligned(8))); + + for(uint32_t pos=0; pos + dfu_by_request(); + // NOT-REACHED + } + } + + flash_lock(); + 8003daa: f7fd fe95 bl 8001ad8 + } + + // Start the upgrade ... takes about a minute. + sf_do_upgrade(hdr.firmware_length); + + if(hdr.install_flags & FWHIF_HIGH_WATER) { + 8003dae: 9b0f ldr r3, [sp, #60] ; 0x3c + 8003db0: 07db lsls r3, r3, #31 + 8003db2: d502 bpl.n 8003dba + // Maybe set a new high-waterlevel for future versions. + // Ignore failures, since we can't recover anyway. + record_highwater_version(hdr.timestamp); + 8003db4: a809 add r0, sp, #36 ; 0x24 + 8003db6: f7fe f817 bl 8001de8 + } + + // We're done, so clear header + uint8_t zeros[128] = { 0 }; + 8003dba: 2280 movs r2, #128 ; 0x80 + 8003dbc: 2100 movs r1, #0 + 8003dbe: a848 add r0, sp, #288 ; 0x120 + 8003dc0: f002 fd86 bl 80068d0 + sf_write(off, sizeof(zeros), zeros); + 8003dc4: a948 add r1, sp, #288 ; 0x120 + 8003dc6: 4638 mov r0, r7 + 8003dc8: f7ff fe08 bl 80039dc + + // Tell python, ultimately, that it worked. + sf_completed_upgrade = SF_COMPLETED_UPGRADE; + 8003dcc: 4b09 ldr r3, [pc, #36] ; (8003df4 ) + 8003dce: 4a0a ldr r2, [pc, #40] ; (8003df8 ) + 8003dd0: 601a str r2, [r3, #0] +} + 8003dd2: f50d 7d09 add.w sp, sp, #548 ; 0x224 + 8003dd6: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 8003dda: bf00 nop + 8003ddc: 08006ef9 .word 0x08006ef9 + 8003de0: 08006fd1 .word 0x08006fd1 + 8003de4: 08006940 .word 0x08006940 + 8003de8: 08006b84 .word 0x08006b84 + 8003dec: 08007210 .word 0x08007210 + 8003df0: 40022000 .word 0x40022000 + 8003df4: 1000634c .word 0x1000634c + 8003df8: b50d5c24 .word 0xb50d5c24 + +08003dfc : + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +// unwanted junk +HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority) { return 0; } + 8003dfc: 2000 movs r0, #0 + 8003dfe: 4770 bx lr + +08003e00 : + * @retval None + */ +void HAL_RCC_DeInit(void) +{ + /* Set MSION bit */ + SET_BIT(RCC->CR, RCC_CR_MSION); + 8003e00: 4b17 ldr r3, [pc, #92] ; (8003e60 ) + 8003e02: 681a ldr r2, [r3, #0] + 8003e04: f042 0201 orr.w r2, r2, #1 + 8003e08: 601a str r2, [r3, #0] + 8003e0a: 461a mov r2, r3 + + /* Insure MSIRDY bit is set before writing default MSIRANGE value */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) { __NOP(); } + 8003e0c: 6811 ldr r1, [r2, #0] + 8003e0e: 4b14 ldr r3, [pc, #80] ; (8003e60 ) + 8003e10: 0789 lsls r1, r1, #30 + 8003e12: d401 bmi.n 8003e18 + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); + 8003e14: bf00 nop + 8003e16: e7f9 b.n 8003e0c + + /* Set MSIRANGE default value */ + MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6); + 8003e18: 681a ldr r2, [r3, #0] + CLEAR_REG(RCC->CFGR); + + /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */ +#if defined(RCC_PLLSAI2_SUPPORT) + + CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON); + 8003e1a: 4912 ldr r1, [pc, #72] ; (8003e64 ) + + /* Insure MSIRDY bit is set before writing default MSIRANGE value */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) { __NOP(); } + + /* Set MSIRANGE default value */ + MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6); + 8003e1c: f022 02f0 bic.w r2, r2, #240 ; 0xf0 + 8003e20: f042 0260 orr.w r2, r2, #96 ; 0x60 + 8003e24: 601a str r2, [r3, #0] + + /* Reset CFGR register (MSI is selected as system clock source) */ + CLEAR_REG(RCC->CFGR); + 8003e26: 2200 movs r2, #0 + 8003e28: 609a str r2, [r3, #8] + + /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */ +#if defined(RCC_PLLSAI2_SUPPORT) + + CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON); + 8003e2a: 6818 ldr r0, [r3, #0] + 8003e2c: 4001 ands r1, r0 + 8003e2e: 6019 str r1, [r3, #0] + CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON); + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Reset PLLCFGR register */ + CLEAR_REG(RCC->PLLCFGR); + 8003e30: 60da str r2, [r3, #12] + SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN_4 ); + 8003e32: 68d9 ldr r1, [r3, #12] + 8003e34: f441 5180 orr.w r1, r1, #4096 ; 0x1000 + 8003e38: 60d9 str r1, [r3, #12] + + /* Reset PLLSAI1CFGR register */ + CLEAR_REG(RCC->PLLSAI1CFGR); + 8003e3a: 611a str r2, [r3, #16] + SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N_4 ); + 8003e3c: 6919 ldr r1, [r3, #16] + 8003e3e: f441 5180 orr.w r1, r1, #4096 ; 0x1000 + 8003e42: 6119 str r1, [r3, #16] + +#if defined(RCC_PLLSAI2_SUPPORT) + + /* Reset PLLSAI2CFGR register */ + CLEAR_REG(RCC->PLLSAI2CFGR); + 8003e44: 615a str r2, [r3, #20] + SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N_4 ); + 8003e46: 6959 ldr r1, [r3, #20] + 8003e48: f441 5180 orr.w r1, r1, #4096 ; 0x1000 + 8003e4c: 6159 str r1, [r3, #20] + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Reset HSEBYP bit */ + CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP); + 8003e4e: 6819 ldr r1, [r3, #0] + 8003e50: f421 2180 bic.w r1, r1, #262144 ; 0x40000 + 8003e54: 6019 str r1, [r3, #0] + + /* Disable all interrupts */ + CLEAR_REG(RCC->CIER); + 8003e56: 619a str r2, [r3, #24] + + /* Update the SystemCoreClock global variable */ + SystemCoreClock = MSI_VALUE; + 8003e58: 4b03 ldr r3, [pc, #12] ; (8003e68 ) + 8003e5a: 4a04 ldr r2, [pc, #16] ; (8003e6c ) + 8003e5c: 601a str r2, [r3, #0] + 8003e5e: 4770 bx lr + 8003e60: 40021000 .word 0x40021000 + 8003e64: eafef4ff .word 0xeafef4ff + 8003e68: 10006348 .word 0x10006348 + 8003e6c: 003d0900 .word 0x003d0900 + +08003e70 : + * @arg @ref RCC_MCODIV_8 division by 8 applied to MCO clock + * @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock + * @retval None + */ +void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv) +{ + 8003e70: b570 push {r4, r5, r6, lr} + assert_param(IS_RCC_MCO(RCC_MCOx)); + assert_param(IS_RCC_MCODIV(RCC_MCODiv)); + assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource)); + + /* MCO Clock Enable */ + __MCO1_CLK_ENABLE(); + 8003e72: 4c11 ldr r4, [pc, #68] ; (8003eb8 ) + 8003e74: 6ce3 ldr r3, [r4, #76] ; 0x4c + 8003e76: f043 0301 orr.w r3, r3, #1 + 8003e7a: 64e3 str r3, [r4, #76] ; 0x4c + 8003e7c: 6ce3 ldr r3, [r4, #76] ; 0x4c + * @arg @ref RCC_MCODIV_8 division by 8 applied to MCO clock + * @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock + * @retval None + */ +void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv) +{ + 8003e7e: b086 sub sp, #24 + assert_param(IS_RCC_MCO(RCC_MCOx)); + assert_param(IS_RCC_MCODIV(RCC_MCODiv)); + assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource)); + + /* MCO Clock Enable */ + __MCO1_CLK_ENABLE(); + 8003e80: f003 0301 and.w r3, r3, #1 + 8003e84: 9300 str r3, [sp, #0] + 8003e86: 9b00 ldr r3, [sp, #0] + + /* Configue the MCO1 pin in alternate function mode */ + GPIO_InitStruct.Pin = MCO1_PIN; + 8003e88: f44f 7380 mov.w r3, #256 ; 0x100 + 8003e8c: 9301 str r3, [sp, #4] + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + 8003e8e: 2302 movs r3, #2 + 8003e90: 9302 str r3, [sp, #8] + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + 8003e92: 9304 str r3, [sp, #16] + * @arg @ref RCC_MCODIV_8 division by 8 applied to MCO clock + * @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock + * @retval None + */ +void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv) +{ + 8003e94: 460d mov r5, r1 + + /* Configue the MCO1 pin in alternate function mode */ + GPIO_InitStruct.Pin = MCO1_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + 8003e96: 2300 movs r3, #0 + GPIO_InitStruct.Alternate = GPIO_AF0_MCO; + HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct); + 8003e98: a901 add r1, sp, #4 + 8003e9a: f04f 4090 mov.w r0, #1207959552 ; 0x48000000 + * @arg @ref RCC_MCODIV_8 division by 8 applied to MCO clock + * @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock + * @retval None + */ +void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv) +{ + 8003e9e: 4616 mov r6, r2 + + /* Configue the MCO1 pin in alternate function mode */ + GPIO_InitStruct.Pin = MCO1_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + 8003ea0: 9303 str r3, [sp, #12] + GPIO_InitStruct.Alternate = GPIO_AF0_MCO; + 8003ea2: 9305 str r3, [sp, #20] + HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct); + 8003ea4: f7fc ff88 bl 8000db8 + + /* Mask MCOSEL[] and MCOPRE[] bits then set MCO1 clock source and prescaler */ + MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), (RCC_MCOSource | RCC_MCODiv )); + 8003ea8: 68a2 ldr r2, [r4, #8] + 8003eaa: f022 42ee bic.w r2, r2, #1996488704 ; 0x77000000 + 8003eae: 4316 orrs r6, r2 + 8003eb0: 4335 orrs r5, r6 + 8003eb2: 60a5 str r5, [r4, #8] +} + 8003eb4: b006 add sp, #24 + 8003eb6: bd70 pop {r4, r5, r6, pc} + 8003eb8: 40021000 .word 0x40021000 + +08003ebc : +uint32_t HAL_RCC_GetSysClockFreq(void) +{ + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + uint32_t sysclockfreq = 0U; + + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) || + 8003ebc: 4932 ldr r1, [pc, #200] ; (8003f88 ) + 8003ebe: 688b ldr r3, [r1, #8] + 8003ec0: f013 0f0c tst.w r3, #12 + * + * + * @retval SYSCLK frequency + */ +uint32_t HAL_RCC_GetSysClockFreq(void) +{ + 8003ec4: b510 push {r4, lr} + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + uint32_t sysclockfreq = 0U; + + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) || + 8003ec6: d009 beq.n 8003edc + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI))) + 8003ec8: 688b ldr r3, [r1, #8] +uint32_t HAL_RCC_GetSysClockFreq(void) +{ + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + uint32_t sysclockfreq = 0U; + + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) || + 8003eca: f003 030c and.w r3, r3, #12 + 8003ece: 2b0c cmp r3, #12 + 8003ed0: d11a bne.n 8003f08 + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI))) + 8003ed2: 68cb ldr r3, [r1, #12] + 8003ed4: f003 0303 and.w r3, r3, #3 + 8003ed8: 2b01 cmp r3, #1 + 8003eda: d115 bne.n 8003f08 + { + /* MSI or PLL with MSI source used as system clock source */ + + /* Get SYSCLK source */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET) + 8003edc: 680a ldr r2, [r1, #0] + 8003ede: 4b2a ldr r3, [pc, #168] ; (8003f88 ) + 8003ee0: 0712 lsls r2, r2, #28 + { /* MSISRANGE from RCC_CSR applies */ + msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; + 8003ee2: bf54 ite pl + 8003ee4: f8d3 3094 ldrpl.w r3, [r3, #148] ; 0x94 + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = (RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; + 8003ee8: 681b ldrmi r3, [r3, #0] + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + 8003eea: 4a28 ldr r2, [pc, #160] ; (8003f8c ) + /* MSI or PLL with MSI source used as system clock source */ + + /* Get SYSCLK source */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET) + { /* MSISRANGE from RCC_CSR applies */ + msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; + 8003eec: bf54 ite pl + 8003eee: f3c3 2303 ubfxpl r3, r3, #8, #4 + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = (RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; + 8003ef2: f3c3 1303 ubfxmi r3, r3, #4, #4 + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + 8003ef6: f852 4023 ldr.w r4, [r2, r3, lsl #2] + + if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) + 8003efa: 688b ldr r3, [r1, #8] + { + /* MSI used as system clock source */ + sysclockfreq = msirange; + 8003efc: f013 0f0c tst.w r3, #12 + 8003f00: bf0c ite eq + 8003f02: 4620 moveq r0, r4 + 8003f04: 2000 movne r0, #0 + 8003f06: e011 b.n 8003f2c + } + } + else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) + 8003f08: 688b ldr r3, [r1, #8] + 8003f0a: f003 030c and.w r3, r3, #12 + 8003f0e: 2b04 cmp r3, #4 + 8003f10: d007 beq.n 8003f22 + { + /* HSI used as system clock source */ + sysclockfreq = HSI_VALUE; + } + else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) + 8003f12: 4b1d ldr r3, [pc, #116] ; (8003f88 ) + 8003f14: 689b ldr r3, [r3, #8] + 8003f16: f003 030c and.w r3, r3, #12 + 8003f1a: 2b08 cmp r3, #8 + 8003f1c: d104 bne.n 8003f28 + { + /* HSE used as system clock source */ + sysclockfreq = HSE_VALUE; + 8003f1e: 481c ldr r0, [pc, #112] ; (8003f90 ) + 8003f20: e000 b.n 8003f24 + } + } + else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) + { + /* HSI used as system clock source */ + sysclockfreq = HSI_VALUE; + 8003f22: 481c ldr r0, [pc, #112] ; (8003f94 ) + * + * @retval SYSCLK frequency + */ +uint32_t HAL_RCC_GetSysClockFreq(void) +{ + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + 8003f24: 2400 movs r4, #0 + 8003f26: e001 b.n 8003f2c + uint32_t sysclockfreq = 0U; + 8003f28: 2000 movs r0, #0 + * + * @retval SYSCLK frequency + */ +uint32_t HAL_RCC_GetSysClockFreq(void) +{ + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + 8003f2a: 4604 mov r4, r0 + { + /* HSE used as system clock source */ + sysclockfreq = HSE_VALUE; + } + + if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) + 8003f2c: 688a ldr r2, [r1, #8] + 8003f2e: 4b16 ldr r3, [pc, #88] ; (8003f88 ) + 8003f30: f002 020c and.w r2, r2, #12 + 8003f34: 2a0c cmp r2, #12 + 8003f36: d126 bne.n 8003f86 + /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + 8003f38: 68da ldr r2, [r3, #12] + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + 8003f3a: 68d8 ldr r0, [r3, #12] + + switch (pllsource) + 8003f3c: f002 0203 and.w r2, r2, #3 + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + 8003f40: f3c0 1002 ubfx r0, r0, #4, #3 + + switch (pllsource) + 8003f44: 2a02 cmp r2, #2 + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + 8003f46: f100 0001 add.w r0, r0, #1 + + switch (pllsource) + 8003f4a: d006 beq.n 8003f5a + 8003f4c: 2a03 cmp r2, #3 + 8003f4e: d10c bne.n 8003f6a + case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + 8003f50: 68db ldr r3, [r3, #12] + 8003f52: 4a0f ldr r2, [pc, #60] ; (8003f90 ) + 8003f54: f3c3 2306 ubfx r3, r3, #8, #7 + 8003f58: e003 b.n 8003f62 + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + + switch (pllsource) + { + case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + 8003f5a: 68db ldr r3, [r3, #12] + 8003f5c: 4a0d ldr r2, [pc, #52] ; (8003f94 ) + 8003f5e: f3c3 2306 ubfx r3, r3, #8, #7 + break; + + case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + 8003f62: fbb2 f0f0 udiv r0, r2, r0 + 8003f66: 4343 muls r3, r0 + break; + 8003f68: e006 b.n 8003f78 + + case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + default: + pllvco = (msirange / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + 8003f6a: 68da ldr r2, [r3, #12] + 8003f6c: fbb4 f0f0 udiv r0, r4, r0 + 8003f70: f3c2 2206 ubfx r2, r2, #8, #7 + 8003f74: fb00 f302 mul.w r3, r0, r2 + break; + } + pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U; + 8003f78: 68c8 ldr r0, [r1, #12] + sysclockfreq = pllvco/pllr; + 8003f7a: f3c0 6041 ubfx r0, r0, #25, #2 + 8003f7e: 3001 adds r0, #1 + 8003f80: 0040 lsls r0, r0, #1 + 8003f82: fbb3 f0f0 udiv r0, r3, r0 + } + + return sysclockfreq; +} + 8003f86: bd10 pop {r4, pc} + 8003f88: 40021000 .word 0x40021000 + 8003f8c: 08006968 .word 0x08006968 + 8003f90: 007a1200 .word 0x007a1200 + 8003f94: 00f42400 .word 0x00f42400 + +08003f98 : + /* Check the parameters */ + assert_param(RCC_OscInitStruct != NULL); + assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); + + /*----------------------------- MSI Configuration --------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) + 8003f98: 6803 ldr r3, [r0, #0] + * supported by this macro. User should request a transition to HSE Off + * first and then HSE On or HSE Bypass. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) +{ + 8003f9a: e92d 41f3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, lr} + /* Check the parameters */ + assert_param(RCC_OscInitStruct != NULL); + assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); + + /*----------------------------- MSI Configuration --------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) + 8003f9e: 06dd lsls r5, r3, #27 + * supported by this macro. User should request a transition to HSE Off + * first and then HSE On or HSE Bypass. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) +{ + 8003fa0: 4604 mov r4, r0 + /* Check the parameters */ + assert_param(RCC_OscInitStruct != NULL); + assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); + + /*----------------------------- MSI Configuration --------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) + 8003fa2: d564 bpl.n 800406e + assert_param(IS_RCC_MSI(RCC_OscInitStruct->MSIState)); + assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue)); + assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange)); + + /* When the MSI is used as system clock it will not be disabled */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) ) + 8003fa4: 4da2 ldr r5, [pc, #648] ; (8004230 ) + 8003fa6: 68ab ldr r3, [r5, #8] + 8003fa8: f013 0f0c tst.w r3, #12 + 8003fac: d129 bne.n 8004002 + { + if((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF)) + 8003fae: 682b ldr r3, [r5, #0] + 8003fb0: 0798 lsls r0, r3, #30 + 8003fb2: d503 bpl.n 8003fbc + 8003fb4: 69a3 ldr r3, [r4, #24] + 8003fb6: b90b cbnz r3, 8003fbc + { + return HAL_ERROR; + 8003fb8: 2001 movs r0, #1 + 8003fba: e1f7 b.n 80043ac + else + { + /* To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. */ + if(RCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE()) + 8003fbc: 6829 ldr r1, [r5, #0] + 8003fbe: 4b9c ldr r3, [pc, #624] ; (8004230 ) + 8003fc0: 6a22 ldr r2, [r4, #32] + 8003fc2: 0709 lsls r1, r1, #28 + 8003fc4: bf4c ite mi + 8003fc6: 681b ldrmi r3, [r3, #0] + 8003fc8: f8d3 3094 ldrpl.w r3, [r3, #148] ; 0x94 + { + return HAL_ERROR; + } + + /* Selects the Multiple Speed oscillator (MSI) clock range .*/ + __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange); + 8003fcc: 682b ldr r3, [r5, #0] + 8003fce: f043 0308 orr.w r3, r3, #8 + 8003fd2: 602b str r3, [r5, #0] + 8003fd4: 682b ldr r3, [r5, #0] + 8003fd6: f023 03f0 bic.w r3, r3, #240 ; 0xf0 + 8003fda: 431a orrs r2, r3 + 8003fdc: 602a str r2, [r5, #0] + /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/ + __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); + 8003fde: 686b ldr r3, [r5, #4] + 8003fe0: 69e2 ldr r2, [r4, #28] + 8003fe2: f423 437f bic.w r3, r3, #65280 ; 0xff00 + 8003fe6: ea43 2302 orr.w r3, r3, r2, lsl #8 + 8003fea: 606b str r3, [r5, #4] + return HAL_ERROR; + } + } + + /* Update the SystemCoreClock global variable */ + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]; + 8003fec: f7ff ff66 bl 8003ebc + 8003ff0: 68ab ldr r3, [r5, #8] + 8003ff2: 4a90 ldr r2, [pc, #576] ; (8004234 ) + 8003ff4: f3c3 1303 ubfx r3, r3, #4, #4 + 8003ff8: 5cd3 ldrb r3, [r2, r3] + 8003ffa: 40d8 lsrs r0, r3 + 8003ffc: 4b8e ldr r3, [pc, #568] ; (8004238 ) + 8003ffe: 6018 str r0, [r3, #0] + 8004000: e035 b.n 800406e + } + } + else + { + /* Check the MSI State */ + if(RCC_OscInitStruct->MSIState != RCC_MSI_OFF) + 8004002: 6983 ldr r3, [r0, #24] + 8004004: b31b cbz r3, 800404e + { + /* Enable the Internal High Speed oscillator (MSI). */ + __HAL_RCC_MSI_ENABLE(); + 8004006: 682b ldr r3, [r5, #0] + 8004008: f043 0301 orr.w r3, r3, #1 + 800400c: 602b str r3, [r5, #0] + + /* Get timeout */ + tickstart = HAL_GetTick(); + 800400e: f7fc fd13 bl 8000a38 + 8004012: 4606 mov r6, r0 + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + 8004014: 682a ldr r2, [r5, #0] + 8004016: 4b86 ldr r3, [pc, #536] ; (8004230 ) + 8004018: 0792 lsls r2, r2, #30 + 800401a: d406 bmi.n 800402a + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + 800401c: f7fc fd0c bl 8000a38 + 8004020: 1b80 subs r0, r0, r6 + 8004022: 2802 cmp r0, #2 + 8004024: d9f6 bls.n 8004014 + { + return HAL_TIMEOUT; + 8004026: 2003 movs r0, #3 + 8004028: e1c0 b.n 80043ac + } + } + /* Selects the Multiple Speed oscillator (MSI) clock range .*/ + __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange); + 800402a: 681a ldr r2, [r3, #0] + 800402c: f042 0208 orr.w r2, r2, #8 + 8004030: 601a str r2, [r3, #0] + 8004032: 681a ldr r2, [r3, #0] + 8004034: f022 01f0 bic.w r1, r2, #240 ; 0xf0 + 8004038: 6a22 ldr r2, [r4, #32] + 800403a: 430a orrs r2, r1 + 800403c: 601a str r2, [r3, #0] + /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/ + __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); + 800403e: 685a ldr r2, [r3, #4] + 8004040: 69e1 ldr r1, [r4, #28] + 8004042: f422 427f bic.w r2, r2, #65280 ; 0xff00 + 8004046: ea42 2201 orr.w r2, r2, r1, lsl #8 + 800404a: 605a str r2, [r3, #4] + 800404c: e00f b.n 800406e + + } + else + { + /* Disable the Internal High Speed oscillator (MSI). */ + __HAL_RCC_MSI_DISABLE(); + 800404e: 682b ldr r3, [r5, #0] + 8004050: f023 0301 bic.w r3, r3, #1 + 8004054: 602b str r3, [r5, #0] + + /* Get timeout */ + tickstart = HAL_GetTick(); + 8004056: f7fc fcef bl 8000a38 + 800405a: 4606 mov r6, r0 + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) + 800405c: 682b ldr r3, [r5, #0] + 800405e: 079f lsls r7, r3, #30 + 8004060: d505 bpl.n 800406e + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + 8004062: f7fc fce9 bl 8000a38 + 8004066: 1b80 subs r0, r0, r6 + 8004068: 2802 cmp r0, #2 + 800406a: d9f7 bls.n 800405c + 800406c: e7db b.n 8004026 + } + } + } + } + /*------------------------------- HSE Configuration ------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) + 800406e: 6823 ldr r3, [r4, #0] + 8004070: 07de lsls r6, r3, #31 + 8004072: d403 bmi.n 800407c + } + } + } + } + /*----------------------------- HSI Configuration --------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) + 8004074: 6823 ldr r3, [r4, #0] + 8004076: 079d lsls r5, r3, #30 + 8004078: d448 bmi.n 800410c + 800407a: e091 b.n 80041a0 + { + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState)); + + /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) || + 800407c: 4d6c ldr r5, [pc, #432] ; (8004230 ) + 800407e: 68ab ldr r3, [r5, #8] + 8004080: f003 030c and.w r3, r3, #12 + 8004084: 2b08 cmp r3, #8 + 8004086: d009 beq.n 800409c + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE))) + 8004088: 68ab ldr r3, [r5, #8] + { + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState)); + + /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) || + 800408a: f003 030c and.w r3, r3, #12 + 800408e: 2b0c cmp r3, #12 + 8004090: d10b bne.n 80040aa + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE))) + 8004092: 68eb ldr r3, [r5, #12] + 8004094: f003 0303 and.w r3, r3, #3 + 8004098: 2b03 cmp r3, #3 + 800409a: d106 bne.n 80040aa + { + if((READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF)) + 800409c: 682b ldr r3, [r5, #0] + 800409e: 0398 lsls r0, r3, #14 + 80040a0: d5e8 bpl.n 8004074 + 80040a2: 6863 ldr r3, [r4, #4] + 80040a4: 2b00 cmp r3, #0 + 80040a6: d1e5 bne.n 8004074 + 80040a8: e786 b.n 8003fb8 + } + } + else + { + /* Set the new HSE configuration ---------------------------------------*/ + __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState); + 80040aa: 6863 ldr r3, [r4, #4] + 80040ac: f5b3 3f80 cmp.w r3, #65536 ; 0x10000 + 80040b0: d006 beq.n 80040c0 + 80040b2: f5b3 2fa0 cmp.w r3, #327680 ; 0x50000 + 80040b6: d108 bne.n 80040ca + 80040b8: 682b ldr r3, [r5, #0] + 80040ba: f443 2380 orr.w r3, r3, #262144 ; 0x40000 + 80040be: 602b str r3, [r5, #0] + 80040c0: 682b ldr r3, [r5, #0] + 80040c2: f443 3380 orr.w r3, r3, #65536 ; 0x10000 + 80040c6: 602b str r3, [r5, #0] + 80040c8: e008 b.n 80040dc + 80040ca: 682a ldr r2, [r5, #0] + 80040cc: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + 80040d0: 602a str r2, [r5, #0] + 80040d2: 682a ldr r2, [r5, #0] + 80040d4: f422 2280 bic.w r2, r2, #262144 ; 0x40000 + 80040d8: 602a str r2, [r5, #0] + + /* Check the HSE State */ + if(RCC_OscInitStruct->HSEState != RCC_HSE_OFF) + 80040da: b15b cbz r3, 80040f4 + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80040dc: f7fc fcac bl 8000a38 + 80040e0: 4606 mov r6, r0 + + /* Wait till HSE is ready */ + while(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) + 80040e2: 682b ldr r3, [r5, #0] + 80040e4: 0399 lsls r1, r3, #14 + 80040e6: d4c5 bmi.n 8004074 + { + if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) + 80040e8: f7fc fca6 bl 8000a38 + 80040ec: 1b80 subs r0, r0, r6 + 80040ee: 2864 cmp r0, #100 ; 0x64 + 80040f0: d9f7 bls.n 80040e2 + 80040f2: e798 b.n 8004026 + } + } + else + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80040f4: f7fc fca0 bl 8000a38 + 80040f8: 4606 mov r6, r0 + + /* Wait till HSE is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) + 80040fa: 682b ldr r3, [r5, #0] + 80040fc: 039a lsls r2, r3, #14 + 80040fe: d5b9 bpl.n 8004074 + { + if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) + 8004100: f7fc fc9a bl 8000a38 + 8004104: 1b80 subs r0, r0, r6 + 8004106: 2864 cmp r0, #100 ; 0x64 + 8004108: d9f7 bls.n 80040fa + 800410a: e78c b.n 8004026 + /* Check the parameters */ + assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState)); + assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue)); + + /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) || + 800410c: 4d48 ldr r5, [pc, #288] ; (8004230 ) + 800410e: 68ab ldr r3, [r5, #8] + 8004110: f003 030c and.w r3, r3, #12 + 8004114: 2b04 cmp r3, #4 + 8004116: d009 beq.n 800412c + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI))) + 8004118: 68ab ldr r3, [r5, #8] + /* Check the parameters */ + assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState)); + assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue)); + + /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) || + 800411a: f003 030c and.w r3, r3, #12 + 800411e: 2b0c cmp r3, #12 + 8004120: d113 bne.n 800414a + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI))) + 8004122: 68eb ldr r3, [r5, #12] + 8004124: f003 0303 and.w r3, r3, #3 + 8004128: 2b02 cmp r3, #2 + 800412a: d10e bne.n 800414a + { + /* When HSI is used as system clock it will not be disabled */ + if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF)) + 800412c: 682b ldr r3, [r5, #0] + 800412e: 055b lsls r3, r3, #21 + 8004130: d503 bpl.n 800413a + 8004132: 68e3 ldr r3, [r4, #12] + 8004134: 2b00 cmp r3, #0 + 8004136: f43f af3f beq.w 8003fb8 + } + /* Otherwise, just the calibration is allowed */ + else + { + /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/ + __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue); + 800413a: 686b ldr r3, [r5, #4] + 800413c: 6922 ldr r2, [r4, #16] + 800413e: f023 53f8 bic.w r3, r3, #520093696 ; 0x1f000000 + 8004142: ea43 6302 orr.w r3, r3, r2, lsl #24 + 8004146: 606b str r3, [r5, #4] + /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) || + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI))) + { + /* When HSI is used as system clock it will not be disabled */ + if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF)) + 8004148: e02a b.n 80041a0 + } + } + else + { + /* Check the HSI State */ + if(RCC_OscInitStruct->HSIState != RCC_HSI_OFF) + 800414a: 68e3 ldr r3, [r4, #12] + 800414c: b1c3 cbz r3, 8004180 + { + /* Enable the Internal High Speed oscillator (HSI). */ + __HAL_RCC_HSI_ENABLE(); + 800414e: 682b ldr r3, [r5, #0] + 8004150: f443 7380 orr.w r3, r3, #256 ; 0x100 + 8004154: 602b str r3, [r5, #0] + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8004156: f7fc fc6f bl 8000a38 + 800415a: 4606 mov r6, r0 + + /* Wait till HSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) + 800415c: 682b ldr r3, [r5, #0] + 800415e: 4a34 ldr r2, [pc, #208] ; (8004230 ) + 8004160: 055f lsls r7, r3, #21 + 8004162: d405 bmi.n 8004170 + { + if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) + 8004164: f7fc fc68 bl 8000a38 + 8004168: 1b80 subs r0, r0, r6 + 800416a: 2802 cmp r0, #2 + 800416c: d9f6 bls.n 800415c + 800416e: e75a b.n 8004026 + return HAL_TIMEOUT; + } + } + + /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/ + __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue); + 8004170: 6853 ldr r3, [r2, #4] + 8004172: 6921 ldr r1, [r4, #16] + 8004174: f023 53f8 bic.w r3, r3, #520093696 ; 0x1f000000 + 8004178: ea43 6301 orr.w r3, r3, r1, lsl #24 + 800417c: 6053 str r3, [r2, #4] + 800417e: e00f b.n 80041a0 + } + else + { + /* Disable the Internal High Speed oscillator (HSI). */ + __HAL_RCC_HSI_DISABLE(); + 8004180: 682b ldr r3, [r5, #0] + 8004182: f423 7380 bic.w r3, r3, #256 ; 0x100 + 8004186: 602b str r3, [r5, #0] + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8004188: f7fc fc56 bl 8000a38 + 800418c: 4606 mov r6, r0 + + /* Wait till HSI is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) + 800418e: 682b ldr r3, [r5, #0] + 8004190: 0558 lsls r0, r3, #21 + 8004192: d505 bpl.n 80041a0 + { + if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) + 8004194: f7fc fc50 bl 8000a38 + 8004198: 1b80 subs r0, r0, r6 + 800419a: 2802 cmp r0, #2 + 800419c: d9f7 bls.n 800418e + 800419e: e742 b.n 8004026 + } + } + } + } + /*------------------------------ LSI Configuration -------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) + 80041a0: 6823 ldr r3, [r4, #0] + 80041a2: 0719 lsls r1, r3, #28 + 80041a4: d403 bmi.n 80041ae + } + } + } + } + /*------------------------------ LSE Configuration -------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) + 80041a6: 6823 ldr r3, [r4, #0] + 80041a8: 075a lsls r2, r3, #29 + 80041aa: d429 bmi.n 8004200 + 80041ac: e099 b.n 80042e2 + { + /* Check the parameters */ + assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState)); + + /* Check the LSI State */ + if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF) + 80041ae: 6963 ldr r3, [r4, #20] + 80041b0: 4d1f ldr r5, [pc, #124] ; (8004230 ) + 80041b2: b193 cbz r3, 80041da + { + /* Enable the Internal Low Speed oscillator (LSI). */ + __HAL_RCC_LSI_ENABLE(); + 80041b4: f8d5 3094 ldr.w r3, [r5, #148] ; 0x94 + 80041b8: f043 0301 orr.w r3, r3, #1 + 80041bc: f8c5 3094 str.w r3, [r5, #148] ; 0x94 + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80041c0: f7fc fc3a bl 8000a38 + 80041c4: 4606 mov r6, r0 + + /* Wait till LSI is ready */ + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == RESET) + 80041c6: f8d5 3094 ldr.w r3, [r5, #148] ; 0x94 + 80041ca: 079b lsls r3, r3, #30 + 80041cc: d4eb bmi.n 80041a6 + { + if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) + 80041ce: f7fc fc33 bl 8000a38 + 80041d2: 1b80 subs r0, r0, r6 + 80041d4: 2802 cmp r0, #2 + 80041d6: d9f6 bls.n 80041c6 + 80041d8: e725 b.n 8004026 + } + } + else + { + /* Disable the Internal Low Speed oscillator (LSI). */ + __HAL_RCC_LSI_DISABLE(); + 80041da: f8d5 3094 ldr.w r3, [r5, #148] ; 0x94 + 80041de: f023 0301 bic.w r3, r3, #1 + 80041e2: f8c5 3094 str.w r3, [r5, #148] ; 0x94 + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80041e6: f7fc fc27 bl 8000a38 + 80041ea: 4606 mov r6, r0 + + /* Wait till LSI is disabled */ + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != RESET) + 80041ec: f8d5 3094 ldr.w r3, [r5, #148] ; 0x94 + 80041f0: 079f lsls r7, r3, #30 + 80041f2: d5d8 bpl.n 80041a6 + { + if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) + 80041f4: f7fc fc20 bl 8000a38 + 80041f8: 1b80 subs r0, r0, r6 + 80041fa: 2802 cmp r0, #2 + 80041fc: d9f6 bls.n 80041ec + 80041fe: e712 b.n 8004026 + /* Check the parameters */ + assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState)); + + /* Update LSE configuration in Backup Domain control register */ + /* Requires to enable write access to Backup Domain of necessary */ + if(HAL_IS_BIT_CLR(RCC->APB1ENR1, RCC_APB1ENR1_PWREN)) + 8004200: 4d0b ldr r5, [pc, #44] ; (8004230 ) + 8004202: 6dab ldr r3, [r5, #88] ; 0x58 + 8004204: 00de lsls r6, r3, #3 + 8004206: d40a bmi.n 800421e + { + __HAL_RCC_PWR_CLK_ENABLE(); + 8004208: 6dab ldr r3, [r5, #88] ; 0x58 + 800420a: f043 5380 orr.w r3, r3, #268435456 ; 0x10000000 + 800420e: 65ab str r3, [r5, #88] ; 0x58 + 8004210: 6dab ldr r3, [r5, #88] ; 0x58 + 8004212: f003 5380 and.w r3, r3, #268435456 ; 0x10000000 + 8004216: 9301 str r3, [sp, #4] + 8004218: 9b01 ldr r3, [sp, #4] + pwrclkchanged = SET; + 800421a: 2701 movs r7, #1 + 800421c: e000 b.n 8004220 + } + } + /*------------------------------ LSE Configuration -------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) + { + FlagStatus pwrclkchanged = RESET; + 800421e: 2700 movs r7, #0 + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + + if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + 8004220: 4e06 ldr r6, [pc, #24] ; (800423c ) + 8004222: 6833 ldr r3, [r6, #0] + 8004224: 05d8 lsls r0, r3, #23 + 8004226: d50b bpl.n 8004240 + } + } + } + + /* Set the new LSE configuration -----------------------------------------*/ + __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); + 8004228: 68a3 ldr r3, [r4, #8] + 800422a: 2b01 cmp r3, #1 + 800422c: d119 bne.n 8004262 + 800422e: e020 b.n 8004272 + 8004230: 40021000 .word 0x40021000 + 8004234: 08006950 .word 0x08006950 + 8004238: 10006348 .word 0x10006348 + 800423c: 40007000 .word 0x40007000 + } + + if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + /* Enable write access to Backup domain */ + SET_BIT(PWR->CR1, PWR_CR1_DBP); + 8004240: 6833 ldr r3, [r6, #0] + 8004242: f443 7380 orr.w r3, r3, #256 ; 0x100 + 8004246: 6033 str r3, [r6, #0] + + /* Wait for Backup domain Write protection disable */ + tickstart = HAL_GetTick(); + 8004248: f7fc fbf6 bl 8000a38 + 800424c: 4680 mov r8, r0 + + while(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + 800424e: 6833 ldr r3, [r6, #0] + 8004250: 05d9 lsls r1, r3, #23 + 8004252: d4e9 bmi.n 8004228 + { + if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) + 8004254: f7fc fbf0 bl 8000a38 + 8004258: ebc8 0000 rsb r0, r8, r0 + 800425c: 2802 cmp r0, #2 + 800425e: d9f6 bls.n 800424e + 8004260: e6e1 b.n 8004026 + } + } + } + + /* Set the new LSE configuration -----------------------------------------*/ + __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); + 8004262: 2b05 cmp r3, #5 + 8004264: d10c bne.n 8004280 + 8004266: f8d5 3090 ldr.w r3, [r5, #144] ; 0x90 + 800426a: f043 0304 orr.w r3, r3, #4 + 800426e: f8c5 3090 str.w r3, [r5, #144] ; 0x90 + 8004272: f8d5 3090 ldr.w r3, [r5, #144] ; 0x90 + 8004276: f043 0301 orr.w r3, r3, #1 + 800427a: f8c5 3090 str.w r3, [r5, #144] ; 0x90 + 800427e: e00c b.n 800429a + 8004280: f8d5 2090 ldr.w r2, [r5, #144] ; 0x90 + 8004284: f022 0201 bic.w r2, r2, #1 + 8004288: f8c5 2090 str.w r2, [r5, #144] ; 0x90 + 800428c: f8d5 2090 ldr.w r2, [r5, #144] ; 0x90 + 8004290: f022 0204 bic.w r2, r2, #4 + 8004294: f8c5 2090 str.w r2, [r5, #144] ; 0x90 + + /* Check the LSE State */ + if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF) + 8004298: b173 cbz r3, 80042b8 + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 800429a: f7fc fbcd bl 8000a38 + + /* Wait till LSE is ready */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + 800429e: f241 3888 movw r8, #5000 ; 0x1388 + + /* Check the LSE State */ + if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF) + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80042a2: 4606 mov r6, r0 + + /* Wait till LSE is ready */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + 80042a4: f8d5 3090 ldr.w r3, [r5, #144] ; 0x90 + 80042a8: 079a lsls r2, r3, #30 + 80042aa: d40e bmi.n 80042ca + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + 80042ac: f7fc fbc4 bl 8000a38 + 80042b0: 1b80 subs r0, r0, r6 + 80042b2: 4540 cmp r0, r8 + 80042b4: d9f6 bls.n 80042a4 + 80042b6: e6b6 b.n 8004026 + } + } + else + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80042b8: f7fc fbbe bl 8000a38 + + /* Wait till LSE is disabled */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + 80042bc: f241 3888 movw r8, #5000 ; 0x1388 + } + } + else + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80042c0: 4606 mov r6, r0 + + /* Wait till LSE is disabled */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET) + 80042c2: f8d5 3090 ldr.w r3, [r5, #144] ; 0x90 + 80042c6: 079b lsls r3, r3, #30 + 80042c8: d405 bmi.n 80042d6 + } + } + } + + /* Restore clock configuration if changed */ + if(pwrclkchanged == SET) + 80042ca: b157 cbz r7, 80042e2 + { + __HAL_RCC_PWR_CLK_DISABLE(); + 80042cc: 6dab ldr r3, [r5, #88] ; 0x58 + 80042ce: f023 5380 bic.w r3, r3, #268435456 ; 0x10000000 + 80042d2: 65ab str r3, [r5, #88] ; 0x58 + 80042d4: e005 b.n 80042e2 + tickstart = HAL_GetTick(); + + /* Wait till LSE is disabled */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + 80042d6: f7fc fbaf bl 8000a38 + 80042da: 1b80 subs r0, r0, r6 + 80042dc: 4540 cmp r0, r8 + 80042de: d9f0 bls.n 80042c2 + 80042e0: e6a1 b.n 8004026 +#endif /* RCC_HSI48_SUPPORT */ + /*-------------------------------- PLL Configuration -----------------------*/ + /* Check the parameters */ + assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState)); + + if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE) + 80042e2: 6aa2 ldr r2, [r4, #40] ; 0x28 + 80042e4: b90a cbnz r2, 80042ea + else + { + return HAL_ERROR; + } + } + return HAL_OK; + 80042e6: 2000 movs r0, #0 + 80042e8: e060 b.n 80043ac + assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState)); + + if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE) + { + /* Check if the PLL is used as system clock or not */ + if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + 80042ea: 4d32 ldr r5, [pc, #200] ; (80043b4 ) + 80042ec: 68ab ldr r3, [r5, #8] + 80042ee: f003 030c and.w r3, r3, #12 + 80042f2: 2b0c cmp r3, #12 + 80042f4: f43f ae60 beq.w 8003fb8 + assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP)); + assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ)); + assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR)); + + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + 80042f8: 682b ldr r3, [r5, #0] + if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE) + { + /* Check if the PLL is used as system clock or not */ + if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + { + if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON) + 80042fa: 2a02 cmp r2, #2 + assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP)); + assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ)); + assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR)); + + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + 80042fc: f023 7380 bic.w r3, r3, #16777216 ; 0x1000000 + 8004300: 602b str r3, [r5, #0] + if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE) + { + /* Check if the PLL is used as system clock or not */ + if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + { + if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON) + 8004302: d137 bne.n 8004374 + + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8004304: f7fc fb98 bl 8000a38 + 8004308: 4606 mov r6, r0 + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) + 800430a: 682b ldr r3, [r5, #0] + 800430c: 4829 ldr r0, [pc, #164] ; (80043b4 ) + 800430e: 019f lsls r7, r3, #6 + 8004310: d505 bpl.n 800431e + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + 8004312: f7fc fb91 bl 8000a38 + 8004316: 1b80 subs r0, r0, r6 + 8004318: 2802 cmp r0, #2 + 800431a: d9f6 bls.n 800430a + 800431c: e683 b.n 8004026 + return HAL_TIMEOUT; + } + } + + /* Configure the main PLL clock source, multiplication and division factors. */ + __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource, + 800431e: 6b61 ldr r1, [r4, #52] ; 0x34 + 8004320: 6ae3 ldr r3, [r4, #44] ; 0x2c + 8004322: 6ba2 ldr r2, [r4, #56] ; 0x38 + 8004324: ea43 2301 orr.w r3, r3, r1, lsl #8 + 8004328: 6b21 ldr r1, [r4, #48] ; 0x30 + 800432a: 3901 subs r1, #1 + 800432c: ea43 1301 orr.w r3, r3, r1, lsl #4 + 8004330: 0912 lsrs r2, r2, #4 + 8004332: ea43 4142 orr.w r1, r3, r2, lsl #17 + 8004336: 6be3 ldr r3, [r4, #60] ; 0x3c + 8004338: 085b lsrs r3, r3, #1 + 800433a: 3b01 subs r3, #1 + 800433c: ea41 5243 orr.w r2, r1, r3, lsl #21 + 8004340: 6c23 ldr r3, [r4, #64] ; 0x40 + 8004342: 085b lsrs r3, r3, #1 + 8004344: 3b01 subs r3, #1 + 8004346: ea42 6343 orr.w r3, r2, r3, lsl #25 + 800434a: 60c3 str r3, [r0, #12] + RCC_OscInitStruct->PLL.PLLP, + RCC_OscInitStruct->PLL.PLLQ, + RCC_OscInitStruct->PLL.PLLR); + + /* Enable the main PLL. */ + __HAL_RCC_PLL_ENABLE(); + 800434c: 6803 ldr r3, [r0, #0] + 800434e: f043 7380 orr.w r3, r3, #16777216 ; 0x1000000 + 8004352: 6003 str r3, [r0, #0] + + /* Enable PLL System Clock output. */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK); + 8004354: 68c3 ldr r3, [r0, #12] + 8004356: f043 7380 orr.w r3, r3, #16777216 ; 0x1000000 + 800435a: 60c3 str r3, [r0, #12] + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 800435c: f7fc fb6c bl 8000a38 + 8004360: 4604 mov r4, r0 + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + 8004362: 682b ldr r3, [r5, #0] + 8004364: 0198 lsls r0, r3, #6 + 8004366: d4be bmi.n 80042e6 + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + 8004368: f7fc fb66 bl 8000a38 + 800436c: 1b00 subs r0, r0, r4 + 800436e: 2802 cmp r0, #2 + 8004370: d9f7 bls.n 8004362 + 8004372: e658 b.n 8004026 + { + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + + /* Disable all PLL outputs to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + 8004374: 682b ldr r3, [r5, #0] + 8004376: 0119 lsls r1, r3, #4 + 8004378: d406 bmi.n 8004388 +#if defined(RCC_PLLSAI2_SUPPORT) + && + (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) + 800437a: 682b ldr r3, [r5, #0] + __HAL_RCC_PLL_DISABLE(); + + /* Disable all PLL outputs to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) +#if defined(RCC_PLLSAI2_SUPPORT) + && + 800437c: 009a lsls r2, r3, #2 + (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) +#endif /* RCC_PLLSAI2_SUPPORT */ + ) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + 800437e: bf5e ittt pl + 8004380: 68eb ldrpl r3, [r5, #12] + 8004382: f023 0303 bicpl.w r3, r3, #3 + 8004386: 60eb strpl r3, [r5, #12] + } + +#if defined(RCC_PLLSAI2_SUPPORT) + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK); + 8004388: 68eb ldr r3, [r5, #12] + 800438a: f023 7388 bic.w r3, r3, #17825792 ; 0x1100000 + 800438e: f423 3380 bic.w r3, r3, #65536 ; 0x10000 + 8004392: 60eb str r3, [r5, #12] +#else + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI2CLK); +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8004394: f7fc fb50 bl 8000a38 + 8004398: 4604 mov r4, r0 + + /* Wait till PLL is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) + 800439a: 682b ldr r3, [r5, #0] + 800439c: 019b lsls r3, r3, #6 + 800439e: d5a2 bpl.n 80042e6 + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + 80043a0: f7fc fb4a bl 8000a38 + 80043a4: 1b00 subs r0, r0, r4 + 80043a6: 2802 cmp r0, #2 + 80043a8: d9f7 bls.n 800439a + 80043aa: e63c b.n 8004026 + { + return HAL_ERROR; + } + } + return HAL_OK; +} + 80043ac: b002 add sp, #8 + 80043ae: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 80043b2: bf00 nop + 80043b4: 40021000 .word 0x40021000 + +080043b8 : + /* To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. */ + + /* Increasing the number of wait states because of higher CPU frequency */ + if(FLatency > (FLASH->ACR & FLASH_ACR_LATENCY)) + 80043b8: 4a53 ldr r2, [pc, #332] ; (8004508 ) + 80043ba: 6813 ldr r3, [r2, #0] + 80043bc: f003 0307 and.w r3, r3, #7 + 80043c0: 428b cmp r3, r1 + * HPRE[3:0] bits to ensure that HCLK not exceed the maximum allowed frequency + * (for more details refer to section above "Initialization/de-initialization functions") + * @retval None + */ +HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency) +{ + 80043c2: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 80043c6: 4605 mov r5, r0 + 80043c8: 460e mov r6, r1 + /* To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. */ + + /* Increasing the number of wait states because of higher CPU frequency */ + if(FLatency > (FLASH->ACR & FLASH_ACR_LATENCY)) + 80043ca: d30a bcc.n 80043e2 + return HAL_ERROR; + } + } + + /*-------------------------- HCLK Configuration --------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) + 80043cc: 6829 ldr r1, [r5, #0] + 80043ce: 0788 lsls r0, r1, #30 + 80043d0: d514 bpl.n 80043fc + { + assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider); + 80043d2: 484e ldr r0, [pc, #312] ; (800450c ) + 80043d4: 6883 ldr r3, [r0, #8] + 80043d6: f023 02f0 bic.w r2, r3, #240 ; 0xf0 + 80043da: 68ab ldr r3, [r5, #8] + 80043dc: 4313 orrs r3, r2 + 80043de: 6083 str r3, [r0, #8] + 80043e0: e00c b.n 80043fc + + /* Increasing the number of wait states because of higher CPU frequency */ + if(FLatency > (FLASH->ACR & FLASH_ACR_LATENCY)) + { + /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ + __HAL_FLASH_SET_LATENCY(FLatency); + 80043e2: 6813 ldr r3, [r2, #0] + 80043e4: f023 0307 bic.w r3, r3, #7 + 80043e8: 430b orrs r3, r1 + 80043ea: 6013 str r3, [r2, #0] + + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + if((FLASH->ACR & FLASH_ACR_LATENCY) != FLatency) + 80043ec: 6813 ldr r3, [r2, #0] + 80043ee: f003 0307 and.w r3, r3, #7 + 80043f2: 4299 cmp r1, r3 + 80043f4: d0ea beq.n 80043cc + { + return HAL_ERROR; + 80043f6: 2001 movs r0, #1 + 80043f8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider); + } + + /*------------------------- SYSCLK Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK) + 80043fc: 07ca lsls r2, r1, #31 + 80043fe: d406 bmi.n 800440e + } + } + } + + /* Decreasing the number of wait states because of lower CPU frequency */ + if(FLatency < (FLASH->ACR & FLASH_ACR_LATENCY)) + 8004400: 4a41 ldr r2, [pc, #260] ; (8004508 ) + 8004402: 6813 ldr r3, [r2, #0] + 8004404: f003 0307 and.w r3, r3, #7 + 8004408: 429e cmp r6, r3 + 800440a: d351 bcc.n 80044b0 + 800440c: e05a b.n 80044c4 + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK) + { + assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource)); + + /* HSE is selected as System Clock Source */ + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + 800440e: 686b ldr r3, [r5, #4] + 8004410: 4c3e ldr r4, [pc, #248] ; (800450c ) + 8004412: 2b02 cmp r3, #2 + { + /* Check the HSE ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) + 8004414: 6822 ldr r2, [r4, #0] + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK) + { + assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource)); + + /* HSE is selected as System Clock Source */ + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + 8004416: d102 bne.n 800441e + { + /* Check the HSE ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) + 8004418: f412 3f00 tst.w r2, #131072 ; 0x20000 + 800441c: e00a b.n 8004434 + { + return HAL_ERROR; + } + } + /* PLL is selected as System Clock Source */ + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) + 800441e: 2b03 cmp r3, #3 + 8004420: d102 bne.n 8004428 + { + /* Check the PLL ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + 8004422: f012 7f00 tst.w r2, #33554432 ; 0x2000000 + 8004426: e005 b.n 8004434 + { + return HAL_ERROR; + } + } + /* MSI is selected as System Clock Source */ + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) + 8004428: b913 cbnz r3, 8004430 + { + /* Check the MSI ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + 800442a: f012 0f02 tst.w r2, #2 + 800442e: e001 b.n 8004434 + } + /* HSI is selected as System Clock Source */ + else + { + /* Check the HSI ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) + 8004430: f412 6f80 tst.w r2, #1024 ; 0x400 + 8004434: d0df beq.n 80043f6 + { + return HAL_ERROR; + } + } + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); + 8004436: 68a2 ldr r2, [r4, #8] + 8004438: f022 0203 bic.w r2, r2, #3 + 800443c: 4313 orrs r3, r2 + 800443e: 60a3 str r3, [r4, #8] + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8004440: f7fc fafa bl 8000a38 + + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + 8004444: 686b ldr r3, [r5, #4] + 8004446: 2b02 cmp r3, #2 + } + } + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8004448: 4607 mov r7, r0 + + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSE) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + 800444a: f241 3888 movw r8, #5000 ; 0x1388 + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + 800444e: d10c bne.n 800446a + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSE) + 8004450: 68a3 ldr r3, [r4, #8] + 8004452: f003 030c and.w r3, r3, #12 + 8004456: 2b08 cmp r3, #8 + 8004458: d0d2 beq.n 8004400 + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + 800445a: f7fc faed bl 8000a38 + 800445e: 1bc0 subs r0, r0, r7 + 8004460: 4540 cmp r0, r8 + 8004462: d9f5 bls.n 8004450 + { + return HAL_TIMEOUT; + 8004464: 2003 movs r0, #3 + 8004466: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + } + } + } + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) + 800446a: 2b03 cmp r3, #3 + 800446c: d10a bne.n 8004484 + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + 800446e: 68a3 ldr r3, [r4, #8] + 8004470: f003 030c and.w r3, r3, #12 + 8004474: 2b0c cmp r3, #12 + 8004476: d0c3 beq.n 8004400 + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + 8004478: f7fc fade bl 8000a38 + 800447c: 1bc0 subs r0, r0, r7 + 800447e: 4540 cmp r0, r8 + 8004480: d9f5 bls.n 800446e + 8004482: e7ef b.n 8004464 + { + return HAL_TIMEOUT; + } + } + } + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) + 8004484: b973 cbnz r3, 80044a4 + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_MSI) + 8004486: 68a3 ldr r3, [r4, #8] + 8004488: f013 0f0c tst.w r3, #12 + 800448c: d0b8 beq.n 8004400 + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + 800448e: f7fc fad3 bl 8000a38 + 8004492: 1bc0 subs r0, r0, r7 + 8004494: 4540 cmp r0, r8 + 8004496: d9f6 bls.n 8004486 + 8004498: e7e4 b.n 8004464 + } + else + { + while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + 800449a: f7fc facd bl 8000a38 + 800449e: 1bc0 subs r0, r0, r7 + 80044a0: 4540 cmp r0, r8 + 80044a2: d8df bhi.n 8004464 + } + } + } + else + { + while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI) + 80044a4: 68a3 ldr r3, [r4, #8] + 80044a6: f003 030c and.w r3, r3, #12 + 80044aa: 2b04 cmp r3, #4 + 80044ac: d1f5 bne.n 800449a + 80044ae: e7a7 b.n 8004400 + + /* Decreasing the number of wait states because of lower CPU frequency */ + if(FLatency < (FLASH->ACR & FLASH_ACR_LATENCY)) + { + /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ + __HAL_FLASH_SET_LATENCY(FLatency); + 80044b0: 6813 ldr r3, [r2, #0] + 80044b2: f023 0307 bic.w r3, r3, #7 + 80044b6: 4333 orrs r3, r6 + 80044b8: 6013 str r3, [r2, #0] + + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + if((FLASH->ACR & FLASH_ACR_LATENCY) != FLatency) + 80044ba: 6813 ldr r3, [r2, #0] + 80044bc: f003 0307 and.w r3, r3, #7 + 80044c0: 429e cmp r6, r3 + 80044c2: d198 bne.n 80043f6 + return HAL_ERROR; + } + } + + /*-------------------------- PCLK1 Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1) + 80044c4: 6829 ldr r1, [r5, #0] + 80044c6: 4c11 ldr r4, [pc, #68] ; (800450c ) + 80044c8: f011 0f04 tst.w r1, #4 + 80044cc: d005 beq.n 80044da + { + assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider); + 80044ce: 68a3 ldr r3, [r4, #8] + 80044d0: f423 62e0 bic.w r2, r3, #1792 ; 0x700 + 80044d4: 68eb ldr r3, [r5, #12] + 80044d6: 4313 orrs r3, r2 + 80044d8: 60a3 str r3, [r4, #8] + } + + /*-------------------------- PCLK2 Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2) + 80044da: 070b lsls r3, r1, #28 + 80044dc: d506 bpl.n 80044ec + { + assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U)); + 80044de: 68a3 ldr r3, [r4, #8] + 80044e0: 692a ldr r2, [r5, #16] + 80044e2: f423 5360 bic.w r3, r3, #14336 ; 0x3800 + 80044e6: ea43 03c2 orr.w r3, r3, r2, lsl #3 + 80044ea: 60a3 str r3, [r4, #8] + } + + /* Update the SystemCoreClock global variable */ + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]; + 80044ec: f7ff fce6 bl 8003ebc + 80044f0: 68a3 ldr r3, [r4, #8] + 80044f2: 4a07 ldr r2, [pc, #28] ; (8004510 ) + 80044f4: f3c3 1303 ubfx r3, r3, #4, #4 + 80044f8: 5cd3 ldrb r3, [r2, r3] + 80044fa: 40d8 lsrs r0, r3 + 80044fc: 4b05 ldr r3, [pc, #20] ; (8004514 ) + 80044fe: 6018 str r0, [r3, #0] + + /* Configure the source of time base considering new system clocks settings*/ + HAL_InitTick (TICK_INT_PRIORITY); + + return HAL_OK; + 8004500: 2000 movs r0, #0 +} + 8004502: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 8004506: bf00 nop + 8004508: 40022000 .word 0x40022000 + 800450c: 40021000 .word 0x40021000 + 8004510: 08006950 .word 0x08006950 + 8004514: 10006348 .word 0x10006348 + +08004518 : + * @retval HCLK frequency in Hz + */ +uint32_t HAL_RCC_GetHCLKFreq(void) +{ + return SystemCoreClock; +} + 8004518: 4b01 ldr r3, [pc, #4] ; (8004520 ) + 800451a: 6818 ldr r0, [r3, #0] + 800451c: 4770 bx lr + 800451e: bf00 nop + 8004520: 10006348 .word 0x10006348 + +08004524 : + * @retval PCLK1 frequency in Hz + */ +uint32_t HAL_RCC_GetPCLK1Freq(void) +{ + /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/ + return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos]); + 8004524: 4b04 ldr r3, [pc, #16] ; (8004538 ) + 8004526: 4a05 ldr r2, [pc, #20] ; (800453c ) + 8004528: 689b ldr r3, [r3, #8] + 800452a: f3c3 2302 ubfx r3, r3, #8, #3 + 800452e: 5cd3 ldrb r3, [r2, r3] + 8004530: 4a03 ldr r2, [pc, #12] ; (8004540 ) + 8004532: 6810 ldr r0, [r2, #0] +} + 8004534: 40d8 lsrs r0, r3 + 8004536: 4770 bx lr + 8004538: 40021000 .word 0x40021000 + 800453c: 08006960 .word 0x08006960 + 8004540: 10006348 .word 0x10006348 + +08004544 : + * @retval PCLK2 frequency in Hz + */ +uint32_t HAL_RCC_GetPCLK2Freq(void) +{ + /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/ + return (HAL_RCC_GetHCLKFreq()>> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos]); + 8004544: 4b04 ldr r3, [pc, #16] ; (8004558 ) + 8004546: 4a05 ldr r2, [pc, #20] ; (800455c ) + 8004548: 689b ldr r3, [r3, #8] + 800454a: f3c3 23c2 ubfx r3, r3, #11, #3 + 800454e: 5cd3 ldrb r3, [r2, r3] + 8004550: 4a03 ldr r2, [pc, #12] ; (8004560 ) + 8004552: 6810 ldr r0, [r2, #0] +} + 8004554: 40d8 lsrs r0, r3 + 8004556: 4770 bx lr + 8004558: 40021000 .word 0x40021000 + 800455c: 08006960 .word 0x08006960 + 8004560: 10006348 .word 0x10006348 + +08004564 : + /* Set all possible values for the Oscillator type parameter ---------------*/ +#if defined(RCC_HSI48_SUPPORT) + RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \ + RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSI48; +#else + RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \ + 8004564: 231f movs r3, #31 + 8004566: 6003 str r3, [r0, #0] + RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI; +#endif /* RCC_HSI48_SUPPORT */ + + /* Get the HSE configuration -----------------------------------------------*/ + if((RCC->CR & RCC_CR_HSEBYP) == RCC_CR_HSEBYP) + 8004568: 4b31 ldr r3, [pc, #196] ; (8004630 ) + 800456a: 681a ldr r2, [r3, #0] + 800456c: 0352 lsls r2, r2, #13 + 800456e: d502 bpl.n 8004576 + { + RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS; + 8004570: f44f 22a0 mov.w r2, #327680 ; 0x50000 + 8004574: e005 b.n 8004582 + } + else if((RCC->CR & RCC_CR_HSEON) == RCC_CR_HSEON) + 8004576: 681a ldr r2, [r3, #0] + 8004578: f412 3280 ands.w r2, r2, #65536 ; 0x10000 + { + RCC_OscInitStruct->HSEState = RCC_HSE_ON; + 800457c: bf18 it ne + 800457e: f44f 3280 movne.w r2, #65536 ; 0x10000 + } + else + { + RCC_OscInitStruct->HSEState = RCC_HSE_OFF; + 8004582: 6042 str r2, [r0, #4] + } + + /* Get the MSI configuration -----------------------------------------------*/ + if((RCC->CR & RCC_CR_MSION) == RCC_CR_MSION) + 8004584: 681a ldr r2, [r3, #0] + 8004586: f012 0201 ands.w r2, r2, #1 + { + RCC_OscInitStruct->MSIState = RCC_MSI_ON; + 800458a: bf18 it ne + 800458c: 2201 movne r2, #1 + } + else + { + RCC_OscInitStruct->MSIState = RCC_MSI_OFF; + 800458e: 6182 str r2, [r0, #24] + } + + RCC_OscInitStruct->MSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos); + 8004590: 685a ldr r2, [r3, #4] + 8004592: f3c2 2207 ubfx r2, r2, #8, #8 + 8004596: 61c2 str r2, [r0, #28] + RCC_OscInitStruct->MSIClockRange = (uint32_t)((RCC->CR & RCC_CR_MSIRANGE) ); + 8004598: 681a ldr r2, [r3, #0] + 800459a: f002 02f0 and.w r2, r2, #240 ; 0xf0 + 800459e: 6202 str r2, [r0, #32] + + /* Get the HSI configuration -----------------------------------------------*/ + if((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION) + 80045a0: 681a ldr r2, [r3, #0] + 80045a2: f412 7280 ands.w r2, r2, #256 ; 0x100 + { + RCC_OscInitStruct->HSIState = RCC_HSI_ON; + 80045a6: bf18 it ne + 80045a8: f44f 7280 movne.w r2, #256 ; 0x100 + } + else + { + RCC_OscInitStruct->HSIState = RCC_HSI_OFF; + 80045ac: 60c2 str r2, [r0, #12] + } + + RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos); + 80045ae: 685a ldr r2, [r3, #4] + 80045b0: f3c2 6204 ubfx r2, r2, #24, #5 + 80045b4: 6102 str r2, [r0, #16] + + /* Get the LSE configuration -----------------------------------------------*/ + if((RCC->BDCR & RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP) + 80045b6: f8d3 2090 ldr.w r2, [r3, #144] ; 0x90 + 80045ba: 0751 lsls r1, r2, #29 + 80045bc: d501 bpl.n 80045c2 + { + RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS; + 80045be: 2205 movs r2, #5 + 80045c0: e006 b.n 80045d0 + } + else if((RCC->BDCR & RCC_BDCR_LSEON) == RCC_BDCR_LSEON) + 80045c2: 4a1b ldr r2, [pc, #108] ; (8004630 ) + 80045c4: f8d2 2090 ldr.w r2, [r2, #144] ; 0x90 + 80045c8: f012 0201 ands.w r2, r2, #1 + { + RCC_OscInitStruct->LSEState = RCC_LSE_ON; + 80045cc: bf18 it ne + 80045ce: 2201 movne r2, #1 + } + else + { + RCC_OscInitStruct->LSEState = RCC_LSE_OFF; + 80045d0: 6082 str r2, [r0, #8] + } + + /* Get the LSI configuration -----------------------------------------------*/ + if((RCC->CSR & RCC_CSR_LSION) == RCC_CSR_LSION) + 80045d2: f8d3 2094 ldr.w r2, [r3, #148] ; 0x94 + 80045d6: f012 0201 ands.w r2, r2, #1 + { + RCC_OscInitStruct->LSIState = RCC_LSI_ON; + 80045da: bf18 it ne + 80045dc: 2201 movne r2, #1 + } + else + { + RCC_OscInitStruct->LSIState = RCC_LSI_OFF; + 80045de: 6142 str r2, [r0, #20] + else + { + RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF; + } +#else + RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF; + 80045e0: 2200 movs r2, #0 + 80045e2: 6242 str r2, [r0, #36] ; 0x24 +#endif /* RCC_HSI48_SUPPORT */ + + /* Get the PLL configuration -----------------------------------------------*/ + if((RCC->CR & RCC_CR_PLLON) == RCC_CR_PLLON) + 80045e4: 681a ldr r2, [r3, #0] + 80045e6: 01d2 lsls r2, r2, #7 + { + RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON; + 80045e8: bf4c ite mi + 80045ea: 2202 movmi r2, #2 + } + else + { + RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF; + 80045ec: 2201 movpl r2, #1 + 80045ee: 6282 str r2, [r0, #40] ; 0x28 + } + RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + 80045f0: 68da ldr r2, [r3, #12] + 80045f2: f002 0203 and.w r2, r2, #3 + 80045f6: 62c2 str r2, [r0, #44] ; 0x2c + RCC_OscInitStruct->PLL.PLLM = (uint32_t)(((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U); + 80045f8: 68da ldr r2, [r3, #12] + 80045fa: f3c2 1202 ubfx r2, r2, #4, #3 + 80045fe: 3201 adds r2, #1 + 8004600: 6302 str r2, [r0, #48] ; 0x30 + RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + 8004602: 68da ldr r2, [r3, #12] + 8004604: f3c2 2206 ubfx r2, r2, #8, #7 + 8004608: 6342 str r2, [r0, #52] ; 0x34 + RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + 800460a: 68da ldr r2, [r3, #12] + 800460c: f3c2 5241 ubfx r2, r2, #21, #2 + 8004610: 3201 adds r2, #1 + 8004612: 0052 lsls r2, r2, #1 + 8004614: 63c2 str r2, [r0, #60] ; 0x3c + RCC_OscInitStruct->PLL.PLLR = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) << 1U); + 8004616: 68da ldr r2, [r3, #12] + 8004618: f3c2 6241 ubfx r2, r2, #25, #2 + 800461c: 3201 adds r2, #1 + 800461e: 0052 lsls r2, r2, #1 + 8004620: 6402 str r2, [r0, #64] ; 0x40 +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + RCC_OscInitStruct->PLL.PLLP = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos); +#else + if((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) != RESET) + 8004622: 68db ldr r3, [r3, #12] + 8004624: 039b lsls r3, r3, #14 + { + RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV17; + 8004626: bf4c ite mi + 8004628: 2311 movmi r3, #17 + } + else + { + RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV7; + 800462a: 2307 movpl r3, #7 + 800462c: 6383 str r3, [r0, #56] ; 0x38 + 800462e: 4770 bx lr + 8004630: 40021000 .word 0x40021000 + +08004634 : + /* Check the parameters */ + assert_param(RCC_ClkInitStruct != NULL); + assert_param(pFLatency != NULL); + + /* Set all possible values for the Clock type parameter --------------------*/ + RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + 8004634: 230f movs r3, #15 + 8004636: 6003 str r3, [r0, #0] + + /* Get the SYSCLK configuration --------------------------------------------*/ + RCC_ClkInitStruct->SYSCLKSource = (uint32_t)(RCC->CFGR & RCC_CFGR_SW); + 8004638: 4b0b ldr r3, [pc, #44] ; (8004668 ) + 800463a: 689a ldr r2, [r3, #8] + 800463c: f002 0203 and.w r2, r2, #3 + 8004640: 6042 str r2, [r0, #4] + + /* Get the HCLK configuration ----------------------------------------------*/ + RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_HPRE); + 8004642: 689a ldr r2, [r3, #8] + 8004644: f002 02f0 and.w r2, r2, #240 ; 0xf0 + 8004648: 6082 str r2, [r0, #8] + + /* Get the APB1 configuration ----------------------------------------------*/ + RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_PPRE1); + 800464a: 689a ldr r2, [r3, #8] + 800464c: f402 62e0 and.w r2, r2, #1792 ; 0x700 + 8004650: 60c2 str r2, [r0, #12] + + /* Get the APB2 configuration ----------------------------------------------*/ + RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)((RCC->CFGR & RCC_CFGR_PPRE2) >> 3U); + 8004652: 689b ldr r3, [r3, #8] + 8004654: 08db lsrs r3, r3, #3 + 8004656: f403 63e0 and.w r3, r3, #1792 ; 0x700 + 800465a: 6103 str r3, [r0, #16] + + /* Get the Flash Wait State (Latency) configuration ------------------------*/ + *pFLatency = (uint32_t)(FLASH->ACR & FLASH_ACR_LATENCY); + 800465c: 4b03 ldr r3, [pc, #12] ; (800466c ) + 800465e: 681b ldr r3, [r3, #0] + 8004660: f003 0307 and.w r3, r3, #7 + 8004664: 600b str r3, [r1, #0] + 8004666: 4770 bx lr + 8004668: 40021000 .word 0x40021000 + 800466c: 40022000 .word 0x40022000 + +08004670 : + * @note The Clock Security System can only be cleared by reset. + * @retval None + */ +void HAL_RCC_EnableCSS(void) +{ + SET_BIT(RCC->CR, RCC_CR_CSSON) ; + 8004670: 4a02 ldr r2, [pc, #8] ; (800467c ) + 8004672: 6813 ldr r3, [r2, #0] + 8004674: f443 2300 orr.w r3, r3, #524288 ; 0x80000 + 8004678: 6013 str r3, [r2, #0] + 800467a: 4770 bx lr + 800467c: 40021000 .word 0x40021000 + +08004680 : +/** + * @brief RCC Clock Security System interrupt callback. + * @retval none + */ +__weak void HAL_RCC_CSSCallback(void) +{ + 8004680: 4770 bx lr + ... + +08004684 : + * @brief Handle the RCC Clock Security System interrupt request. + * @note This API should be called under the NMI_Handler(). + * @retval None + */ +void HAL_RCC_NMI_IRQHandler(void) +{ + 8004684: b510 push {r4, lr} + /* Check RCC CSSF interrupt flag */ + if(__HAL_RCC_GET_IT(RCC_IT_CSS)) + 8004686: 4c05 ldr r4, [pc, #20] ; (800469c ) + 8004688: 69e3 ldr r3, [r4, #28] + 800468a: 05db lsls r3, r3, #23 + 800468c: d504 bpl.n 8004698 + { + /* RCC Clock Security System interrupt user callback */ + HAL_RCC_CSSCallback(); + 800468e: f7ff fff7 bl 8004680 + + /* Clear RCC CSS pending bit */ + __HAL_RCC_CLEAR_IT(RCC_IT_CSS); + 8004692: f44f 7380 mov.w r3, #256 ; 0x100 + 8004696: 6223 str r3, [r4, #32] + 8004698: bd10 pop {r4, pc} + 800469a: bf00 nop + 800469c: 40021000 .word 0x40021000 + +080046a0 : + * @note PLLSAI1 is temporary disable to apply new parameters + * + * @retval HAL status + */ +static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider) +{ + 80046a0: b5f8 push {r3, r4, r5, r6, r7, lr} + assert_param(IS_RCC_PLLSAI1M_VALUE(PllSai1->PLLSAI1M)); + assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N)); + assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PllSai1->PLLSAI1ClockOut)); + + /* Check that PLLSAI1 clock source and divider M can be applied */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE) + 80046a2: 4b46 ldr r3, [pc, #280] ; (80047bc ) + 80046a4: 68da ldr r2, [r3, #12] + 80046a6: f012 0f03 tst.w r2, #3 + * @note PLLSAI1 is temporary disable to apply new parameters + * + * @retval HAL status + */ +static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider) +{ + 80046aa: 4604 mov r4, r0 + 80046ac: 460e mov r6, r1 + 80046ae: 461d mov r5, r3 + 80046b0: 6800 ldr r0, [r0, #0] + assert_param(IS_RCC_PLLSAI1M_VALUE(PllSai1->PLLSAI1M)); + assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N)); + assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PllSai1->PLLSAI1ClockOut)); + + /* Check that PLLSAI1 clock source and divider M can be applied */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE) + 80046b2: d00d beq.n 80046d0 + { + /* PLL clock source and divider M already set, check that no request for change */ + if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai1->PLLSAI1Source) + 80046b4: 68da ldr r2, [r3, #12] + 80046b6: f002 0203 and.w r2, r2, #3 + 80046ba: 4282 cmp r2, r0 + 80046bc: d11d bne.n 80046fa + || + 80046be: b1e2 cbz r2, 80046fa + (PllSai1->PLLSAI1Source == RCC_PLLSOURCE_NONE) + || + (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai1->PLLSAI1M) + 80046c0: 68db ldr r3, [r3, #12] + { + /* PLL clock source and divider M already set, check that no request for change */ + if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai1->PLLSAI1Source) + || + (PllSai1->PLLSAI1Source == RCC_PLLSOURCE_NONE) + || + 80046c2: 6862 ldr r2, [r4, #4] + 80046c4: f3c3 1302 ubfx r3, r3, #4, #3 + 80046c8: 3301 adds r3, #1 + 80046ca: 4293 cmp r3, r2 + 80046cc: d115 bne.n 80046fa + 80046ce: e01f b.n 8004710 + } + } + else + { + /* Check PLLSAI1 clock source availability */ + switch(PllSai1->PLLSAI1Source) + 80046d0: 2802 cmp r0, #2 + 80046d2: d007 beq.n 80046e4 + 80046d4: 2803 cmp r0, #3 + 80046d6: d009 beq.n 80046ec + 80046d8: 2801 cmp r0, #1 + 80046da: d10e bne.n 80046fa + { + case RCC_PLLSOURCE_MSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_MSIRDY)) + 80046dc: 681b ldr r3, [r3, #0] + 80046de: 079f lsls r7, r3, #30 + 80046e0: d56a bpl.n 80047b8 + 80046e2: e00c b.n 80046fe + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSIRDY)) + 80046e4: 681b ldr r3, [r3, #0] + 80046e6: f413 6f80 tst.w r3, #1024 ; 0x400 + 80046ea: e005 b.n 80046f8 + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSE: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY) && HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + 80046ec: 681a ldr r2, [r3, #0] + 80046ee: 0391 lsls r1, r2, #14 + 80046f0: d405 bmi.n 80046fe + 80046f2: 681b ldr r3, [r3, #0] + 80046f4: f413 2f80 tst.w r3, #262144 ; 0x40000 + 80046f8: d101 bne.n 80046fe + 80046fa: 2001 movs r0, #1 + 80046fc: bdf8 pop {r3, r4, r5, r6, r7, pc} + } + + if(status == HAL_OK) + { + /* Set PLLSAI1 clock source and divider M */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai1->PLLSAI1Source | (PllSai1->PLLSAI1M - 1U) << RCC_PLLCFGR_PLLM_Pos); + 80046fe: 68ea ldr r2, [r5, #12] + 8004700: 6863 ldr r3, [r4, #4] + 8004702: f022 0273 bic.w r2, r2, #115 ; 0x73 + 8004706: 3b01 subs r3, #1 + 8004708: 4310 orrs r0, r2 + 800470a: ea40 1003 orr.w r0, r0, r3, lsl #4 + 800470e: 60e8 str r0, [r5, #12] + } + + if(status == HAL_OK) + { + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + 8004710: 682b ldr r3, [r5, #0] + 8004712: f023 6380 bic.w r3, r3, #67108864 ; 0x4000000 + 8004716: 602b str r3, [r5, #0] + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8004718: f7fc f98e bl 8000a38 + 800471c: 4607 mov r7, r0 + + /* Wait till PLLSAI1 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + 800471e: 682b ldr r3, [r5, #0] + 8004720: 4826 ldr r0, [pc, #152] ; (80047bc ) + 8004722: 011a lsls r2, r3, #4 + 8004724: d506 bpl.n 8004734 + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + 8004726: f7fc f987 bl 8000a38 + 800472a: 1bc0 subs r0, r0, r7 + 800472c: 2802 cmp r0, #2 + 800472e: d9f6 bls.n 800471e + { + status = HAL_TIMEOUT; + 8004730: 2003 movs r0, #3 + 8004732: bdf8 pop {r3, r4, r5, r6, r7, pc} + 8004734: 68a7 ldr r7, [r4, #8] + } + } + + if(status == HAL_OK) + { + if(Divider == DIVIDER_P_UPDATE) + 8004736: b966 cbnz r6, 8004752 + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos)); +#else + MODIFY_REG(RCC->PLLSAI1CFGR, + 8004738: 6906 ldr r6, [r0, #16] + 800473a: f426 311f bic.w r1, r6, #162816 ; 0x27c00 + 800473e: f421 7140 bic.w r1, r1, #768 ; 0x300 + 8004742: ea41 2307 orr.w r3, r1, r7, lsl #8 + 8004746: 68e1 ldr r1, [r4, #12] + 8004748: 0909 lsrs r1, r1, #4 + 800474a: ea43 4141 orr.w r1, r3, r1, lsl #17 + 800474e: 6101 str r1, [r0, #16] + 8004750: e01c b.n 800478c + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + ((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos)); +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + } + else if(Divider == DIVIDER_Q_UPDATE) + 8004752: 2e01 cmp r6, #1 + 8004754: d10d bne.n 8004772 + { + assert_param(IS_RCC_PLLSAI1Q_VALUE(PllSai1->PLLSAI1Q)); + /* Configure the PLLSAI1 Division factor Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + 8004756: 6922 ldr r2, [r4, #16] + 8004758: 6901 ldr r1, [r0, #16] + 800475a: 0852 lsrs r2, r2, #1 + 800475c: 1e53 subs r3, r2, #1 + 800475e: f421 02c0 bic.w r2, r1, #6291456 ; 0x600000 + 8004762: f422 42fe bic.w r2, r2, #32512 ; 0x7f00 + 8004766: ea42 2207 orr.w r2, r2, r7, lsl #8 + 800476a: ea42 5243 orr.w r2, r2, r3, lsl #21 + 800476e: 6102 str r2, [r0, #16] + 8004770: e00c b.n 800478c + } + else + { + assert_param(IS_RCC_PLLSAI1R_VALUE(PllSai1->PLLSAI1R)); + /* Configure the PLLSAI1 Division factor R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + 8004772: 6902 ldr r2, [r0, #16] + 8004774: 6966 ldr r6, [r4, #20] + 8004776: f022 63c0 bic.w r3, r2, #100663296 ; 0x6000000 + 800477a: 0876 lsrs r6, r6, #1 + 800477c: f423 43fe bic.w r3, r3, #32512 ; 0x7f00 + 8004780: 3e01 subs r6, #1 + 8004782: ea43 2307 orr.w r3, r3, r7, lsl #8 + 8004786: ea43 6346 orr.w r3, r3, r6, lsl #25 + 800478a: 6103 str r3, [r0, #16] + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos)); + } + + /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/ + __HAL_RCC_PLLSAI1_ENABLE(); + 800478c: 682b ldr r3, [r5, #0] + 800478e: f043 6380 orr.w r3, r3, #67108864 ; 0x4000000 + 8004792: 602b str r3, [r5, #0] + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8004794: f7fc f950 bl 8000a38 + 8004798: 4606 mov r6, r0 + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + 800479a: 682b ldr r3, [r5, #0] + 800479c: 4a07 ldr r2, [pc, #28] ; (80047bc ) + 800479e: 011b lsls r3, r3, #4 + 80047a0: d405 bmi.n 80047ae + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + 80047a2: f7fc f949 bl 8000a38 + 80047a6: 1b80 subs r0, r0, r6 + 80047a8: 2802 cmp r0, #2 + 80047aa: d9f6 bls.n 800479a + 80047ac: e7c0 b.n 8004730 + } + + if(status == HAL_OK) + { + /* Configure the PLLSAI1 Clock output(s) */ + __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PllSai1->PLLSAI1ClockOut); + 80047ae: 6911 ldr r1, [r2, #16] + 80047b0: 69a3 ldr r3, [r4, #24] + 80047b2: 430b orrs r3, r1 + 80047b4: 6113 str r3, [r2, #16] + 80047b6: 2000 movs r0, #0 + } + } + + return status; +#endif +} + 80047b8: bdf8 pop {r3, r4, r5, r6, r7, pc} + 80047ba: bf00 nop + 80047bc: 40021000 .word 0x40021000 + +080047c0 : + * the RTC clock source: in this case the access to Backup domain is enabled. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) +{ + 80047c0: e92d 47f3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, lr} + + /* Check the parameters */ + assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); + + /*-------------------------- SAI1 clock source configuration ---------------------*/ + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1)) + 80047c4: 6805 ldr r5, [r0, #0] + 80047c6: f415 6500 ands.w r5, r5, #2048 ; 0x800 + * the RTC clock source: in this case the access to Backup domain is enabled. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) +{ + 80047ca: 4604 mov r4, r0 + + /* Check the parameters */ + assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); + + /*-------------------------- SAI1 clock source configuration ---------------------*/ + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1)) + 80047cc: d018 beq.n 8004800 + { + /* Check the parameters */ + assert_param(IS_RCC_SAI1CLK(PeriphClkInit->Sai1ClockSelection)); + + switch(PeriphClkInit->Sai1ClockSelection) + 80047ce: 6e41 ldr r1, [r0, #100] ; 0x64 + 80047d0: f5b1 0f00 cmp.w r1, #8388608 ; 0x800000 + 80047d4: d008 beq.n 80047e8 + 80047d6: f5b1 0f40 cmp.w r1, #12582912 ; 0xc00000 + 80047da: d005 beq.n 80047e8 + 80047dc: b979 cbnz r1, 80047fe + /* SAI1 clock source config set later after clock selection check */ + break; + + case RCC_SAI1CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI1*/ + /* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE); + 80047de: 3004 adds r0, #4 + 80047e0: f7ff ff5e bl 80046a0 + default: + ret = HAL_ERROR; + break; + } + + if(ret == HAL_OK) + 80047e4: 4605 mov r5, r0 + 80047e6: b958 cbnz r0, 8004800 + { + /* Set the source of SAI1 clock*/ + __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection); + 80047e8: 49b3 ldr r1, [pc, #716] ; (8004ab8 ) + 80047ea: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + 80047ee: f423 0240 bic.w r2, r3, #12582912 ; 0xc00000 + 80047f2: 6e63 ldr r3, [r4, #100] ; 0x64 + 80047f4: 4313 orrs r3, r2 + 80047f6: f8c1 3088 str.w r3, [r1, #136] ; 0x88 + 80047fa: 2500 movs r5, #0 + 80047fc: e000 b.n 8004800 + case RCC_SAI1CLKSOURCE_PIN: /* External clock is used as source of SAI1 clock*/ + /* SAI1 clock source config set later after clock selection check */ + break; + + default: + ret = HAL_ERROR; + 80047fe: 2501 movs r5, #1 + } + +#if defined(SAI2) + + /*-------------------------- SAI2 clock source configuration ---------------------*/ + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2)) + 8004800: 6823 ldr r3, [r4, #0] + 8004802: 04db lsls r3, r3, #19 + 8004804: d523 bpl.n 800484e + { + /* Check the parameters */ + assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection)); + + switch(PeriphClkInit->Sai2ClockSelection) + 8004806: 6ea1 ldr r1, [r4, #104] ; 0x68 + 8004808: f1b1 7f80 cmp.w r1, #16777216 ; 0x1000000 + 800480c: d012 beq.n 8004834 + 800480e: d805 bhi.n 800481c + 8004810: b9e1 cbnz r1, 800484c + /* SAI2 clock source config set later after clock selection check */ + break; + + case RCC_SAI2CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI2*/ + /* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE); + 8004812: 1d20 adds r0, r4, #4 + 8004814: f7ff ff44 bl 80046a0 + 8004818: 4606 mov r6, r0 + /* SAI2 clock source config set later after clock selection check */ + break; + 800481a: e00c b.n 8004836 + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2)) + { + /* Check the parameters */ + assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection)); + + switch(PeriphClkInit->Sai2ClockSelection) + 800481c: f1b1 7f00 cmp.w r1, #33554432 ; 0x2000000 + 8004820: d003 beq.n 800482a + 8004822: f1b1 7f40 cmp.w r1, #50331648 ; 0x3000000 + 8004826: d005 beq.n 8004834 + 8004828: e010 b.n 800484c + { + case RCC_SAI2CLKSOURCE_PLL: /* PLL is used as clock source for SAI2*/ + /* Enable SAI Clock output generated form System PLL . */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); + 800482a: 4aa3 ldr r2, [pc, #652] ; (8004ab8 ) + 800482c: 68d3 ldr r3, [r2, #12] + 800482e: f443 3380 orr.w r3, r3, #65536 ; 0x10000 + 8004832: 60d3 str r3, [r2, #12] + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2)) + { + /* Check the parameters */ + assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection)); + + switch(PeriphClkInit->Sai2ClockSelection) + 8004834: 462e mov r6, r5 + default: + ret = HAL_ERROR; + break; + } + + if(ret == HAL_OK) + 8004836: b966 cbnz r6, 8004852 + { + /* Set the source of SAI2 clock*/ + __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection); + 8004838: 499f ldr r1, [pc, #636] ; (8004ab8 ) + 800483a: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + 800483e: f023 7240 bic.w r2, r3, #50331648 ; 0x3000000 + 8004842: 6ea3 ldr r3, [r4, #104] ; 0x68 + 8004844: 4313 orrs r3, r2 + 8004846: f8c1 3088 str.w r3, [r1, #136] ; 0x88 + 800484a: e003 b.n 8004854 + case RCC_SAI2CLKSOURCE_PIN: /* External clock is used as source of SAI2 clock*/ + /* SAI2 clock source config set later after clock selection check */ + break; + + default: + ret = HAL_ERROR; + 800484c: 2501 movs r5, #1 + 800484e: 462e mov r6, r5 + 8004850: e000 b.n 8004854 + 8004852: 4635 mov r5, r6 + } + } +#endif /* SAI2 */ + + /*-------------------------- RTC clock source configuration ----------------------*/ + if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) + 8004854: 6823 ldr r3, [r4, #0] + 8004856: 039f lsls r7, r3, #14 + 8004858: d562 bpl.n 8004920 + + /* Check for RTC Parameters used to output RTCCLK */ + assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); + + /* Enable Power Clock */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + 800485a: 4f97 ldr r7, [pc, #604] ; (8004ab8 ) + 800485c: 6dbb ldr r3, [r7, #88] ; 0x58 + 800485e: 00d8 lsls r0, r3, #3 + 8004860: d40b bmi.n 800487a + { + __HAL_RCC_PWR_CLK_ENABLE(); + 8004862: 6dbb ldr r3, [r7, #88] ; 0x58 + 8004864: f043 5380 orr.w r3, r3, #268435456 ; 0x10000000 + 8004868: 65bb str r3, [r7, #88] ; 0x58 + 800486a: 6dbb ldr r3, [r7, #88] ; 0x58 + 800486c: f003 5380 and.w r3, r3, #268435456 ; 0x10000000 + 8004870: 9301 str r3, [sp, #4] + 8004872: 9b01 ldr r3, [sp, #4] + pwrclkchanged = SET; + 8004874: f04f 0801 mov.w r8, #1 + 8004878: e001 b.n 800487e +#endif /* SAI2 */ + + /*-------------------------- RTC clock source configuration ----------------------*/ + if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) + { + FlagStatus pwrclkchanged = RESET; + 800487a: f04f 0800 mov.w r8, #0 + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + + /* Enable write access to Backup domain */ + SET_BIT(PWR->CR1, PWR_CR1_DBP); + 800487e: f8df 923c ldr.w r9, [pc, #572] ; 8004abc + 8004882: f8d9 3000 ldr.w r3, [r9] + 8004886: f443 7380 orr.w r3, r3, #256 ; 0x100 + 800488a: f8c9 3000 str.w r3, [r9] + + /* Wait for Backup domain Write protection disable */ + tickstart = HAL_GetTick(); + 800488e: f7fc f8d3 bl 8000a38 + 8004892: 4682 mov sl, r0 + + while((PWR->CR1 & PWR_CR1_DBP) == RESET) + 8004894: f8d9 3000 ldr.w r3, [r9] + 8004898: 05d9 lsls r1, r3, #23 + 800489a: d406 bmi.n 80048aa + { + if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) + 800489c: f7fc f8cc bl 8000a38 + 80048a0: ebca 0000 rsb r0, sl, r0 + 80048a4: 2802 cmp r0, #2 + 80048a6: d9f5 bls.n 8004894 + 80048a8: e02f b.n 800490a + ret = HAL_TIMEOUT; + break; + } + } + + if(ret == HAL_OK) + 80048aa: bb8e cbnz r6, 8004910 + { + /* Reset the Backup domain only if the RTC Clock source selection is modified from default */ + tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL); + 80048ac: f8d7 3090 ldr.w r3, [r7, #144] ; 0x90 + 80048b0: 4a81 ldr r2, [pc, #516] ; (8004ab8 ) + + if((tmpregister != RCC_RTCCLKSOURCE_NO_CLK) && (tmpregister != PeriphClkInit->RTCClockSelection)) + 80048b2: f413 7340 ands.w r3, r3, #768 ; 0x300 + 80048b6: d015 beq.n 80048e4 + 80048b8: f8d4 1084 ldr.w r1, [r4, #132] ; 0x84 + 80048bc: 428b cmp r3, r1 + 80048be: d011 beq.n 80048e4 + { + /* Store the content of BDCR register before the reset of Backup Domain */ + tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL)); + 80048c0: f8d2 3090 ldr.w r3, [r2, #144] ; 0x90 + /* RTC Clock selection can be changed only if the Backup Domain is reset */ + __HAL_RCC_BACKUPRESET_FORCE(); + 80048c4: f8d2 1090 ldr.w r1, [r2, #144] ; 0x90 + 80048c8: f441 3180 orr.w r1, r1, #65536 ; 0x10000 + 80048cc: f8c2 1090 str.w r1, [r2, #144] ; 0x90 + __HAL_RCC_BACKUPRESET_RELEASE(); + 80048d0: f8d2 1090 ldr.w r1, [r2, #144] ; 0x90 + tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL); + + if((tmpregister != RCC_RTCCLKSOURCE_NO_CLK) && (tmpregister != PeriphClkInit->RTCClockSelection)) + { + /* Store the content of BDCR register before the reset of Backup Domain */ + tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL)); + 80048d4: f423 7340 bic.w r3, r3, #768 ; 0x300 + /* RTC Clock selection can be changed only if the Backup Domain is reset */ + __HAL_RCC_BACKUPRESET_FORCE(); + __HAL_RCC_BACKUPRESET_RELEASE(); + 80048d8: f421 3180 bic.w r1, r1, #65536 ; 0x10000 + 80048dc: f8c2 1090 str.w r1, [r2, #144] ; 0x90 + /* Restore the Content of BDCR register */ + RCC->BDCR = tmpregister; + 80048e0: f8c2 3090 str.w r3, [r2, #144] ; 0x90 + } + + /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ + if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSEON)) + 80048e4: 07da lsls r2, r3, #31 + 80048e6: f140 812c bpl.w 8004b42 + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80048ea: f7fc f8a5 bl 8000a38 + + /* Wait till LSE is ready */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + 80048ee: f241 3a88 movw sl, #5000 ; 0x1388 + + /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ + if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSEON)) + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80048f2: 4681 mov r9, r0 + + /* Wait till LSE is ready */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + 80048f4: f8d7 3090 ldr.w r3, [r7, #144] ; 0x90 + 80048f8: 079b lsls r3, r3, #30 + 80048fa: f100 8122 bmi.w 8004b42 + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + 80048fe: f7fc f89b bl 8000a38 + 8004902: ebc9 0000 rsb r0, r9, r0 + 8004906: 4550 cmp r0, sl + 8004908: d9f4 bls.n 80048f4 + + while((PWR->CR1 & PWR_CR1_DBP) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) + { + ret = HAL_TIMEOUT; + 800490a: 2503 movs r5, #3 + 800490c: 462e mov r6, r5 + 800490e: e000 b.n 8004912 + 8004910: 4635 mov r5, r6 + /* set overall return value */ + status = ret; + } + + /* Restore clock configuration if changed */ + if(pwrclkchanged == SET) + 8004912: f1b8 0f00 cmp.w r8, #0 + 8004916: d003 beq.n 8004920 + { + __HAL_RCC_PWR_CLK_DISABLE(); + 8004918: 6dbb ldr r3, [r7, #88] ; 0x58 + 800491a: f023 5380 bic.w r3, r3, #268435456 ; 0x10000000 + 800491e: 65bb str r3, [r7, #88] ; 0x58 + } + } + + /*-------------------------- USART1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) + 8004920: 6823 ldr r3, [r4, #0] + 8004922: 07d8 lsls r0, r3, #31 + 8004924: d508 bpl.n 8004938 + { + /* Check the parameters */ + assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection)); + + /* Configure the USART1 clock source */ + __HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection); + 8004926: 4864 ldr r0, [pc, #400] ; (8004ab8 ) + 8004928: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 800492c: f022 0103 bic.w r1, r2, #3 + 8004930: 6ba2 ldr r2, [r4, #56] ; 0x38 + 8004932: 430a orrs r2, r1 + 8004934: f8c0 2088 str.w r2, [r0, #136] ; 0x88 + } + + /*-------------------------- USART2 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) + 8004938: 0799 lsls r1, r3, #30 + 800493a: d508 bpl.n 800494e + { + /* Check the parameters */ + assert_param(IS_RCC_USART2CLKSOURCE(PeriphClkInit->Usart2ClockSelection)); + + /* Configure the USART2 clock source */ + __HAL_RCC_USART2_CONFIG(PeriphClkInit->Usart2ClockSelection); + 800493c: 485e ldr r0, [pc, #376] ; (8004ab8 ) + 800493e: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 8004942: f022 010c bic.w r1, r2, #12 + 8004946: 6be2 ldr r2, [r4, #60] ; 0x3c + 8004948: 430a orrs r2, r1 + 800494a: f8c0 2088 str.w r2, [r0, #136] ; 0x88 + } + +#if defined(USART3) + + /*-------------------------- USART3 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) + 800494e: 075a lsls r2, r3, #29 + 8004950: d508 bpl.n 8004964 + { + /* Check the parameters */ + assert_param(IS_RCC_USART3CLKSOURCE(PeriphClkInit->Usart3ClockSelection)); + + /* Configure the USART3 clock source */ + __HAL_RCC_USART3_CONFIG(PeriphClkInit->Usart3ClockSelection); + 8004952: 4859 ldr r0, [pc, #356] ; (8004ab8 ) + 8004954: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 8004958: f022 0130 bic.w r1, r2, #48 ; 0x30 + 800495c: 6c22 ldr r2, [r4, #64] ; 0x40 + 800495e: 430a orrs r2, r1 + 8004960: f8c0 2088 str.w r2, [r0, #136] ; 0x88 +#endif /* USART3 */ + +#if defined(UART4) + + /*-------------------------- UART4 clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) + 8004964: 071f lsls r7, r3, #28 + 8004966: d508 bpl.n 800497a + { + /* Check the parameters */ + assert_param(IS_RCC_UART4CLKSOURCE(PeriphClkInit->Uart4ClockSelection)); + + /* Configure the UART4 clock source */ + __HAL_RCC_UART4_CONFIG(PeriphClkInit->Uart4ClockSelection); + 8004968: 4853 ldr r0, [pc, #332] ; (8004ab8 ) + 800496a: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 800496e: f022 01c0 bic.w r1, r2, #192 ; 0xc0 + 8004972: 6c62 ldr r2, [r4, #68] ; 0x44 + 8004974: 430a orrs r2, r1 + 8004976: f8c0 2088 str.w r2, [r0, #136] ; 0x88 +#endif /* UART4 */ + +#if defined(UART5) + + /*-------------------------- UART5 clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) + 800497a: 06d8 lsls r0, r3, #27 + 800497c: d508 bpl.n 8004990 + { + /* Check the parameters */ + assert_param(IS_RCC_UART5CLKSOURCE(PeriphClkInit->Uart5ClockSelection)); + + /* Configure the UART5 clock source */ + __HAL_RCC_UART5_CONFIG(PeriphClkInit->Uart5ClockSelection); + 800497e: 484e ldr r0, [pc, #312] ; (8004ab8 ) + 8004980: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 8004984: f422 7140 bic.w r1, r2, #768 ; 0x300 + 8004988: 6ca2 ldr r2, [r4, #72] ; 0x48 + 800498a: 430a orrs r2, r1 + 800498c: f8c0 2088 str.w r2, [r0, #136] ; 0x88 + } + +#endif /* UART5 */ + + /*-------------------------- LPUART1 clock source configuration ------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) + 8004990: 0699 lsls r1, r3, #26 + 8004992: d508 bpl.n 80049a6 + { + /* Check the parameters */ + assert_param(IS_RCC_LPUART1CLKSOURCE(PeriphClkInit->Lpuart1ClockSelection)); + + /* Configure the LPUAR1 clock source */ + __HAL_RCC_LPUART1_CONFIG(PeriphClkInit->Lpuart1ClockSelection); + 8004994: 4848 ldr r0, [pc, #288] ; (8004ab8 ) + 8004996: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 800499a: f422 6140 bic.w r1, r2, #3072 ; 0xc00 + 800499e: 6ce2 ldr r2, [r4, #76] ; 0x4c + 80049a0: 430a orrs r2, r1 + 80049a2: f8c0 2088 str.w r2, [r0, #136] ; 0x88 + } + + /*-------------------------- LPTIM1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == (RCC_PERIPHCLK_LPTIM1)) + 80049a6: 059a lsls r2, r3, #22 + 80049a8: d508 bpl.n 80049bc + { + assert_param(IS_RCC_LPTIM1CLK(PeriphClkInit->Lptim1ClockSelection)); + __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection); + 80049aa: 4843 ldr r0, [pc, #268] ; (8004ab8 ) + 80049ac: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 80049b0: f422 2140 bic.w r1, r2, #786432 ; 0xc0000 + 80049b4: 6de2 ldr r2, [r4, #92] ; 0x5c + 80049b6: 430a orrs r2, r1 + 80049b8: f8c0 2088 str.w r2, [r0, #136] ; 0x88 + } + + /*-------------------------- LPTIM2 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM2) == (RCC_PERIPHCLK_LPTIM2)) + 80049bc: 055f lsls r7, r3, #21 + 80049be: d508 bpl.n 80049d2 + { + assert_param(IS_RCC_LPTIM2CLK(PeriphClkInit->Lptim2ClockSelection)); + __HAL_RCC_LPTIM2_CONFIG(PeriphClkInit->Lptim2ClockSelection); + 80049c0: 483d ldr r0, [pc, #244] ; (8004ab8 ) + 80049c2: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 80049c6: f422 1140 bic.w r1, r2, #3145728 ; 0x300000 + 80049ca: 6e22 ldr r2, [r4, #96] ; 0x60 + 80049cc: 430a orrs r2, r1 + 80049ce: f8c0 2088 str.w r2, [r0, #136] ; 0x88 + } + + /*-------------------------- I2C1 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) + 80049d2: 0658 lsls r0, r3, #25 + 80049d4: d508 bpl.n 80049e8 + { + /* Check the parameters */ + assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection)); + + /* Configure the I2C1 clock source */ + __HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection); + 80049d6: 4838 ldr r0, [pc, #224] ; (8004ab8 ) + 80049d8: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 80049dc: f422 5140 bic.w r1, r2, #12288 ; 0x3000 + 80049e0: 6d22 ldr r2, [r4, #80] ; 0x50 + 80049e2: 430a orrs r2, r1 + 80049e4: f8c0 2088 str.w r2, [r0, #136] ; 0x88 + } + +#if defined(I2C2) + + /*-------------------------- I2C2 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) + 80049e8: 0619 lsls r1, r3, #24 + 80049ea: d508 bpl.n 80049fe + { + /* Check the parameters */ + assert_param(IS_RCC_I2C2CLKSOURCE(PeriphClkInit->I2c2ClockSelection)); + + /* Configure the I2C2 clock source */ + __HAL_RCC_I2C2_CONFIG(PeriphClkInit->I2c2ClockSelection); + 80049ec: 4832 ldr r0, [pc, #200] ; (8004ab8 ) + 80049ee: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 80049f2: f422 4140 bic.w r1, r2, #49152 ; 0xc000 + 80049f6: 6d62 ldr r2, [r4, #84] ; 0x54 + 80049f8: 430a orrs r2, r1 + 80049fa: f8c0 2088 str.w r2, [r0, #136] ; 0x88 + } + +#endif /* I2C2 */ + + /*-------------------------- I2C3 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) + 80049fe: 05da lsls r2, r3, #23 + 8004a00: d508 bpl.n 8004a14 + { + /* Check the parameters */ + assert_param(IS_RCC_I2C3CLKSOURCE(PeriphClkInit->I2c3ClockSelection)); + + /* Configure the I2C3 clock source */ + __HAL_RCC_I2C3_CONFIG(PeriphClkInit->I2c3ClockSelection); + 8004a02: 482d ldr r0, [pc, #180] ; (8004ab8 ) + 8004a04: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 8004a08: f422 3140 bic.w r1, r2, #196608 ; 0x30000 + 8004a0c: 6da2 ldr r2, [r4, #88] ; 0x58 + 8004a0e: 430a orrs r2, r1 + 8004a10: f8c0 2088 str.w r2, [r0, #136] ; 0x88 +#endif /* I2C4 */ + +#if defined(USB_OTG_FS) || defined(USB) + + /*-------------------------- USB clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == (RCC_PERIPHCLK_USB)) + 8004a14: 049b lsls r3, r3, #18 + 8004a16: d51b bpl.n 8004a50 + { + assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection)); + __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection); + 8004a18: 4a27 ldr r2, [pc, #156] ; (8004ab8 ) + 8004a1a: 6ee1 ldr r1, [r4, #108] ; 0x6c + 8004a1c: f8d2 3088 ldr.w r3, [r2, #136] ; 0x88 + 8004a20: f023 6340 bic.w r3, r3, #201326592 ; 0xc000000 + 8004a24: 430b orrs r3, r1 + + if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL) + 8004a26: f1b1 6f00 cmp.w r1, #134217728 ; 0x8000000 + + /*-------------------------- USB clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == (RCC_PERIPHCLK_USB)) + { + assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection)); + __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection); + 8004a2a: f8c2 3088 str.w r3, [r2, #136] ; 0x88 + + if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL) + 8004a2e: d104 bne.n 8004a3a + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + 8004a30: 68d3 ldr r3, [r2, #12] + 8004a32: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 + 8004a36: 60d3 str r3, [r2, #12] + 8004a38: e00a b.n 8004a50 + } + else + { + if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLLSAI1) + 8004a3a: f1b1 6f80 cmp.w r1, #67108864 ; 0x4000000 + 8004a3e: d107 bne.n 8004a50 + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + 8004a40: 2101 movs r1, #1 + 8004a42: 1d20 adds r0, r4, #4 + 8004a44: f7ff fe2c bl 80046a0 + + if(ret != HAL_OK) + 8004a48: 4606 mov r6, r0 + 8004a4a: 2800 cmp r0, #0 + 8004a4c: bf18 it ne + 8004a4e: 4605 movne r5, r0 +#endif /* USB_OTG_FS || USB */ + +#if defined(SDMMC1) + + /*-------------------------- SDMMC1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == (RCC_PERIPHCLK_SDMMC1)) + 8004a50: 6823 ldr r3, [r4, #0] + 8004a52: 031f lsls r7, r3, #12 + 8004a54: d51b bpl.n 8004a8e + { + assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection)); + __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection); + 8004a56: 4a18 ldr r2, [pc, #96] ; (8004ab8 ) + 8004a58: 6f21 ldr r1, [r4, #112] ; 0x70 + 8004a5a: f8d2 3088 ldr.w r3, [r2, #136] ; 0x88 + 8004a5e: f023 6340 bic.w r3, r3, #201326592 ; 0xc000000 + 8004a62: 430b orrs r3, r1 + + if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL) + 8004a64: f1b1 6f00 cmp.w r1, #134217728 ; 0x8000000 + + /*-------------------------- SDMMC1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == (RCC_PERIPHCLK_SDMMC1)) + { + assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection)); + __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection); + 8004a68: f8c2 3088 str.w r3, [r2, #136] ; 0x88 + + if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL) + 8004a6c: d104 bne.n 8004a78 + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + 8004a6e: 68d3 ldr r3, [r2, #12] + 8004a70: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 + 8004a74: 60d3 str r3, [r2, #12] + 8004a76: e00a b.n 8004a8e + } + else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLSAI1) + 8004a78: f1b1 6f80 cmp.w r1, #67108864 ; 0x4000000 + 8004a7c: d107 bne.n 8004a8e + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + 8004a7e: 2101 movs r1, #1 + 8004a80: 1d20 adds r0, r4, #4 + 8004a82: f7ff fe0d bl 80046a0 + + if(ret != HAL_OK) + 8004a86: 4606 mov r6, r0 + 8004a88: 2800 cmp r0, #0 + 8004a8a: bf18 it ne + 8004a8c: 4605 movne r5, r0 + } + +#endif /* SDMMC1 */ + + /*-------------------------- RNG clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG)) + 8004a8e: 6823 ldr r3, [r4, #0] + 8004a90: 0358 lsls r0, r3, #13 + 8004a92: d520 bpl.n 8004ad6 + { + assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection)); + __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection); + 8004a94: 4a08 ldr r2, [pc, #32] ; (8004ab8 ) + 8004a96: 6f61 ldr r1, [r4, #116] ; 0x74 + 8004a98: f8d2 3088 ldr.w r3, [r2, #136] ; 0x88 + 8004a9c: f023 6340 bic.w r3, r3, #201326592 ; 0xc000000 + 8004aa0: 430b orrs r3, r1 + + if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL) + 8004aa2: f1b1 6f00 cmp.w r1, #134217728 ; 0x8000000 + + /*-------------------------- RNG clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG)) + { + assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection)); + __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection); + 8004aa6: f8c2 3088 str.w r3, [r2, #136] ; 0x88 + + if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL) + 8004aaa: d109 bne.n 8004ac0 + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + 8004aac: 68d3 ldr r3, [r2, #12] + 8004aae: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 + 8004ab2: 60d3 str r3, [r2, #12] + 8004ab4: e00f b.n 8004ad6 + 8004ab6: bf00 nop + 8004ab8: 40021000 .word 0x40021000 + 8004abc: 40007000 .word 0x40007000 + } + else if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLLSAI1) + 8004ac0: f1b1 6f80 cmp.w r1, #67108864 ; 0x4000000 + 8004ac4: d107 bne.n 8004ad6 + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + 8004ac6: 2101 movs r1, #1 + 8004ac8: 1d20 adds r0, r4, #4 + 8004aca: f7ff fde9 bl 80046a0 + + if(ret != HAL_OK) + 8004ace: 4606 mov r6, r0 + 8004ad0: 2800 cmp r0, #0 + 8004ad2: bf18 it ne + 8004ad4: 4605 movne r5, r0 + } + } + } + + /*-------------------------- ADC clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) + 8004ad6: 6823 ldr r3, [r4, #0] + 8004ad8: 0459 lsls r1, r3, #17 + 8004ada: d519 bpl.n 8004b10 + { + /* Check the parameters */ + assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection)); + + /* Configure the ADC interface clock source */ + __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection); + 8004adc: 4920 ldr r1, [pc, #128] ; (8004b60 ) + 8004ade: 6fa2 ldr r2, [r4, #120] ; 0x78 + 8004ae0: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + 8004ae4: f023 5340 bic.w r3, r3, #805306368 ; 0x30000000 + 8004ae8: 4313 orrs r3, r2 + + if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1) + 8004aea: f1b2 5f80 cmp.w r2, #268435456 ; 0x10000000 + { + /* Check the parameters */ + assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection)); + + /* Configure the ADC interface clock source */ + __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection); + 8004aee: f8c1 3088 str.w r3, [r1, #136] ; 0x88 + + if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1) + 8004af2: d107 bne.n 8004b04 + { + /* PLLSAI1 input clock, parameters M, N & R configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_R_UPDATE); + 8004af4: 2102 movs r1, #2 + 8004af6: 1d20 adds r0, r4, #4 + 8004af8: f7ff fdd2 bl 80046a0 + + if(ret != HAL_OK) + 8004afc: 2800 cmp r0, #0 + 8004afe: bf18 it ne + 8004b00: 4605 movne r5, r0 + 8004b02: e005 b.n 8004b10 + } + } + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) + + else if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI2) + 8004b04: f1b2 5f00 cmp.w r2, #536870912 ; 0x20000000 + 8004b08: d102 bne.n 8004b10 + /* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */ +#if defined(RCC_PLLSAI2_SUPPORT) + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE); +#endif + + if(ret != HAL_OK) + 8004b0a: 2e00 cmp r6, #0 + 8004b0c: bf18 it ne + 8004b0e: 4635 movne r5, r6 + } + +#if defined(SWPMI1) + + /*-------------------------- SWPMI1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) + 8004b10: 6821 ldr r1, [r4, #0] + 8004b12: 040a lsls r2, r1, #16 + 8004b14: d508 bpl.n 8004b28 + { + /* Check the parameters */ + assert_param(IS_RCC_SWPMI1CLKSOURCE(PeriphClkInit->Swpmi1ClockSelection)); + + /* Configure the SWPMI1 clock source */ + __HAL_RCC_SWPMI1_CONFIG(PeriphClkInit->Swpmi1ClockSelection); + 8004b16: 4812 ldr r0, [pc, #72] ; (8004b60 ) + 8004b18: f8d0 3088 ldr.w r3, [r0, #136] ; 0x88 + 8004b1c: f023 4280 bic.w r2, r3, #1073741824 ; 0x40000000 + 8004b20: 6fe3 ldr r3, [r4, #124] ; 0x7c + 8004b22: 4313 orrs r3, r2 + 8004b24: f8c0 3088 str.w r3, [r0, #136] ; 0x88 +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + + /*-------------------------- DFSDM1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) + 8004b28: 03cb lsls r3, r1, #15 + 8004b2a: d514 bpl.n 8004b56 + { + /* Check the parameters */ + assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection)); + + /* Configure the DFSDM1 interface clock source */ + __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection); + 8004b2c: 490c ldr r1, [pc, #48] ; (8004b60 ) + 8004b2e: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + 8004b32: f023 4200 bic.w r2, r3, #2147483648 ; 0x80000000 + 8004b36: f8d4 3080 ldr.w r3, [r4, #128] ; 0x80 + 8004b3a: 4313 orrs r3, r2 + 8004b3c: f8c1 3088 str.w r3, [r1, #136] ; 0x88 + } + +#endif /* DFSDM1_Filter0 */ + + return status; + 8004b40: e009 b.n 8004b56 + } + + if(ret == HAL_OK) + { + /* Apply new RTC clock source selection */ + __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); + 8004b42: f8d7 3090 ldr.w r3, [r7, #144] ; 0x90 + 8004b46: f423 7240 bic.w r2, r3, #768 ; 0x300 + 8004b4a: f8d4 3084 ldr.w r3, [r4, #132] ; 0x84 + 8004b4e: 4313 orrs r3, r2 + 8004b50: f8c7 3090 str.w r3, [r7, #144] ; 0x90 + 8004b54: e6dd b.n 8004912 + } + +#endif /* DFSDM1_Filter0 */ + + return status; +} + 8004b56: 4628 mov r0, r5 + 8004b58: b002 add sp, #8 + 8004b5a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 8004b5e: bf00 nop + 8004b60: 40021000 .word 0x40021000 + +08004b64 : + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + 8004b64: 4b44 ldr r3, [pc, #272] ; (8004c78 ) + 8004b66: 6003 str r3, [r0, #0] + +#endif /* STM32L431xx */ + + /* Get the PLLSAI1 Clock configuration -----------------------------------------------*/ + + PeriphClkInit->PLLSAI1.PLLSAI1Source = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> RCC_PLLCFGR_PLLSRC_Pos); + 8004b68: 4b44 ldr r3, [pc, #272] ; (8004c7c ) + 8004b6a: 68da ldr r2, [r3, #12] + 8004b6c: f002 0203 and.w r2, r2, #3 + 8004b70: 6042 str r2, [r0, #4] + PeriphClkInit->PLLSAI1.PLLSAI1M = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U; + 8004b72: 68da ldr r2, [r3, #12] + 8004b74: f3c2 1202 ubfx r2, r2, #4, #3 + 8004b78: 3201 adds r2, #1 + 8004b7a: 6082 str r2, [r0, #8] + PeriphClkInit->PLLSAI1.PLLSAI1N = (uint32_t)((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos); + 8004b7c: 691a ldr r2, [r3, #16] + 8004b7e: f3c2 2206 ubfx r2, r2, #8, #7 + 8004b82: 60c2 str r2, [r0, #12] + PeriphClkInit->PLLSAI1.PLLSAI1P = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1P) >> RCC_PLLSAI1CFGR_PLLSAI1P_Pos) << 4U) + 7U; + 8004b84: 691a ldr r2, [r3, #16] + 8004b86: 0b52 lsrs r2, r2, #13 + 8004b88: f002 0210 and.w r2, r2, #16 + 8004b8c: 3207 adds r2, #7 + 8004b8e: 6102 str r2, [r0, #16] + PeriphClkInit->PLLSAI1.PLLSAI1Q = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos)+1U) * 2U; + 8004b90: 691a ldr r2, [r3, #16] + 8004b92: f3c2 5241 ubfx r2, r2, #21, #2 + 8004b96: 3201 adds r2, #1 + 8004b98: 0052 lsls r2, r2, #1 + 8004b9a: 6142 str r2, [r0, #20] + PeriphClkInit->PLLSAI1.PLLSAI1R = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos)+1U) * 2U; + 8004b9c: 691a ldr r2, [r3, #16] + 8004b9e: f3c2 6241 ubfx r2, r2, #25, #2 + 8004ba2: 3201 adds r2, #1 + 8004ba4: 0052 lsls r2, r2, #1 + 8004ba6: 6182 str r2, [r0, #24] + PeriphClkInit->PLLSAI2.PLLSAI2R = (uint32_t)(((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR_PLLSAI2R)>> RCC_PLLSAI2CFGR_PLLSAI2R_Pos)+1U) * 2U; + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Get the USART1 clock source ---------------------------------------------*/ + PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE(); + 8004ba8: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004bac: f002 0203 and.w r2, r2, #3 + 8004bb0: 6382 str r2, [r0, #56] ; 0x38 + /* Get the USART2 clock source ---------------------------------------------*/ + PeriphClkInit->Usart2ClockSelection = __HAL_RCC_GET_USART2_SOURCE(); + 8004bb2: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004bb6: f002 020c and.w r2, r2, #12 + 8004bba: 63c2 str r2, [r0, #60] ; 0x3c + +#if defined(USART3) + /* Get the USART3 clock source ---------------------------------------------*/ + PeriphClkInit->Usart3ClockSelection = __HAL_RCC_GET_USART3_SOURCE(); + 8004bbc: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004bc0: f002 0230 and.w r2, r2, #48 ; 0x30 + 8004bc4: 6402 str r2, [r0, #64] ; 0x40 +#endif /* USART3 */ + +#if defined(UART4) + /* Get the UART4 clock source ----------------------------------------------*/ + PeriphClkInit->Uart4ClockSelection = __HAL_RCC_GET_UART4_SOURCE(); + 8004bc6: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004bca: f002 02c0 and.w r2, r2, #192 ; 0xc0 + 8004bce: 6442 str r2, [r0, #68] ; 0x44 +#endif /* UART4 */ + +#if defined(UART5) + /* Get the UART5 clock source ----------------------------------------------*/ + PeriphClkInit->Uart5ClockSelection = __HAL_RCC_GET_UART5_SOURCE(); + 8004bd0: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004bd4: f402 7240 and.w r2, r2, #768 ; 0x300 + 8004bd8: 6482 str r2, [r0, #72] ; 0x48 +#endif /* UART5 */ + + /* Get the LPUART1 clock source --------------------------------------------*/ + PeriphClkInit->Lpuart1ClockSelection = __HAL_RCC_GET_LPUART1_SOURCE(); + 8004bda: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004bde: f402 6240 and.w r2, r2, #3072 ; 0xc00 + 8004be2: 64c2 str r2, [r0, #76] ; 0x4c + + /* Get the I2C1 clock source -----------------------------------------------*/ + PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE(); + 8004be4: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004be8: f402 5240 and.w r2, r2, #12288 ; 0x3000 + 8004bec: 6502 str r2, [r0, #80] ; 0x50 + +#if defined(I2C2) + /* Get the I2C2 clock source ----------------------------------------------*/ + PeriphClkInit->I2c2ClockSelection = __HAL_RCC_GET_I2C2_SOURCE(); + 8004bee: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004bf2: f402 4240 and.w r2, r2, #49152 ; 0xc000 + 8004bf6: 6542 str r2, [r0, #84] ; 0x54 +#endif /* I2C2 */ + + /* Get the I2C3 clock source -----------------------------------------------*/ + PeriphClkInit->I2c3ClockSelection = __HAL_RCC_GET_I2C3_SOURCE(); + 8004bf8: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004bfc: f402 3240 and.w r2, r2, #196608 ; 0x30000 + 8004c00: 6582 str r2, [r0, #88] ; 0x58 + /* Get the I2C4 clock source -----------------------------------------------*/ + PeriphClkInit->I2c4ClockSelection = __HAL_RCC_GET_I2C4_SOURCE(); +#endif /* I2C4 */ + + /* Get the LPTIM1 clock source ---------------------------------------------*/ + PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE(); + 8004c02: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c06: f402 2240 and.w r2, r2, #786432 ; 0xc0000 + 8004c0a: 65c2 str r2, [r0, #92] ; 0x5c + + /* Get the LPTIM2 clock source ---------------------------------------------*/ + PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE(); + 8004c0c: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c10: f402 1240 and.w r2, r2, #3145728 ; 0x300000 + 8004c14: 6602 str r2, [r0, #96] ; 0x60 + + /* Get the SAI1 clock source -----------------------------------------------*/ + PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE(); + 8004c16: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c1a: f402 0240 and.w r2, r2, #12582912 ; 0xc00000 + 8004c1e: 6642 str r2, [r0, #100] ; 0x64 + +#if defined(SAI2) + /* Get the SAI2 clock source -----------------------------------------------*/ + PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE(); + 8004c20: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c24: f002 7240 and.w r2, r2, #50331648 ; 0x3000000 + 8004c28: 6682 str r2, [r0, #104] ; 0x68 +#endif /* SAI2 */ + + /* Get the RTC clock source ------------------------------------------------*/ + PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE(); + 8004c2a: f8d3 2090 ldr.w r2, [r3, #144] ; 0x90 + 8004c2e: f402 7240 and.w r2, r2, #768 ; 0x300 + 8004c32: f8c0 2084 str.w r2, [r0, #132] ; 0x84 + +#if defined(USB_OTG_FS) || defined(USB) + /* Get the USB clock source ------------------------------------------------*/ + PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE(); + 8004c36: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c3a: f002 6240 and.w r2, r2, #201326592 ; 0xc000000 + 8004c3e: 66c2 str r2, [r0, #108] ; 0x6c +#endif /* USB_OTG_FS || USB */ + +#if defined(SDMMC1) + /* Get the SDMMC1 clock source ---------------------------------------------*/ + PeriphClkInit->Sdmmc1ClockSelection = __HAL_RCC_GET_SDMMC1_SOURCE(); + 8004c40: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c44: f002 6240 and.w r2, r2, #201326592 ; 0xc000000 + 8004c48: 6702 str r2, [r0, #112] ; 0x70 +#endif /* SDMMC1 */ + + /* Get the RNG clock source ------------------------------------------------*/ + PeriphClkInit->RngClockSelection = __HAL_RCC_GET_RNG_SOURCE(); + 8004c4a: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c4e: f002 6240 and.w r2, r2, #201326592 ; 0xc000000 + 8004c52: 6742 str r2, [r0, #116] ; 0x74 + + /* Get the ADC clock source ------------------------------------------------*/ + PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE(); + 8004c54: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c58: f002 5240 and.w r2, r2, #805306368 ; 0x30000000 + 8004c5c: 6782 str r2, [r0, #120] ; 0x78 + +#if defined(SWPMI1) + /* Get the SWPMI1 clock source ---------------------------------------------*/ + PeriphClkInit->Swpmi1ClockSelection = __HAL_RCC_GET_SWPMI1_SOURCE(); + 8004c5e: f8d3 2088 ldr.w r2, [r3, #136] ; 0x88 + 8004c62: f002 4280 and.w r2, r2, #1073741824 ; 0x40000000 + 8004c66: 67c2 str r2, [r0, #124] ; 0x7c +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + /* Get the DFSDM1 clock source ---------------------------------------------*/ + PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE(); + 8004c68: f8d3 3088 ldr.w r3, [r3, #136] ; 0x88 + 8004c6c: f003 4300 and.w r3, r3, #2147483648 ; 0x80000000 + 8004c70: f8c0 3080 str.w r3, [r0, #128] ; 0x80 + 8004c74: 4770 bx lr + 8004c76: bf00 nop + 8004c78: 000fffff .word 0x000fffff + 8004c7c: 40021000 .word 0x40021000 + +08004c80 : + uint32_t pllvco = 0U, plln = 0U, pllp = 0U; + + /* Check the parameters */ + assert_param(IS_RCC_PERIPHCLOCK(PeriphClk)); + + if(PeriphClk == RCC_PERIPHCLK_RTC) + 8004c80: f5b0 3f00 cmp.w r0, #131072 ; 0x20000 + @endif + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + * @retval Frequency in Hz + */ +uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) +{ + 8004c84: b410 push {r4} + 8004c86: 4bc3 ldr r3, [pc, #780] ; (8004f94 ) + uint32_t pllvco = 0U, plln = 0U, pllp = 0U; + + /* Check the parameters */ + assert_param(IS_RCC_PERIPHCLOCK(PeriphClk)); + + if(PeriphClk == RCC_PERIPHCLK_RTC) + 8004c88: d116 bne.n 8004cb8 + { + /* Get the current RTC source */ + srcclk = __HAL_RCC_GET_RTC_SOURCE(); + 8004c8a: f8d3 2090 ldr.w r2, [r3, #144] ; 0x90 + 8004c8e: f402 7240 and.w r2, r2, #768 ; 0x300 + + /* Check if LSE is ready and if RTC clock selection is LSE */ + if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + 8004c92: f5b2 7f80 cmp.w r2, #256 ; 0x100 + 8004c96: f000 81f8 beq.w 800508a + { + frequency = LSE_VALUE; + } + /* Check if LSI is ready and if RTC clock selection is LSI */ + else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + 8004c9a: f5b2 7f00 cmp.w r2, #512 ; 0x200 + 8004c9e: d102 bne.n 8004ca6 + 8004ca0: f8d3 3094 ldr.w r3, [r3, #148] ; 0x94 + 8004ca4: e1e2 b.n 800506c + { + frequency = LSI_VALUE; + } + /* Check if HSE is ready and if RTC clock selection is HSI_DIV32*/ + else if ((srcclk == RCC_RTCCLKSOURCE_HSE_DIV32) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))) + 8004ca6: f5b2 7f40 cmp.w r2, #768 ; 0x300 + 8004caa: f040 81fc bne.w 80050a6 + 8004cae: 681b ldr r3, [r3, #0] + { + frequency = HSE_VALUE / 32; + 8004cb0: 48b9 ldr r0, [pc, #740] ; (8004f98 ) + 8004cb2: f413 3f00 tst.w r3, #131072 ; 0x20000 + 8004cb6: e1bf b.n 8005038 + else + { + /* Other external peripheral clock source than RTC */ + + /* Compute PLL clock input */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI) /* MSI ? */ + 8004cb8: 68da ldr r2, [r3, #12] + 8004cba: f002 0203 and.w r2, r2, #3 + 8004cbe: 2a01 cmp r2, #1 + 8004cc0: d111 bne.n 8004ce6 + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + 8004cc2: 681a ldr r2, [r3, #0] + 8004cc4: f012 0202 ands.w r2, r2, #2 + 8004cc8: d024 beq.n 8004d14 + { + /*MSI frequency range in HZ*/ + pllvco = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + 8004cca: 681a ldr r2, [r3, #0] + 8004ccc: 49b3 ldr r1, [pc, #716] ; (8004f9c ) + 8004cce: 0712 lsls r2, r2, #28 + 8004cd0: bf4b itete mi + 8004cd2: 681a ldrmi r2, [r3, #0] + 8004cd4: f8d3 2094 ldrpl.w r2, [r3, #148] ; 0x94 + 8004cd8: f3c2 1203 ubfxmi r2, r2, #4, #4 + 8004cdc: f3c2 2203 ubfxpl r2, r2, #8, #4 + 8004ce0: f851 4022 ldr.w r4, [r1, r2, lsl #2] + 8004ce4: e019 b.n 8004d1a + else + { + pllvco = 0U; + } + } + else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI) /* HSI ? */ + 8004ce6: 68da ldr r2, [r3, #12] + 8004ce8: f002 0203 and.w r2, r2, #3 + 8004cec: 2a02 cmp r2, #2 + 8004cee: d104 bne.n 8004cfa + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + 8004cf0: 681a ldr r2, [r3, #0] + { + pllvco = HSI_VALUE; + 8004cf2: f412 6f80 tst.w r2, #1024 ; 0x400 + 8004cf6: 4aaa ldr r2, [pc, #680] ; (8004fa0 ) + 8004cf8: e008 b.n 8004d0c + else + { + pllvco = 0U; + } + } + else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) /* HSE ? */ + 8004cfa: 68da ldr r2, [r3, #12] + 8004cfc: f002 0203 and.w r2, r2, #3 + 8004d00: 2a03 cmp r2, #3 + 8004d02: d109 bne.n 8004d18 + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) + 8004d04: 681a ldr r2, [r3, #0] + { + pllvco = HSE_VALUE; + 8004d06: f412 3f00 tst.w r2, #131072 ; 0x20000 + 8004d0a: 4aa6 ldr r2, [pc, #664] ; (8004fa4 ) + 8004d0c: bf0c ite eq + 8004d0e: 2400 moveq r4, #0 + 8004d10: 4614 movne r4, r2 + 8004d12: e002 b.n 8004d1a + { + pllvco = HSI_VALUE; + } + else + { + pllvco = 0U; + 8004d14: 4614 mov r4, r2 + 8004d16: e000 b.n 8004d1a + 8004d18: 2400 movs r4, #0 + { + pllvco = 0U; + } + + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + 8004d1a: 68da ldr r2, [r3, #12] + 8004d1c: 499d ldr r1, [pc, #628] ; (8004f94 ) + 8004d1e: f3c2 1202 ubfx r2, r2, #4, #3 + + switch(PeriphClk) + 8004d22: f5b0 7f00 cmp.w r0, #512 ; 0x200 + { + pllvco = 0U; + } + + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + 8004d26: f102 0201 add.w r2, r2, #1 + 8004d2a: fbb4 f2f2 udiv r2, r4, r2 + + switch(PeriphClk) + 8004d2e: f000 8173 beq.w 8005018 + 8004d32: d822 bhi.n 8004d7a + 8004d34: 2810 cmp r0, #16 + 8004d36: f000 80f7 beq.w 8004f28 + 8004d3a: d80e bhi.n 8004d5a + 8004d3c: 2802 cmp r0, #2 + 8004d3e: f000 80cb beq.w 8004ed8 + 8004d42: d803 bhi.n 8004d4c + 8004d44: 2801 cmp r0, #1 + 8004d46: f000 80b4 beq.w 8004eb2 + 8004d4a: e1ac b.n 80050a6 + 8004d4c: 2804 cmp r0, #4 + 8004d4e: f000 80d3 beq.w 8004ef8 + 8004d52: 2808 cmp r0, #8 + 8004d54: f000 80dc beq.w 8004f10 + 8004d58: e1a5 b.n 80050a6 + 8004d5a: 2840 cmp r0, #64 ; 0x40 + 8004d5c: f000 8134 beq.w 8004fc8 + 8004d60: d803 bhi.n 8004d6a + 8004d62: 2820 cmp r0, #32 + 8004d64: f000 80ee beq.w 8004f44 + 8004d68: e19d b.n 80050a6 + 8004d6a: 2880 cmp r0, #128 ; 0x80 + 8004d6c: f000 8139 beq.w 8004fe2 + 8004d70: f5b0 7f80 cmp.w r0, #256 ; 0x100 + 8004d74: f000 8142 beq.w 8004ffc + 8004d78: e195 b.n 80050a6 + 8004d7a: f5b0 4f80 cmp.w r0, #16384 ; 0x4000 + 8004d7e: f000 80f0 beq.w 8004f62 + 8004d82: d80e bhi.n 8004da2 + 8004d84: f5b0 6f00 cmp.w r0, #2048 ; 0x800 + 8004d88: d027 beq.n 8004dda + 8004d8a: d804 bhi.n 8004d96 + 8004d8c: f5b0 6f80 cmp.w r0, #1024 ; 0x400 + 8004d90: f000 8161 beq.w 8005056 + 8004d94: e187 b.n 80050a6 + 8004d96: f5b0 5f80 cmp.w r0, #4096 ; 0x1000 + 8004d9a: d013 beq.n 8004dc4 + 8004d9c: f5b0 5f00 cmp.w r0, #8192 ; 0x2000 + 8004da0: e00e b.n 8004dc0 + 8004da2: f5b0 3f80 cmp.w r0, #65536 ; 0x10000 + 8004da6: f000 8109 beq.w 8004fbc + 8004daa: d804 bhi.n 8004db6 + 8004dac: f5b0 4f00 cmp.w r0, #32768 ; 0x8000 + 8004db0: f000 816e beq.w 8005090 + 8004db4: e177 b.n 80050a6 + 8004db6: f5b0 2f80 cmp.w r0, #262144 ; 0x40000 + 8004dba: d039 beq.n 8004e30 + 8004dbc: f5b0 2f00 cmp.w r0, #524288 ; 0x80000 + 8004dc0: d036 beq.n 8004e30 + 8004dc2: e170 b.n 80050a6 + } + /* Else, PLL clock output to check below */ + } + else /* RCC_PERIPHCLK_SAI2 */ + { + srcclk = __HAL_RCC_GET_SAI2_SOURCE(); + 8004dc4: f8d1 0088 ldr.w r0, [r1, #136] ; 0x88 + 8004dc8: f000 7040 and.w r0, r0, #50331648 ; 0x3000000 + + if(srcclk == RCC_SAI2CLKSOURCE_PIN) + 8004dcc: f1b0 7f40 cmp.w r0, #50331648 ; 0x3000000 + 8004dd0: f000 8166 beq.w 80050a0 +#endif /* SAI2 */ + + if(frequency == 0U) + { +#if defined(SAI2) + if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL)) + 8004dd4: f1b0 7f00 cmp.w r0, #33554432 ; 0x2000000 + 8004dd8: e009 b.n 8004dee + case RCC_PERIPHCLK_SAI1: + case RCC_PERIPHCLK_SAI2: + + if(PeriphClk == RCC_PERIPHCLK_SAI1) + { + srcclk = __HAL_RCC_GET_SAI1_SOURCE(); + 8004dda: f8d3 0088 ldr.w r0, [r3, #136] ; 0x88 + 8004dde: f400 0040 and.w r0, r0, #12582912 ; 0xc00000 + + if(srcclk == RCC_SAI1CLKSOURCE_PIN) + 8004de2: f5b0 0f40 cmp.w r0, #12582912 ; 0xc00000 + 8004de6: f000 815b beq.w 80050a0 +#endif /* SAI2 */ + + if(frequency == 0U) + { +#if defined(SAI2) + if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL)) + 8004dea: f5b0 0f00 cmp.w r0, #8388608 ; 0x800000 + 8004dee: d10a bne.n 8004e06 + { + if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != RESET) + 8004df0: 68db ldr r3, [r3, #12] + 8004df2: 4968 ldr r1, [pc, #416] ; (8004f94 ) + 8004df4: f413 3080 ands.w r0, r3, #65536 ; 0x10000 + 8004df8: f000 8156 beq.w 80050a8 + { + /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + 8004dfc: 68c8 ldr r0, [r1, #12] +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + 8004dfe: 68cb ldr r3, [r1, #12] + if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL)) + { + if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != RESET) + { + /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + 8004e00: f3c0 2006 ubfx r0, r0, #8, #7 + 8004e04: e00b b.n 8004e1e + } + } + frequency = (pllvco * plln) / pllp; + } + } + else if(srcclk == 0U) /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */ + 8004e06: 2800 cmp r0, #0 + 8004e08: f040 814d bne.w 80050a6 + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET) + 8004e0c: 691b ldr r3, [r3, #16] + 8004e0e: 4961 ldr r1, [pc, #388] ; (8004f94 ) + 8004e10: 03dc lsls r4, r3, #15 + 8004e12: f140 8149 bpl.w 80050a8 + { + /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + 8004e16: 6908 ldr r0, [r1, #16] +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET) + 8004e18: 690b ldr r3, [r1, #16] + else if(srcclk == 0U) /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */ + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET) + { + /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + 8004e1a: f3c0 2006 ubfx r0, r0, #8, #7 + { + pllp = 17U; + } + else + { + pllp = 7U; + 8004e1e: f413 3f00 tst.w r3, #131072 ; 0x20000 + 8004e22: bf14 ite ne + 8004e24: 2311 movne r3, #17 + 8004e26: 2307 moveq r3, #7 + } + } + frequency = (pllvco * plln) / pllp; + 8004e28: 4350 muls r0, r2 + 8004e2a: fbb0 f0f3 udiv r0, r0, r3 + 8004e2e: e13b b.n 80050a8 + + case RCC_PERIPHCLK_SDMMC1: + +#endif /* SDMMC1 */ + + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL); + 8004e30: f8d3 3088 ldr.w r3, [r3, #136] ; 0x88 + 8004e34: 4957 ldr r1, [pc, #348] ; (8004f94 ) + 8004e36: f003 6340 and.w r3, r3, #201326592 ; 0xc000000 + + if(srcclk == RCC_CCIPR_CLK48SEL) /* MSI ? */ + 8004e3a: f1b3 6f40 cmp.w r3, #201326592 ; 0xc000000 + 8004e3e: d112 bne.n 8004e66 + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + 8004e40: 6808 ldr r0, [r1, #0] + 8004e42: f010 0002 ands.w r0, r0, #2 + 8004e46: f000 812f beq.w 80050a8 + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + 8004e4a: 680b ldr r3, [r1, #0] + 8004e4c: 4a53 ldr r2, [pc, #332] ; (8004f9c ) + 8004e4e: 071b lsls r3, r3, #28 + 8004e50: bf4b itete mi + 8004e52: 680b ldrmi r3, [r1, #0] + 8004e54: f8d1 3094 ldrpl.w r3, [r1, #148] ; 0x94 + 8004e58: f3c3 1303 ubfxmi r3, r3, #4, #4 + 8004e5c: f3c3 2303 ubfxpl r3, r3, #8, #4 + 8004e60: f852 0023 ldr.w r0, [r2, r3, lsl #2] + 8004e64: e120 b.n 80050a8 + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_1) /* PLL ? */ + 8004e66: f1b3 6f00 cmp.w r3, #134217728 ; 0x8000000 + 8004e6a: d10c bne.n 8004e86 + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + 8004e6c: 680b ldr r3, [r1, #0] + 8004e6e: f013 7000 ands.w r0, r3, #33554432 ; 0x2000000 + 8004e72: f000 8119 beq.w 80050a8 + 8004e76: 68cb ldr r3, [r1, #12] + 8004e78: f413 1080 ands.w r0, r3, #1048576 ; 0x100000 + 8004e7c: f000 8114 beq.w 80050a8 + { + /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + 8004e80: 68c8 ldr r0, [r1, #12] + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + 8004e82: 68cb ldr r3, [r1, #12] + 8004e84: e00f b.n 8004ea6 + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_0) /* PLLSAI1 ? */ + 8004e86: f1b3 6f80 cmp.w r3, #67108864 ; 0x4000000 + 8004e8a: f040 810c bne.w 80050a6 + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN)) + 8004e8e: 680b ldr r3, [r1, #0] + 8004e90: f013 6000 ands.w r0, r3, #134217728 ; 0x8000000 + 8004e94: f000 8108 beq.w 80050a8 + 8004e98: 690b ldr r3, [r1, #16] + 8004e9a: f413 1080 ands.w r0, r3, #1048576 ; 0x100000 + 8004e9e: f000 8103 beq.w 80050a8 + { + /* f(PLL48M2CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1Q */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + 8004ea2: 6908 ldr r0, [r1, #16] + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U); + 8004ea4: 690b ldr r3, [r1, #16] + 8004ea6: f3c0 2006 ubfx r0, r0, #8, #7 + 8004eaa: 4350 muls r0, r2 + 8004eac: f3c3 5341 ubfx r3, r3, #21, #2 + 8004eb0: e06d b.n 8004f8e +#endif /* RCC_HSI48_SUPPORT */ + break; + + case RCC_PERIPHCLK_USART1: + /* Get the current USART1 source */ + srcclk = __HAL_RCC_GET_USART1_SOURCE(); + 8004eb2: f8d1 2088 ldr.w r2, [r1, #136] ; 0x88 + + if(srcclk == RCC_USART1CLKSOURCE_PCLK2) + 8004eb6: f012 0203 ands.w r2, r2, #3 + 8004eba: d103 bne.n 8004ec4 + break; + } + } + + return(frequency); +} + 8004ebc: f85d 4b04 ldr.w r4, [sp], #4 + /* Get the current USART1 source */ + srcclk = __HAL_RCC_GET_USART1_SOURCE(); + + if(srcclk == RCC_USART1CLKSOURCE_PCLK2) + { + frequency = HAL_RCC_GetPCLK2Freq(); + 8004ec0: f7ff bb40 b.w 8004544 + } + else if(srcclk == RCC_USART1CLKSOURCE_SYSCLK) + 8004ec4: 2a01 cmp r2, #1 + 8004ec6: d103 bne.n 8004ed0 + break; + } + } + + return(frequency); +} + 8004ec8: f85d 4b04 ldr.w r4, [sp], #4 + { + frequency = HAL_RCC_GetPCLK2Freq(); + } + else if(srcclk == RCC_USART1CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + 8004ecc: f7fe bff6 b.w 8003ebc + } + else if((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8004ed0: 2a02 cmp r2, #2 + 8004ed2: f040 80da bne.w 800508a + 8004ed6: e0d3 b.n 8005080 + } + break; + + case RCC_PERIPHCLK_USART2: + /* Get the current USART2 source */ + srcclk = __HAL_RCC_GET_USART2_SOURCE(); + 8004ed8: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + + if(srcclk == RCC_USART2CLKSOURCE_PCLK1) + 8004edc: f013 030c ands.w r3, r3, #12 + 8004ee0: d103 bne.n 8004eea + break; + } + } + + return(frequency); +} + 8004ee2: f85d 4b04 ldr.w r4, [sp], #4 + /* Get the current USART2 source */ + srcclk = __HAL_RCC_GET_USART2_SOURCE(); + + if(srcclk == RCC_USART2CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + 8004ee6: f7ff bb1d b.w 8004524 + } + else if(srcclk == RCC_USART2CLKSOURCE_SYSCLK) + 8004eea: 2b04 cmp r3, #4 + 8004eec: d0ec beq.n 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8004eee: 2b08 cmp r3, #8 + 8004ef0: f000 809e beq.w 8005030 + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + 8004ef4: 2b0c cmp r3, #12 + 8004ef6: e0a4 b.n 8005042 + +#if defined(USART3) + + case RCC_PERIPHCLK_USART3: + /* Get the current USART3 source */ + srcclk = __HAL_RCC_GET_USART3_SOURCE(); + 8004ef8: f8d1 2088 ldr.w r2, [r1, #136] ; 0x88 + + if(srcclk == RCC_USART3CLKSOURCE_PCLK1) + 8004efc: f012 0230 ands.w r2, r2, #48 ; 0x30 + 8004f00: d0ef beq.n 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_USART3CLKSOURCE_SYSCLK) + 8004f02: 2a10 cmp r2, #16 + 8004f04: d0e0 beq.n 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8004f06: 2a20 cmp r2, #32 + 8004f08: f000 80ba beq.w 8005080 + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART3CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + 8004f0c: 2a30 cmp r2, #48 ; 0x30 + 8004f0e: e0bb b.n 8005088 + +#if defined(UART4) + + case RCC_PERIPHCLK_UART4: + /* Get the current UART4 source */ + srcclk = __HAL_RCC_GET_UART4_SOURCE(); + 8004f10: f8d1 2088 ldr.w r2, [r1, #136] ; 0x88 + + if(srcclk == RCC_UART4CLKSOURCE_PCLK1) + 8004f14: f012 02c0 ands.w r2, r2, #192 ; 0xc0 + 8004f18: d0e3 beq.n 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_UART4CLKSOURCE_SYSCLK) + 8004f1a: 2a40 cmp r2, #64 ; 0x40 + 8004f1c: d0d4 beq.n 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_UART4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8004f1e: 2a80 cmp r2, #128 ; 0x80 + 8004f20: f000 80ae beq.w 8005080 + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_UART4CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + 8004f24: 2ac0 cmp r2, #192 ; 0xc0 + 8004f26: e0af b.n 8005088 + +#if defined(UART5) + + case RCC_PERIPHCLK_UART5: + /* Get the current UART5 source */ + srcclk = __HAL_RCC_GET_UART5_SOURCE(); + 8004f28: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + + if(srcclk == RCC_UART5CLKSOURCE_PCLK1) + 8004f2c: f413 7340 ands.w r3, r3, #768 ; 0x300 + 8004f30: d0d7 beq.n 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_UART5CLKSOURCE_SYSCLK) + 8004f32: f5b3 7f80 cmp.w r3, #256 ; 0x100 + 8004f36: d0c7 beq.n 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_UART5CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8004f38: f5b3 7f00 cmp.w r3, #512 ; 0x200 + 8004f3c: d078 beq.n 8005030 + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_UART5CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + 8004f3e: f5b3 7f40 cmp.w r3, #768 ; 0x300 + 8004f42: e07e b.n 8005042 + +#endif /* UART5 */ + + case RCC_PERIPHCLK_LPUART1: + /* Get the current LPUART1 source */ + srcclk = __HAL_RCC_GET_LPUART1_SOURCE(); + 8004f44: f8d1 2088 ldr.w r2, [r1, #136] ; 0x88 + + if(srcclk == RCC_LPUART1CLKSOURCE_PCLK1) + 8004f48: f412 6240 ands.w r2, r2, #3072 ; 0xc00 + 8004f4c: d0c9 beq.n 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_LPUART1CLKSOURCE_SYSCLK) + 8004f4e: f5b2 6f80 cmp.w r2, #1024 ; 0x400 + 8004f52: d0b9 beq.n 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_LPUART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8004f54: f5b2 6f00 cmp.w r2, #2048 ; 0x800 + 8004f58: f000 8092 beq.w 8005080 + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_LPUART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + 8004f5c: f5b2 6f40 cmp.w r2, #3072 ; 0xc00 + 8004f60: e092 b.n 8005088 + } + break; + + case RCC_PERIPHCLK_ADC: + + srcclk = __HAL_RCC_GET_ADC_SOURCE(); + 8004f62: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + 8004f66: f003 5340 and.w r3, r3, #805306368 ; 0x30000000 + + if(srcclk == RCC_ADCCLKSOURCE_SYSCLK) + 8004f6a: f1b3 5f40 cmp.w r3, #805306368 ; 0x30000000 + 8004f6e: d0ab beq.n 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI1) + 8004f70: f1b3 5f80 cmp.w r3, #268435456 ; 0x10000000 + 8004f74: d118 bne.n 8004fa8 + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_ADC1CLK) != RESET) + 8004f76: 690b ldr r3, [r1, #16] + 8004f78: f013 7080 ands.w r0, r3, #16777216 ; 0x1000000 + 8004f7c: f000 8094 beq.w 80050a8 + { + /* f(PLLADC1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1R */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + 8004f80: 6908 ldr r0, [r1, #16] + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U); + 8004f82: 690b ldr r3, [r1, #16] + 8004f84: f3c0 2006 ubfx r0, r0, #8, #7 + 8004f88: 4350 muls r0, r2 + 8004f8a: f3c3 6341 ubfx r3, r3, #25, #2 + 8004f8e: 3301 adds r3, #1 + 8004f90: 005b lsls r3, r3, #1 + 8004f92: e74a b.n 8004e2a + 8004f94: 40021000 .word 0x40021000 + 8004f98: 0003d090 .word 0x0003d090 + 8004f9c: 08006968 .word 0x08006968 + 8004fa0: 00f42400 .word 0x00f42400 + 8004fa4: 007a1200 .word 0x007a1200 + } + } +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) + else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI2) + 8004fa8: f1b3 5f00 cmp.w r3, #536870912 ; 0x20000000 + 8004fac: d17b bne.n 80050a6 + { + if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_ADC2CLK) != RESET) + 8004fae: 694b ldr r3, [r1, #20] + 8004fb0: f013 7080 ands.w r0, r3, #16777216 ; 0x1000000 + 8004fb4: d078 beq.n 80050a8 + { + /* f(PLLADC2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2R */ + plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; + 8004fb6: 6948 ldr r0, [r1, #20] + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) << 1U); + 8004fb8: 694b ldr r3, [r1, #20] + 8004fba: e7e3 b.n 8004f84 + +#if defined(DFSDM1_Filter0) + + case RCC_PERIPHCLK_DFSDM1: + /* Get the current DFSDM1 source */ + srcclk = __HAL_RCC_GET_DFSDM1_SOURCE(); + 8004fbc: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + + if(srcclk == RCC_DFSDM1CLKSOURCE_PCLK2) + 8004fc0: 2b00 cmp r3, #0 + 8004fc2: f6bf af7b bge.w 8004ebc + 8004fc6: e77f b.n 8004ec8 + +#endif /* DFSDM1_Filter0 */ + + case RCC_PERIPHCLK_I2C1: + /* Get the current I2C1 source */ + srcclk = __HAL_RCC_GET_I2C1_SOURCE(); + 8004fc8: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + + if(srcclk == RCC_I2C1CLKSOURCE_PCLK1) + 8004fcc: f413 5340 ands.w r3, r3, #12288 ; 0x3000 + 8004fd0: d087 beq.n 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C1CLKSOURCE_SYSCLK) + 8004fd2: f5b3 5f80 cmp.w r3, #4096 ; 0x1000 + 8004fd6: f43f af77 beq.w 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8004fda: f5b3 5f00 cmp.w r3, #8192 ; 0x2000 + 8004fde: d162 bne.n 80050a6 + 8004fe0: e026 b.n 8005030 + +#if defined(I2C2) + + case RCC_PERIPHCLK_I2C2: + /* Get the current I2C2 source */ + srcclk = __HAL_RCC_GET_I2C2_SOURCE(); + 8004fe2: f8d1 2088 ldr.w r2, [r1, #136] ; 0x88 + + if(srcclk == RCC_I2C2CLKSOURCE_PCLK1) + 8004fe6: f412 4240 ands.w r2, r2, #49152 ; 0xc000 + 8004fea: f43f af7a beq.w 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C2CLKSOURCE_SYSCLK) + 8004fee: f5b2 4f80 cmp.w r2, #16384 ; 0x4000 + 8004ff2: f43f af69 beq.w 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8004ff6: f5b2 4f00 cmp.w r2, #32768 ; 0x8000 + 8004ffa: e00b b.n 8005014 + +#endif /* I2C2 */ + + case RCC_PERIPHCLK_I2C3: + /* Get the current I2C3 source */ + srcclk = __HAL_RCC_GET_I2C3_SOURCE(); + 8004ffc: f8d1 2088 ldr.w r2, [r1, #136] ; 0x88 + + if(srcclk == RCC_I2C3CLKSOURCE_PCLK1) + 8005000: f412 3240 ands.w r2, r2, #196608 ; 0x30000 + 8005004: f43f af6d beq.w 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C3CLKSOURCE_SYSCLK) + 8005008: f5b2 3f80 cmp.w r2, #65536 ; 0x10000 + 800500c: f43f af5c beq.w 8004ec8 + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 8005010: f5b2 3f00 cmp.w r2, #131072 ; 0x20000 + 8005014: d147 bne.n 80050a6 + 8005016: e033 b.n 8005080 + +#endif /* I2C4 */ + + case RCC_PERIPHCLK_LPTIM1: + /* Get the current LPTIM1 source */ + srcclk = __HAL_RCC_GET_LPTIM1_SOURCE(); + 8005018: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + + if(srcclk == RCC_LPTIM1CLKSOURCE_PCLK1) + 800501c: f413 2340 ands.w r3, r3, #786432 ; 0xc0000 + 8005020: f43f af5f beq.w 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_LPTIM1CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + 8005024: f5b3 2f80 cmp.w r3, #262144 ; 0x40000 + 8005028: d01e beq.n 8005068 + { + frequency = LSI_VALUE; + } + else if((srcclk == RCC_LPTIM1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 800502a: f5b3 2f00 cmp.w r3, #524288 ; 0x80000 + 800502e: d106 bne.n 800503e + 8005030: 680b ldr r3, [r1, #0] + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + 8005032: 481f ldr r0, [pc, #124] ; (80050b0 ) + 8005034: f413 6f80 tst.w r3, #1024 ; 0x400 + 8005038: bf08 it eq + 800503a: 2000 moveq r0, #0 + 800503c: e034 b.n 80050a8 + } + else if((srcclk == RCC_LPTIM1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if ((srcclk == RCC_LPTIM1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + 800503e: f5b3 2f40 cmp.w r3, #786432 ; 0xc0000 + 8005042: d130 bne.n 80050a6 + 8005044: f8d1 3090 ldr.w r3, [r1, #144] ; 0x90 + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + 8005048: f013 0f02 tst.w r3, #2 + 800504c: bf0c ite eq + 800504e: 2000 moveq r0, #0 + 8005050: f44f 4000 movne.w r0, #32768 ; 0x8000 + 8005054: e028 b.n 80050a8 + } + break; + + case RCC_PERIPHCLK_LPTIM2: + /* Get the current LPTIM2 source */ + srcclk = __HAL_RCC_GET_LPTIM2_SOURCE(); + 8005056: f8d1 2088 ldr.w r2, [r1, #136] ; 0x88 + + if(srcclk == RCC_LPTIM2CLKSOURCE_PCLK1) + 800505a: f412 1240 ands.w r2, r2, #3145728 ; 0x300000 + 800505e: f43f af40 beq.w 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_LPTIM2CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + 8005062: f5b2 1f80 cmp.w r2, #1048576 ; 0x100000 + 8005066: d108 bne.n 800507a + 8005068: f8d1 3094 ldr.w r3, [r1, #148] ; 0x94 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_LPTIM1CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + { + frequency = LSI_VALUE; + 800506c: f013 0f02 tst.w r3, #2 + 8005070: bf0c ite eq + 8005072: 2000 moveq r0, #0 + 8005074: f44f 40fa movne.w r0, #32000 ; 0x7d00 + 8005078: e016 b.n 80050a8 + } + else if((srcclk == RCC_LPTIM2CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + { + frequency = LSI_VALUE; + } + else if((srcclk == RCC_LPTIM2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 800507a: f5b2 1f00 cmp.w r2, #2097152 ; 0x200000 + 800507e: d101 bne.n 8005084 + 8005080: 681b ldr r3, [r3, #0] + 8005082: e7d6 b.n 8005032 + { + frequency = HSI_VALUE; + } + else if ((srcclk == RCC_LPTIM2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + 8005084: f5b2 1f40 cmp.w r2, #3145728 ; 0x300000 + 8005088: d10d bne.n 80050a6 + 800508a: f8d3 3090 ldr.w r3, [r3, #144] ; 0x90 + 800508e: e7db b.n 8005048 + +#if defined(SWPMI1) + + case RCC_PERIPHCLK_SWPMI1: + /* Get the current SWPMI1 source */ + srcclk = __HAL_RCC_GET_SWPMI1_SOURCE(); + 8005090: f8d1 3088 ldr.w r3, [r1, #136] ; 0x88 + + if(srcclk == RCC_SWPMI1CLKSOURCE_PCLK1) + 8005094: f013 4380 ands.w r3, r3, #1073741824 ; 0x40000000 + 8005098: f43f af23 beq.w 8004ee2 + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_SWPMI1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + 800509c: b11b cbz r3, 80050a6 + 800509e: e7c7 b.n 8005030 + 80050a0: f64b 3080 movw r0, #48000 ; 0xbb80 + 80050a4: e000 b.n 80050a8 + frequency = HSE_VALUE / 32; + } + /* Clock not enabled for RTC*/ + else + { + frequency = 0U; + 80050a6: 2000 movs r0, #0 + break; + } + } + + return(frequency); +} + 80050a8: f85d 4b04 ldr.w r4, [sp], #4 + 80050ac: 4770 bx lr + 80050ae: bf00 nop + 80050b0: 00f42400 .word 0x00f42400 + +080050b4 : + * @param PLLSAI1Init pointer to an RCC_PLLSAI1InitTypeDef structure that + * contains the configuration information for the PLLSAI1 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) +{ + 80050b4: b570 push {r4, r5, r6, lr} + assert_param(IS_RCC_PLLSAI1Q_VALUE(PLLSAI1Init->PLLSAI1Q)); + assert_param(IS_RCC_PLLSAI1R_VALUE(PLLSAI1Init->PLLSAI1R)); + assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1Init->PLLSAI1ClockOut)); + + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + 80050b6: 4c1d ldr r4, [pc, #116] ; (800512c ) + 80050b8: 6823 ldr r3, [r4, #0] + 80050ba: f023 6380 bic.w r3, r3, #67108864 ; 0x4000000 + 80050be: 6023 str r3, [r4, #0] + * @param PLLSAI1Init pointer to an RCC_PLLSAI1InitTypeDef structure that + * contains the configuration information for the PLLSAI1 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) +{ + 80050c0: 4605 mov r5, r0 + + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 80050c2: f7fb fcb9 bl 8000a38 + 80050c6: 4606 mov r6, r0 + + /* Wait till PLLSAI1 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + 80050c8: 6823 ldr r3, [r4, #0] + 80050ca: 4818 ldr r0, [pc, #96] ; (800512c ) + 80050cc: 011a lsls r2, r3, #4 + 80050ce: d506 bpl.n 80050de + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + 80050d0: f7fb fcb2 bl 8000a38 + 80050d4: 1b80 subs r0, r0, r6 + 80050d6: 2802 cmp r0, #2 + 80050d8: d9f6 bls.n 80050c8 + { + status = HAL_TIMEOUT; + 80050da: 2003 movs r0, #3 + 80050dc: bd70 pop {r4, r5, r6, pc} + + if(status == HAL_OK) + { + /* Configure the PLLSAI1 Multiplication factor N */ + /* Configure the PLLSAI1 Division factors P, Q and R */ + __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R); + 80050de: 68ea ldr r2, [r5, #12] + 80050e0: 68ab ldr r3, [r5, #8] + 80050e2: 0912 lsrs r2, r2, #4 + 80050e4: 021b lsls r3, r3, #8 + 80050e6: ea43 4142 orr.w r1, r3, r2, lsl #17 + 80050ea: 692b ldr r3, [r5, #16] + 80050ec: 085b lsrs r3, r3, #1 + 80050ee: 3b01 subs r3, #1 + 80050f0: ea41 5243 orr.w r2, r1, r3, lsl #21 + 80050f4: 696b ldr r3, [r5, #20] + 80050f6: 085b lsrs r3, r3, #1 + 80050f8: 3b01 subs r3, #1 + 80050fa: ea42 6343 orr.w r3, r2, r3, lsl #25 + 80050fe: 6103 str r3, [r0, #16] + /* Configure the PLLSAI1 Clock output(s) */ + __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1Init->PLLSAI1ClockOut); + 8005100: 6902 ldr r2, [r0, #16] + 8005102: 69ab ldr r3, [r5, #24] + 8005104: 4313 orrs r3, r2 + 8005106: 6103 str r3, [r0, #16] + + /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/ + __HAL_RCC_PLLSAI1_ENABLE(); + 8005108: 6803 ldr r3, [r0, #0] + 800510a: f043 6380 orr.w r3, r3, #67108864 ; 0x4000000 + 800510e: 6003 str r3, [r0, #0] + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 8005110: f7fb fc92 bl 8000a38 + 8005114: 4605 mov r5, r0 + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + 8005116: 6823 ldr r3, [r4, #0] + 8005118: 011b lsls r3, r3, #4 + 800511a: d405 bmi.n 8005128 + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + 800511c: f7fb fc8c bl 8000a38 + 8005120: 1b40 subs r0, r0, r5 + 8005122: 2802 cmp r0, #2 + 8005124: d9f7 bls.n 8005116 + 8005126: e7d8 b.n 80050da + 8005128: 2000 movs r0, #0 + break; + } + } + } + + return status; + 800512a: bd70 pop {r4, r5, r6, pc} + 800512c: 40021000 .word 0x40021000 + +08005130 : +/** + * @brief Disable PLLSAI1. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void) +{ + 8005130: b538 push {r3, r4, r5, lr} + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + 8005132: 4c10 ldr r4, [pc, #64] ; (8005174 ) + 8005134: 6823 ldr r3, [r4, #0] + 8005136: f023 6380 bic.w r3, r3, #67108864 ; 0x4000000 + 800513a: 6023 str r3, [r4, #0] + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + 800513c: f7fb fc7c bl 8000a38 + 8005140: 4605 mov r5, r0 + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + 8005142: 6820 ldr r0, [r4, #0] + 8005144: f010 6000 ands.w r0, r0, #134217728 ; 0x8000000 + 8005148: d005 beq.n 8005156 + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + 800514a: f7fb fc75 bl 8000a38 + 800514e: 1b40 subs r0, r0, r5 + 8005150: 2802 cmp r0, #2 + 8005152: d9f6 bls.n 8005142 + { + status = HAL_TIMEOUT; + 8005154: 2003 movs r0, #3 + break; + } + } + + /* Disable the PLLSAI1 Clock outputs */ + __HAL_RCC_PLLSAI1CLKOUT_DISABLE(RCC_PLLSAI1CFGR_PLLSAI1PEN|RCC_PLLSAI1CFGR_PLLSAI1QEN|RCC_PLLSAI1CFGR_PLLSAI1REN); + 8005156: 6923 ldr r3, [r4, #16] + 8005158: 4a06 ldr r2, [pc, #24] ; (8005174 ) + 800515a: f023 7388 bic.w r3, r3, #17825792 ; 0x1100000 + 800515e: f423 3380 bic.w r3, r3, #65536 ; 0x10000 + 8005162: 6123 str r3, [r4, #16] + + /* Reset PLL source to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + 8005164: 6823 ldr r3, [r4, #0] + 8005166: 019b lsls r3, r3, #6 + && + (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) +#endif /* RCC_PLLSAI2_SUPPORT */ + ) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + 8005168: bf5e ittt pl + 800516a: 68d3 ldrpl r3, [r2, #12] + 800516c: f023 0303 bicpl.w r3, r3, #3 + 8005170: 60d3 strpl r3, [r2, #12] + } + + return status; +} + 8005172: bd38 pop {r3, r4, r5, pc} + 8005174: 40021000 .word 0x40021000 + +08005178 : + */ +void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk) +{ + assert_param(IS_RCC_STOP_WAKEUPCLOCK(WakeUpClk)); + + __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(WakeUpClk); + 8005178: 4a03 ldr r2, [pc, #12] ; (8005188 ) + 800517a: 6893 ldr r3, [r2, #8] + 800517c: f423 4300 bic.w r3, r3, #32768 ; 0x8000 + 8005180: 4318 orrs r0, r3 + 8005182: 6090 str r0, [r2, #8] + 8005184: 4770 bx lr + 8005186: bf00 nop + 8005188: 40021000 .word 0x40021000 + +0800518c : + */ +void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange) +{ + assert_param(IS_RCC_MSI_STANDBY_CLOCK_RANGE(MSIRange)); + + __HAL_RCC_MSI_STANDBY_RANGE_CONFIG(MSIRange); + 800518c: 4a04 ldr r2, [pc, #16] ; (80051a0 ) + 800518e: f8d2 3094 ldr.w r3, [r2, #148] ; 0x94 + 8005192: f423 6370 bic.w r3, r3, #3840 ; 0xf00 + 8005196: ea43 1000 orr.w r0, r3, r0, lsl #4 + 800519a: f8c2 0094 str.w r0, [r2, #148] ; 0x94 + 800519e: 4770 bx lr + 80051a0: 40021000 .word 0x40021000 + +080051a4 : + * clock with HAL_RCCEx_PeriphCLKConfig(). + * @retval None + */ +void HAL_RCCEx_EnableLSECSS(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; + 80051a4: 4a03 ldr r2, [pc, #12] ; (80051b4 ) + 80051a6: f8d2 3090 ldr.w r3, [r2, #144] ; 0x90 + 80051aa: f043 0320 orr.w r3, r3, #32 + 80051ae: f8c2 3090 str.w r3, [r2, #144] ; 0x90 + 80051b2: 4770 bx lr + 80051b4: 40021000 .word 0x40021000 + +080051b8 : + * @note LSE Clock Security System can only be disabled after a LSE failure detection. + * @retval None + */ +void HAL_RCCEx_DisableLSECSS(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; + 80051b8: 4b05 ldr r3, [pc, #20] ; (80051d0 ) + 80051ba: f8d3 2090 ldr.w r2, [r3, #144] ; 0x90 + 80051be: f022 0220 bic.w r2, r2, #32 + 80051c2: f8c3 2090 str.w r2, [r3, #144] ; 0x90 + + /* Disable LSE CSS IT if any */ + __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS); + 80051c6: 699a ldr r2, [r3, #24] + 80051c8: f422 7200 bic.w r2, r2, #512 ; 0x200 + 80051cc: 619a str r2, [r3, #24] + 80051ce: 4770 bx lr + 80051d0: 40021000 .word 0x40021000 + +080051d4 : + * @retval None + */ +void HAL_RCCEx_EnableLSECSS_IT(void) +{ + /* Enable LSE CSS */ + SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; + 80051d4: 4b0a ldr r3, [pc, #40] ; (8005200 ) + 80051d6: f8d3 2090 ldr.w r2, [r3, #144] ; 0x90 + 80051da: f042 0220 orr.w r2, r2, #32 + 80051de: f8c3 2090 str.w r2, [r3, #144] ; 0x90 + + /* Enable LSE CSS IT */ + __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS); + 80051e2: 699a ldr r2, [r3, #24] + 80051e4: f442 7200 orr.w r2, r2, #512 ; 0x200 + 80051e8: 619a str r2, [r3, #24] + + /* Enable IT on EXTI Line 19 */ + __HAL_RCC_LSECSS_EXTI_ENABLE_IT(); + 80051ea: f5a3 3386 sub.w r3, r3, #68608 ; 0x10c00 + 80051ee: 681a ldr r2, [r3, #0] + 80051f0: f442 2200 orr.w r2, r2, #524288 ; 0x80000 + 80051f4: 601a str r2, [r3, #0] + __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE(); + 80051f6: 689a ldr r2, [r3, #8] + 80051f8: f442 2200 orr.w r2, r2, #524288 ; 0x80000 + 80051fc: 609a str r2, [r3, #8] + 80051fe: 4770 bx lr + 8005200: 40021000 .word 0x40021000 + +08005204 : +/** + * @brief RCCEx LSE Clock Security System interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_LSECSS_Callback(void) +{ + 8005204: 4770 bx lr + ... + +08005208 : +/** + * @brief Handle the RCC LSE Clock Security System interrupt request. + * @retval None + */ +void HAL_RCCEx_LSECSS_IRQHandler(void) +{ + 8005208: b510 push {r4, lr} + /* Check RCC LSE CSSF flag */ + if(__HAL_RCC_GET_IT(RCC_IT_LSECSS)) + 800520a: 4c05 ldr r4, [pc, #20] ; (8005220 ) + 800520c: 69e3 ldr r3, [r4, #28] + 800520e: 059b lsls r3, r3, #22 + 8005210: d504 bpl.n 800521c + { + /* RCC LSE Clock Security System interrupt user callback */ + HAL_RCCEx_LSECSS_Callback(); + 8005212: f7ff fff7 bl 8005204 + + /* Clear RCC LSE CSS pending bit */ + __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS); + 8005216: f44f 7300 mov.w r3, #512 ; 0x200 + 800521a: 6223 str r3, [r4, #32] + 800521c: bd10 pop {r4, pc} + 800521e: bf00 nop + 8005220: 40021000 .word 0x40021000 + +08005224 : + * calibration LSE oscillator is to be enabled with HAL_RCC_OscConfig(). + * @retval None + */ +void HAL_RCCEx_EnableMSIPLLMode(void) +{ + SET_BIT(RCC->CR, RCC_CR_MSIPLLEN) ; + 8005224: 4a02 ldr r2, [pc, #8] ; (8005230 ) + 8005226: 6813 ldr r3, [r2, #0] + 8005228: f043 0304 orr.w r3, r3, #4 + 800522c: 6013 str r3, [r2, #0] + 800522e: 4770 bx lr + 8005230: 40021000 .word 0x40021000 + +08005234 : + * @note PLL-mode of the MSI is automatically reset when LSE oscillator is disabled. + * @retval None + */ +void HAL_RCCEx_DisableMSIPLLMode(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN) ; + 8005234: 4a02 ldr r2, [pc, #8] ; (8005240 ) + 8005236: 6813 ldr r3, [r2, #0] + 8005238: f023 0304 bic.w r3, r3, #4 + 800523c: 6013 str r3, [r2, #0] + 800523e: 4770 bx lr + 8005240: 40021000 .word 0x40021000 + +08005244 : + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +}; + +/*********************** FUNCTION DEFINITIONS ***********************/ +void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) +{ + 8005244: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + 8005248: 2200 movs r2, #0 + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +}; + +/*********************** FUNCTION DEFINITIONS ***********************/ +void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) +{ + 800524a: b0cb sub sp, #300 ; 0x12c + 800524c: 460c mov r4, r1 + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + 800524e: 5c8d ldrb r5, [r1, r2] + 8005250: 78e3 ldrb r3, [r4, #3] + 8005252: ea43 6305 orr.w r3, r3, r5, lsl #24 + 8005256: 7865 ldrb r5, [r4, #1] + 8005258: ea43 4305 orr.w r3, r3, r5, lsl #16 + 800525c: 78a5 ldrb r5, [r4, #2] + 800525e: ea43 2305 orr.w r3, r3, r5, lsl #8 + 8005262: ad0a add r5, sp, #40 ; 0x28 + 8005264: 3404 adds r4, #4 + 8005266: 50ab str r3, [r5, r2] +/*********************** FUNCTION DEFINITIONS ***********************/ +void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) +{ + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + 8005268: 3204 adds r2, #4 + 800526a: 2a40 cmp r2, #64 ; 0x40 + 800526c: d1ef bne.n 800524e + 800526e: 462b mov r3, r5 + 8005270: 2610 movs r6, #16 + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for ( ; i < 64; ++i) + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + 8005272: 6b9d ldr r5, [r3, #56] ; 0x38 + 8005274: 6819 ldr r1, [r3, #0] + 8005276: 685a ldr r2, [r3, #4] + 8005278: ea4f 44f5 mov.w r4, r5, ror #19 + 800527c: ea84 4475 eor.w r4, r4, r5, ror #17 + 8005280: ea84 2595 eor.w r5, r4, r5, lsr #10 + 8005284: 6a5c ldr r4, [r3, #36] ; 0x24 + 8005286: 4421 add r1, r4 + 8005288: 186c adds r4, r5, r1 + 800528a: ea4f 41b2 mov.w r1, r2, ror #18 + 800528e: ea81 11f2 eor.w r1, r1, r2, ror #7 + 8005292: ea81 02d2 eor.w r2, r1, r2, lsr #3 +{ + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for ( ; i < 64; ++i) + 8005296: 3601 adds r6, #1 + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + 8005298: 4422 add r2, r4 +{ + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for ( ; i < 64; ++i) + 800529a: 2e40 cmp r6, #64 ; 0x40 + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + 800529c: 641a str r2, [r3, #64] ; 0x40 + 800529e: f103 0304 add.w r3, r3, #4 +{ + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for ( ; i < 64; ++i) + 80052a2: d1e6 bne.n 8005272 + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + + a = ctx->state[0]; + 80052a4: 6d03 ldr r3, [r0, #80] ; 0x50 + 80052a6: 9301 str r3, [sp, #4] + b = ctx->state[1]; + 80052a8: 6d43 ldr r3, [r0, #84] ; 0x54 + 80052aa: 9302 str r3, [sp, #8] + c = ctx->state[2]; + 80052ac: 6d83 ldr r3, [r0, #88] ; 0x58 + 80052ae: 9303 str r3, [sp, #12] + d = ctx->state[3]; + 80052b0: 6dc3 ldr r3, [r0, #92] ; 0x5c + 80052b2: 9304 str r3, [sp, #16] + e = ctx->state[4]; + 80052b4: 6e03 ldr r3, [r0, #96] ; 0x60 + 80052b6: 9305 str r3, [sp, #20] + f = ctx->state[5]; + 80052b8: 6e43 ldr r3, [r0, #100] ; 0x64 + 80052ba: 9306 str r3, [sp, #24] + g = ctx->state[6]; + 80052bc: 6e83 ldr r3, [r0, #104] ; 0x68 + 80052be: 9307 str r3, [sp, #28] + h = ctx->state[7]; + 80052c0: 6ec3 ldr r3, [r0, #108] ; 0x6c + 80052c2: 9308 str r3, [sp, #32] + 80052c4: 469b mov fp, r3 + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + 80052c6: 9f07 ldr r7, [sp, #28] + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + f = ctx->state[5]; + 80052c8: f8dd e018 ldr.w lr, [sp, #24] + + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + 80052cc: 9b05 ldr r3, [sp, #20] + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + 80052ce: f8dd 8010 ldr.w r8, [sp, #16] + for ( ; i < 64; ++i) + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + 80052d2: 9d03 ldr r5, [sp, #12] + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for ( ; i < 64; ++i) + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + + a = ctx->state[0]; + b = ctx->state[1]; + 80052d4: 9e02 ldr r6, [sp, #8] + for (i = 0, j = 0; i < 16; ++i, j += 4) + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for ( ; i < 64; ++i) + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + + a = ctx->state[0]; + 80052d6: 9901 ldr r1, [sp, #4] + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; + 80052d8: f8df 90ac ldr.w r9, [pc, #172] ; 8005388 + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + 80052dc: f04f 0c00 mov.w ip, #0 + t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; + 80052e0: ea4f 22f3 mov.w r2, r3, ror #11 + 80052e4: ea82 12b3 eor.w r2, r2, r3, ror #6 + 80052e8: ea82 6a73 eor.w sl, r2, r3, ror #25 + 80052ec: aa0a add r2, sp, #40 ; 0x28 + 80052ee: f852 402c ldr.w r4, [r2, ip, lsl #2] + 80052f2: 4622 mov r2, r4 + 80052f4: f859 402c ldr.w r4, [r9, ip, lsl #2] + 80052f8: 4414 add r4, r2 + 80052fa: eb0a 0204 add.w r2, sl, r4 + 80052fe: ea03 0a0e and.w sl, r3, lr + 8005302: ea27 0403 bic.w r4, r7, r3 + 8005306: ea84 040a eor.w r4, r4, sl + 800530a: 4414 add r4, r2 + 800530c: 445c add r4, fp + t2 = EP0(a) + MAJ(a,b,c); + 800530e: ea4f 3a71 mov.w sl, r1, ror #13 + 8005312: ea85 0b06 eor.w fp, r5, r6 + 8005316: ea0b 0b01 and.w fp, fp, r1 + 800531a: ea8a 0ab1 eor.w sl, sl, r1, ror #2 + 800531e: ea06 0205 and.w r2, r6, r5 + 8005322: ea8b 0202 eor.w r2, fp, r2 + 8005326: ea8a 5ab1 eor.w sl, sl, r1, ror #22 + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + 800532a: f10c 0c01 add.w ip, ip, #1 + t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; + t2 = EP0(a) + MAJ(a,b,c); + 800532e: 4492 add sl, r2 + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + 8005330: f1bc 0f40 cmp.w ip, #64 ; 0x40 + t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; + t2 = EP0(a) + MAJ(a,b,c); + h = g; + g = f; + f = e; + e = d + t1; + 8005334: eb04 0208 add.w r2, r4, r8 + 8005338: 9209 str r2, [sp, #36] ; 0x24 + d = c; + c = b; + b = a; + a = t1 + t2; + 800533a: 4454 add r4, sl + 800533c: 46a8 mov r8, r5 + 800533e: 46bb mov fp, r7 + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + 8005340: d006 beq.n 8005350 + 8005342: 4677 mov r7, lr + 8005344: 4635 mov r5, r6 + 8005346: 469e mov lr, r3 + 8005348: 460e mov r6, r1 + t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; + t2 = EP0(a) + MAJ(a,b,c); + h = g; + g = f; + f = e; + e = d + t1; + 800534a: 9b09 ldr r3, [sp, #36] ; 0x24 + d = c; + c = b; + b = a; + a = t1 + t2; + 800534c: 4621 mov r1, r4 + 800534e: e7c7 b.n 80052e0 + } + + ctx->state[0] += a; + 8005350: 9a01 ldr r2, [sp, #4] + 8005352: 4422 add r2, r4 + 8005354: 6502 str r2, [r0, #80] ; 0x50 + ctx->state[1] += b; + 8005356: 9a02 ldr r2, [sp, #8] + 8005358: 440a add r2, r1 + 800535a: 6542 str r2, [r0, #84] ; 0x54 + ctx->state[2] += c; + 800535c: 9a03 ldr r2, [sp, #12] + ctx->state[3] += d; + ctx->state[4] += e; + 800535e: 9909 ldr r1, [sp, #36] ; 0x24 + a = t1 + t2; + } + + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + 8005360: 4432 add r2, r6 + 8005362: 6582 str r2, [r0, #88] ; 0x58 + ctx->state[3] += d; + 8005364: 9a04 ldr r2, [sp, #16] + 8005366: 442a add r2, r5 + 8005368: 65c2 str r2, [r0, #92] ; 0x5c + ctx->state[4] += e; + 800536a: 9a05 ldr r2, [sp, #20] + 800536c: 440a add r2, r1 + 800536e: 6602 str r2, [r0, #96] ; 0x60 + ctx->state[5] += f; + 8005370: 9a06 ldr r2, [sp, #24] + 8005372: 441a add r2, r3 + ctx->state[6] += g; + 8005374: 9b07 ldr r3, [sp, #28] + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + ctx->state[3] += d; + ctx->state[4] += e; + ctx->state[5] += f; + 8005376: 6642 str r2, [r0, #100] ; 0x64 + ctx->state[6] += g; + 8005378: 4473 add r3, lr + 800537a: 6683 str r3, [r0, #104] ; 0x68 + ctx->state[7] += h; + 800537c: 9b08 ldr r3, [sp, #32] + 800537e: 443b add r3, r7 + 8005380: 66c3 str r3, [r0, #108] ; 0x6c +} + 8005382: b04b add sp, #300 ; 0x12c + 8005384: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 8005388: 080073b4 .word 0x080073b4 + +0800538c : + +void sha256_init(SHA256_CTX *ctx) +{ + ctx->datalen = 0; + 800538c: 2300 movs r3, #0 + 800538e: 6403 str r3, [r0, #64] ; 0x40 + ctx->bitlen = 0; + 8005390: 2200 movs r2, #0 + 8005392: 2300 movs r3, #0 + 8005394: e9c0 2312 strd r2, r3, [r0, #72] ; 0x48 + ctx->state[0] = 0x6a09e667; + 8005398: 4b0a ldr r3, [pc, #40] ; (80053c4 ) + 800539a: 6503 str r3, [r0, #80] ; 0x50 + ctx->state[1] = 0xbb67ae85; + 800539c: 4b0a ldr r3, [pc, #40] ; (80053c8 ) + 800539e: 6543 str r3, [r0, #84] ; 0x54 + ctx->state[2] = 0x3c6ef372; + 80053a0: 4b0a ldr r3, [pc, #40] ; (80053cc ) + 80053a2: 6583 str r3, [r0, #88] ; 0x58 + ctx->state[3] = 0xa54ff53a; + 80053a4: 4b0a ldr r3, [pc, #40] ; (80053d0 ) + 80053a6: 65c3 str r3, [r0, #92] ; 0x5c + ctx->state[4] = 0x510e527f; + 80053a8: 4b0a ldr r3, [pc, #40] ; (80053d4 ) + 80053aa: 6603 str r3, [r0, #96] ; 0x60 + ctx->state[5] = 0x9b05688c; + 80053ac: 4b0a ldr r3, [pc, #40] ; (80053d8 ) + 80053ae: 6643 str r3, [r0, #100] ; 0x64 + ctx->state[6] = 0x1f83d9ab; + 80053b0: 4b0a ldr r3, [pc, #40] ; (80053dc ) + 80053b2: 6683 str r3, [r0, #104] ; 0x68 + ctx->state[7] = 0x5be0cd19; + 80053b4: f103 5374 add.w r3, r3, #1023410176 ; 0x3d000000 + 80053b8: f5a3 0323 sub.w r3, r3, #10682368 ; 0xa30000 + 80053bc: f6a3 4392 subw r3, r3, #3218 ; 0xc92 + 80053c0: 66c3 str r3, [r0, #108] ; 0x6c + 80053c2: 4770 bx lr + 80053c4: 6a09e667 .word 0x6a09e667 + 80053c8: bb67ae85 .word 0xbb67ae85 + 80053cc: 3c6ef372 .word 0x3c6ef372 + 80053d0: a54ff53a .word 0xa54ff53a + 80053d4: 510e527f .word 0x510e527f + 80053d8: 9b05688c .word 0x9b05688c + 80053dc: 1f83d9ab .word 0x1f83d9ab + +080053e0 : +} + +void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) +{ + 80053e0: b5f8 push {r3, r4, r5, r6, r7, lr} + 80053e2: 4604 mov r4, r0 + 80053e4: 460d mov r5, r1 + 80053e6: 188e adds r6, r1, r2 + ctx->data[ctx->datalen] = data[i]; + ctx->datalen++; + if (ctx->datalen == 64) { + sha256_transform(ctx, ctx->data); + ctx->bitlen += 512; + ctx->datalen = 0; + 80053e8: 2700 movs r7, #0 + +void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) +{ + WORD i; + + for (i = 0; i < len; ++i) { + 80053ea: 42b5 cmp r5, r6 + 80053ec: d015 beq.n 800541a + ctx->data[ctx->datalen] = data[i]; + 80053ee: 6c23 ldr r3, [r4, #64] ; 0x40 + 80053f0: f815 2b01 ldrb.w r2, [r5], #1 + 80053f4: 54e2 strb r2, [r4, r3] + ctx->datalen++; + 80053f6: 3301 adds r3, #1 + if (ctx->datalen == 64) { + 80053f8: 2b40 cmp r3, #64 ; 0x40 +{ + WORD i; + + for (i = 0; i < len; ++i) { + ctx->data[ctx->datalen] = data[i]; + ctx->datalen++; + 80053fa: 6423 str r3, [r4, #64] ; 0x40 + if (ctx->datalen == 64) { + 80053fc: d1f5 bne.n 80053ea + sha256_transform(ctx, ctx->data); + 80053fe: 4621 mov r1, r4 + 8005400: 4620 mov r0, r4 + 8005402: f7ff ff1f bl 8005244 + ctx->bitlen += 512; + 8005406: e9d4 0112 ldrd r0, r1, [r4, #72] ; 0x48 + 800540a: f510 7000 adds.w r0, r0, #512 ; 0x200 + 800540e: f141 0100 adc.w r1, r1, #0 + 8005412: e9c4 0112 strd r0, r1, [r4, #72] ; 0x48 + ctx->datalen = 0; + 8005416: 6427 str r7, [r4, #64] ; 0x40 + 8005418: e7e7 b.n 80053ea + } + } +} + 800541a: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0800541c : + +void sha256_final(SHA256_CTX *ctx, BYTE hash[]) +{ + 800541c: b538 push {r3, r4, r5, lr} + WORD i; + + i = ctx->datalen; + 800541e: 6c03 ldr r3, [r0, #64] ; 0x40 + 8005420: 2280 movs r2, #128 ; 0x80 + + // Pad whatever data is left in the buffer. + if (ctx->datalen < 56) { + 8005422: 2b37 cmp r3, #55 ; 0x37 + } + } +} + +void sha256_final(SHA256_CTX *ctx, BYTE hash[]) +{ + 8005424: 4604 mov r4, r0 + 8005426: 460d mov r5, r1 + + i = ctx->datalen; + + // Pad whatever data is left in the buffer. + if (ctx->datalen < 56) { + ctx->data[i++] = 0x80; + 8005428: 54c2 strb r2, [r0, r3] + WORD i; + + i = ctx->datalen; + + // Pad whatever data is left in the buffer. + if (ctx->datalen < 56) { + 800542a: d808 bhi.n 800543e + 800542c: 4403 add r3, r0 + 800542e: f100 0237 add.w r2, r0, #55 ; 0x37 + ctx->data[i++] = 0x80; + while (i < 56) + ctx->data[i++] = 0x00; + 8005432: 2100 movs r1, #0 + i = ctx->datalen; + + // Pad whatever data is left in the buffer. + if (ctx->datalen < 56) { + ctx->data[i++] = 0x80; + while (i < 56) + 8005434: 429a cmp r2, r3 + 8005436: d014 beq.n 8005462 + ctx->data[i++] = 0x00; + 8005438: f803 1f01 strb.w r1, [r3, #1]! + 800543c: e7fa b.n 8005434 + 800543e: 3301 adds r3, #1 + 8005440: 4403 add r3, r0 + } + else { + ctx->data[i++] = 0x80; + while (i < 64) + ctx->data[i++] = 0x00; + 8005442: 2100 movs r1, #0 + while (i < 56) + ctx->data[i++] = 0x00; + } + else { + ctx->data[i++] = 0x80; + while (i < 64) + 8005444: 1b1a subs r2, r3, r4 + 8005446: 2a3f cmp r2, #63 ; 0x3f + 8005448: d802 bhi.n 8005450 + ctx->data[i++] = 0x00; + 800544a: f803 1b01 strb.w r1, [r3], #1 + 800544e: e7f9 b.n 8005444 + sha256_transform(ctx, ctx->data); + 8005450: 4621 mov r1, r4 + 8005452: 4620 mov r0, r4 + 8005454: f7ff fef6 bl 8005244 + memset(ctx->data, 0, 56); + 8005458: 2238 movs r2, #56 ; 0x38 + 800545a: 2100 movs r1, #0 + 800545c: 4620 mov r0, r4 + 800545e: f001 fa37 bl 80068d0 + } + + // Append to the padding the total message's length in bits and transform. + ctx->bitlen += ctx->datalen * 8; + 8005462: 6c23 ldr r3, [r4, #64] ; 0x40 + 8005464: 00d9 lsls r1, r3, #3 + 8005466: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 800546a: 1852 adds r2, r2, r1 + 800546c: f143 0300 adc.w r3, r3, #0 + ctx->data[63] = ctx->bitlen; + ctx->data[62] = ctx->bitlen >> 8; + 8005470: 0a11 lsrs r1, r2, #8 + sha256_transform(ctx, ctx->data); + memset(ctx->data, 0, 56); + } + + // Append to the padding the total message's length in bits and transform. + ctx->bitlen += ctx->datalen * 8; + 8005472: e9c4 2312 strd r2, r3, [r4, #72] ; 0x48 + ctx->data[63] = ctx->bitlen; + 8005476: f884 203f strb.w r2, [r4, #63] ; 0x3f + ctx->data[62] = ctx->bitlen >> 8; + 800547a: f884 103e strb.w r1, [r4, #62] ; 0x3e + ctx->data[61] = ctx->bitlen >> 16; + 800547e: 0c11 lsrs r1, r2, #16 + ctx->data[60] = ctx->bitlen >> 24; + 8005480: 0e12 lsrs r2, r2, #24 + 8005482: f884 203c strb.w r2, [r4, #60] ; 0x3c + ctx->data[59] = ctx->bitlen >> 32; + ctx->data[58] = ctx->bitlen >> 40; + 8005486: 0a1a lsrs r2, r3, #8 + ctx->bitlen += ctx->datalen * 8; + ctx->data[63] = ctx->bitlen; + ctx->data[62] = ctx->bitlen >> 8; + ctx->data[61] = ctx->bitlen >> 16; + ctx->data[60] = ctx->bitlen >> 24; + ctx->data[59] = ctx->bitlen >> 32; + 8005488: f884 303b strb.w r3, [r4, #59] ; 0x3b + ctx->data[58] = ctx->bitlen >> 40; + 800548c: f884 203a strb.w r2, [r4, #58] ; 0x3a + ctx->data[57] = ctx->bitlen >> 48; + 8005490: 0c1a lsrs r2, r3, #16 + ctx->data[56] = ctx->bitlen >> 56; + 8005492: 0e1b lsrs r3, r3, #24 + + // Append to the padding the total message's length in bits and transform. + ctx->bitlen += ctx->datalen * 8; + ctx->data[63] = ctx->bitlen; + ctx->data[62] = ctx->bitlen >> 8; + ctx->data[61] = ctx->bitlen >> 16; + 8005494: f884 103d strb.w r1, [r4, #61] ; 0x3d + ctx->data[60] = ctx->bitlen >> 24; + ctx->data[59] = ctx->bitlen >> 32; + ctx->data[58] = ctx->bitlen >> 40; + ctx->data[57] = ctx->bitlen >> 48; + 8005498: f884 2039 strb.w r2, [r4, #57] ; 0x39 + ctx->data[56] = ctx->bitlen >> 56; + 800549c: f884 3038 strb.w r3, [r4, #56] ; 0x38 + sha256_transform(ctx, ctx->data); + 80054a0: 4621 mov r1, r4 + 80054a2: 4620 mov r0, r4 + 80054a4: f7ff fece bl 8005244 + 80054a8: 2203 movs r2, #3 + + // Since this implementation uses little endian byte ordering and SHA uses big endian, + // reverse all the bytes when copying the final state to the output hash. + for (i = 0; i < 4; ++i) { + hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; + 80054aa: 6d21 ldr r1, [r4, #80] ; 0x50 + 80054ac: 00d3 lsls r3, r2, #3 + 80054ae: 40d9 lsrs r1, r3 + 80054b0: 7029 strb r1, [r5, #0] + hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; + 80054b2: 6d61 ldr r1, [r4, #84] ; 0x54 + 80054b4: 40d9 lsrs r1, r3 + 80054b6: 7129 strb r1, [r5, #4] + hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; + 80054b8: 6da1 ldr r1, [r4, #88] ; 0x58 + 80054ba: 40d9 lsrs r1, r3 + 80054bc: 7229 strb r1, [r5, #8] + hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; + 80054be: 6de1 ldr r1, [r4, #92] ; 0x5c + 80054c0: 40d9 lsrs r1, r3 + 80054c2: 7329 strb r1, [r5, #12] + hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; + 80054c4: 6e21 ldr r1, [r4, #96] ; 0x60 + 80054c6: 40d9 lsrs r1, r3 + 80054c8: 7429 strb r1, [r5, #16] + hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; + 80054ca: 6e61 ldr r1, [r4, #100] ; 0x64 + 80054cc: 40d9 lsrs r1, r3 + 80054ce: 7529 strb r1, [r5, #20] + hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; + 80054d0: 6ea1 ldr r1, [r4, #104] ; 0x68 + 80054d2: 40d9 lsrs r1, r3 + 80054d4: 7629 strb r1, [r5, #24] + hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; + 80054d6: 6ee1 ldr r1, [r4, #108] ; 0x6c + 80054d8: 3a01 subs r2, #1 + 80054da: fa21 f303 lsr.w r3, r1, r3 + 80054de: 772b strb r3, [r5, #28] + ctx->data[56] = ctx->bitlen >> 56; + sha256_transform(ctx, ctx->data); + + // Since this implementation uses little endian byte ordering and SHA uses big endian, + // reverse all the bytes when copying the final state to the output hash. + for (i = 0; i < 4; ++i) { + 80054e0: 1c53 adds r3, r2, #1 + 80054e2: f105 0501 add.w r5, r5, #1 + 80054e6: d1e0 bne.n 80054aa + hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; + hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; + hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; + hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; + } +} + 80054e8: bd38 pop {r3, r4, r5, pc} + +080054ea : + +#if !asm_mult +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + 80054ea: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + ); + +#else /* Thumb-1 */ + uint32_t r4, r5, r6, r7; + + __asm__ volatile ( + 80054ee: 3b01 subs r3, #1 + 80054f0: 009b lsls r3, r3, #2 + 80054f2: 4698 mov r8, r3 + 80054f4: 005b lsls r3, r3, #1 + 80054f6: 4699 mov r9, r3 + 80054f8: 2300 movs r3, #0 + 80054fa: 2400 movs r4, #0 + 80054fc: 2500 movs r5, #0 + 80054fe: 2600 movs r6, #0 + 8005500: b401 push {r0} + 8005502: 2700 movs r7, #0 + 8005504: e002 b.n 800550c + 8005506: 0037 movs r7, r6 + 8005508: 4640 mov r0, r8 + 800550a: 1a3f subs r7, r7, r0 + 800550c: b478 push {r3, r4, r5, r6} + 800550e: 1bf0 subs r0, r6, r7 + 8005510: 5814 ldr r4, [r2, r0] + 8005512: 59c8 ldr r0, [r1, r7] + 8005514: 0c03 lsrs r3, r0, #16 + 8005516: b280 uxth r0, r0 + 8005518: 0c25 lsrs r5, r4, #16 + 800551a: b2a4 uxth r4, r4 + 800551c: 001e movs r6, r3 + 800551e: 436e muls r6, r5 + 8005520: 4363 muls r3, r4 + 8005522: 4345 muls r5, r0 + 8005524: 4360 muls r0, r4 + 8005526: 2400 movs r4, #0 + 8005528: 195b adds r3, r3, r5 + 800552a: 4164 adcs r4, r4 + 800552c: 0424 lsls r4, r4, #16 + 800552e: 1936 adds r6, r6, r4 + 8005530: 041c lsls r4, r3, #16 + 8005532: 0c1b lsrs r3, r3, #16 + 8005534: 1900 adds r0, r0, r4 + 8005536: 415e adcs r6, r3 + 8005538: bc38 pop {r3, r4, r5} + 800553a: 181b adds r3, r3, r0 + 800553c: 4174 adcs r4, r6 + 800553e: 2000 movs r0, #0 + 8005540: 4145 adcs r5, r0 + 8005542: bc40 pop {r6} + 8005544: 3704 adds r7, #4 + 8005546: 4547 cmp r7, r8 + 8005548: dc01 bgt.n 800554e + 800554a: 42b7 cmp r7, r6 + 800554c: ddde ble.n 800550c + 800554e: 9800 ldr r0, [sp, #0] + 8005550: 5183 str r3, [r0, r6] + 8005552: 4623 mov r3, r4 + 8005554: 462c mov r4, r5 + 8005556: 2500 movs r5, #0 + 8005558: 3604 adds r6, #4 + 800555a: 4546 cmp r6, r8 + 800555c: ddd1 ble.n 8005502 + 800555e: 454e cmp r6, r9 + 8005560: ddd1 ble.n 8005506 + 8005562: 5183 str r3, [r0, r6] + 8005564: bc01 pop {r0} + 8005566: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +0800556a : +} + +#if !asm_clear +uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { + wordcount_t i; + for (i = 0; i < num_words; ++i) { + 800556a: 2200 movs r2, #0 +void uECC_set_rng(uECC_RNG_Function rng_function) { + g_rng_function = rng_function; +} + +#if !asm_clear +uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { + 800556c: b510 push {r4, lr} + wordcount_t i; + for (i = 0; i < num_words; ++i) { + vli[i] = 0; + 800556e: 4614 mov r4, r2 +} + +#if !asm_clear +uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { + wordcount_t i; + for (i = 0; i < num_words; ++i) { + 8005570: b253 sxtb r3, r2 + 8005572: 428b cmp r3, r1 + 8005574: da04 bge.n 8005580 + vli[i] = 0; + 8005576: b21b sxth r3, r3 + 8005578: 3201 adds r2, #1 + 800557a: f840 4023 str.w r4, [r0, r3, lsl #2] + 800557e: e7f7 b.n 8005570 + } +} + 8005580: bd10 pop {r4, pc} + +08005582 : +#endif /* !asm_clear */ + +/* Constant-time comparison to zero - secure way to compare long integers */ +/* Returns 1 if vli == 0, 0 otherwise. */ +uECC_VLI_API uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) { + 8005582: b510 push {r4, lr} + uECC_word_t bits = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + 8005584: 2300 movs r3, #0 +#endif /* !asm_clear */ + +/* Constant-time comparison to zero - secure way to compare long integers */ +/* Returns 1 if vli == 0, 0 otherwise. */ +uECC_VLI_API uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) { + uECC_word_t bits = 0; + 8005586: 461a mov r2, r3 + wordcount_t i; + for (i = 0; i < num_words; ++i) { + 8005588: b25c sxtb r4, r3 + 800558a: 428c cmp r4, r1 + 800558c: da04 bge.n 8005598 + bits |= vli[i]; + 800558e: f850 4024 ldr.w r4, [r0, r4, lsl #2] + 8005592: 3301 adds r3, #1 + 8005594: 4322 orrs r2, r4 + 8005596: e7f7 b.n 8005588 + } + return (bits == 0); +} + 8005598: fab2 f082 clz r0, r2 + 800559c: 0940 lsrs r0, r0, #5 + 800559e: bd10 pop {r4, pc} + +080055a0 : + +/* Returns nonzero if bit 'bit' of vli is set. */ +uECC_VLI_API uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) { + return (vli[bit >> uECC_WORD_BITS_SHIFT] & ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); + 80055a0: 114a asrs r2, r1, #5 + 80055a2: 2301 movs r3, #1 + 80055a4: f850 0022 ldr.w r0, [r0, r2, lsl #2] + 80055a8: f001 011f and.w r1, r1, #31 + 80055ac: fa03 f101 lsl.w r1, r3, r1 +} + 80055b0: 4008 ands r0, r1 + 80055b2: 4770 bx lr + +080055b4 : + + return (i + 1); +} + +/* Counts the number of bits required to represent vli. */ +uECC_VLI_API bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words) { + 80055b4: 3901 subs r1, #1 + 80055b6: b2c9 uxtb r1, r1 +/* Counts the number of words in vli. */ +static wordcount_t vli_numDigits(const uECC_word_t *vli, const wordcount_t max_words) { + wordcount_t i; + /* Search from the end until we find a non-zero digit. + We do it in reverse because we expect that most digits will be nonzero. */ + for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { + 80055b8: b24b sxtb r3, r1 + 80055ba: 2b00 cmp r3, #0 + 80055bc: da0b bge.n 80055d6 + } + + return (i + 1); + 80055be: 3101 adds r1, #1 +uECC_VLI_API bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words) { + uECC_word_t i; + uECC_word_t digit; + + wordcount_t num_digits = vli_numDigits(vli, max_words); + if (num_digits == 0) { + 80055c0: f011 03ff ands.w r3, r1, #255 ; 0xff + 80055c4: d015 beq.n 80055f2 + return 0; + } + + digit = vli[num_digits - 1]; + 80055c6: b259 sxtb r1, r3 + 80055c8: f101 4380 add.w r3, r1, #1073741824 ; 0x40000000 + 80055cc: 3b01 subs r3, #1 + 80055ce: f850 2023 ldr.w r2, [r0, r3, lsl #2] + for (i = 0; digit; ++i) { + 80055d2: 2300 movs r3, #0 + 80055d4: e004 b.n 80055e0 +/* Counts the number of words in vli. */ +static wordcount_t vli_numDigits(const uECC_word_t *vli, const wordcount_t max_words) { + wordcount_t i; + /* Search from the end until we find a non-zero digit. + We do it in reverse because we expect that most digits will be nonzero. */ + for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { + 80055d6: f850 3023 ldr.w r3, [r0, r3, lsl #2] + 80055da: 2b00 cmp r3, #0 + 80055dc: d0ea beq.n 80055b4 + 80055de: e7ee b.n 80055be + if (num_digits == 0) { + return 0; + } + + digit = vli[num_digits - 1]; + for (i = 0; digit; ++i) { + 80055e0: b112 cbz r2, 80055e8 + digit >>= 1; + 80055e2: 0852 lsrs r2, r2, #1 + if (num_digits == 0) { + return 0; + } + + digit = vli[num_digits - 1]; + for (i = 0; digit; ++i) { + 80055e4: 3301 adds r3, #1 + 80055e6: e7fb b.n 80055e0 + digit >>= 1; + } + + return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); + 80055e8: 1e48 subs r0, r1, #1 + 80055ea: eb03 1040 add.w r0, r3, r0, lsl #5 + 80055ee: b280 uxth r0, r0 + 80055f0: e000 b.n 80055f4 + uECC_word_t i; + uECC_word_t digit; + + wordcount_t num_digits = vli_numDigits(vli, max_words); + if (num_digits == 0) { + return 0; + 80055f2: 4618 mov r0, r3 + for (i = 0; digit; ++i) { + digit >>= 1; + } + + return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); +} + 80055f4: b200 sxth r0, r0 + 80055f6: 4770 bx lr + +080055f8 : + +/* Sets dest = src. */ +#if !asm_set +uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) { + 80055f8: b530 push {r4, r5, lr} + wordcount_t i; + for (i = 0; i < num_words; ++i) { + 80055fa: 2400 movs r4, #0 + 80055fc: b263 sxtb r3, r4 + 80055fe: 4293 cmp r3, r2 + 8005600: da06 bge.n 8005610 + dest[i] = src[i]; + 8005602: b21b sxth r3, r3 + 8005604: 3401 adds r4, #1 + 8005606: f851 5023 ldr.w r5, [r1, r3, lsl #2] + 800560a: f840 5023 str.w r5, [r0, r3, lsl #2] + 800560e: e7f5 b.n 80055fc + } +} + 8005610: bd30 pop {r4, r5, pc} + +08005612 : +#endif /* !asm_set */ + +/* Returns sign of left - right. */ +static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + 8005612: b510 push {r4, lr} + 8005614: 3a01 subs r2, #1 + 8005616: b2d2 uxtb r2, r2 + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + 8005618: b253 sxtb r3, r2 + 800561a: 2b00 cmp r3, #0 + 800561c: db09 blt.n 8005632 + if (left[i] > right[i]) { + 800561e: b21b sxth r3, r3 + 8005620: f850 4023 ldr.w r4, [r0, r3, lsl #2] + 8005624: f851 3023 ldr.w r3, [r1, r3, lsl #2] + 8005628: 429c cmp r4, r3 + 800562a: d804 bhi.n 8005636 + return 1; + } else if (left[i] < right[i]) { + 800562c: d2f2 bcs.n 8005614 + return -1; + 800562e: 20ff movs r0, #255 ; 0xff + 8005630: e002 b.n 8005638 + } + } + return 0; + 8005632: 2000 movs r0, #0 + 8005634: e000 b.n 8005638 + const uECC_word_t *right, + wordcount_t num_words) { + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + if (left[i] > right[i]) { + return 1; + 8005636: 2001 movs r0, #1 + } else if (left[i] < right[i]) { + return -1; + } + } + return 0; +} + 8005638: b240 sxtb r0, r0 + 800563a: bd10 pop {r4, pc} + +0800563c : + return (!equal - 2 * neg); +} + +/* Computes vli = vli >> 1. */ +#if !asm_rshift1 +uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { + 800563c: eb00 0181 add.w r1, r0, r1, lsl #2 + uECC_word_t *end = vli; + uECC_word_t carry = 0; + 8005640: 2300 movs r3, #0 + + vli += num_words; + while (vli-- > end) { + 8005642: 4288 cmp r0, r1 + 8005644: d206 bcs.n 8005654 + uECC_word_t temp = *vli; + 8005646: f851 2d04 ldr.w r2, [r1, #-4]! + *vli = (temp >> 1) | carry; + 800564a: ea43 0352 orr.w r3, r3, r2, lsr #1 + 800564e: 600b str r3, [r1, #0] + carry = temp << (uECC_WORD_BITS - 1); + 8005650: 07d3 lsls r3, r2, #31 + 8005652: e7f6 b.n 8005642 + } +} + 8005654: 4770 bx lr + ... + +08005658 : +/* Computes result = (left * right) % mod. */ +uECC_VLI_API void uECC_vli_modMult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + 8005658: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 800565c: b0b5 sub sp, #212 ; 0xd4 + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_mult(product, left, right, num_words); + 800565e: ad04 add r5, sp, #16 +/* Computes result = (left * right) % mod. */ +uECC_VLI_API void uECC_vli_modMult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + 8005660: f99d 40f8 ldrsb.w r4, [sp, #248] ; 0xf8 + 8005664: 4699 mov r9, r3 + 8005666: 4680 mov r8, r0 + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_mult(product, left, right, num_words); + 8005668: 4623 mov r3, r4 + 800566a: 4628 mov r0, r5 + 800566c: f7ff ff3d bl 80054ea + uECC_word_t *product, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t mod_multiple[2 * uECC_MAX_WORDS]; + uECC_word_t tmp[2 * uECC_MAX_WORDS]; + uECC_word_t *v[2] = {tmp, product}; + 8005670: ab24 add r3, sp, #144 ; 0x90 + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words); + 8005672: 4621 mov r1, r4 + 8005674: 4648 mov r0, r9 + uECC_word_t *product, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t mod_multiple[2 * uECC_MAX_WORDS]; + uECC_word_t tmp[2 * uECC_MAX_WORDS]; + uECC_word_t *v[2] = {tmp, product}; + 8005676: 9302 str r3, [sp, #8] + 8005678: 9503 str r5, [sp, #12] + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words); + 800567a: f7ff ff9b bl 80055b4 + 800567e: ebc0 1084 rsb r0, r0, r4, lsl #6 + 8005682: b285 uxth r5, r0 + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + 8005684: 4b49 ldr r3, [pc, #292] ; (80057ac ) + uECC_word_t *v[2] = {tmp, product}; + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words); + wordcount_t word_shift = shift / uECC_WORD_BITS; + 8005686: b22a sxth r2, r5 + wordcount_t bit_shift = shift % uECC_WORD_BITS; + 8005688: 4013 ands r3, r2 + 800568a: 2b00 cmp r3, #0 + 800568c: bfbc itt lt + 800568e: f103 33ff addlt.w r3, r3, #4294967295 ; 0xffffffff + 8005692: f063 031f ornlt r3, r3, #31 + uECC_word_t *v[2] = {tmp, product}; + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words); + wordcount_t word_shift = shift / uECC_WORD_BITS; + 8005696: f04f 0720 mov.w r7, #32 + 800569a: fb92 f7f7 sdiv r7, r2, r7 + 800569e: b2ff uxtb r7, r7 + wordcount_t bit_shift = shift % uECC_WORD_BITS; + 80056a0: bfb8 it lt + 80056a2: 3301 addlt r3, #1 + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple, word_shift); + 80056a4: b27f sxtb r7, r7 + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words); + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + 80056a6: b29e uxth r6, r3 + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple, word_shift); + 80056a8: a814 add r0, sp, #80 ; 0x50 + 80056aa: 4639 mov r1, r7 + 80056ac: f7ff ff5d bl 800556a + if (bit_shift > 0) { + 80056b0: b233 sxth r3, r6 + 80056b2: 2b00 cmp r3, #0 + 80056b4: b238 sxth r0, r7 + 80056b6: dd14 ble.n 80056e2 + 80056b8: aa14 add r2, sp, #80 ; 0x50 + 80056ba: 2100 movs r1, #0 + 80056bc: eb02 0080 add.w r0, r2, r0, lsl #2 + for(index = 0; index < (uECC_word_t)num_words; ++index) { + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + 80056c0: f1c3 0720 rsb r7, r3, #32 + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words); + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple, word_shift); + if (bit_shift > 0) { + 80056c4: 460a mov r2, r1 + for(index = 0; index < (uECC_word_t)num_words; ++index) { + 80056c6: 42a2 cmp r2, r4 + 80056c8: d212 bcs.n 80056f0 + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + 80056ca: f859 6022 ldr.w r6, [r9, r2, lsl #2] + 80056ce: fa06 fe03 lsl.w lr, r6, r3 + 80056d2: ea4e 0101 orr.w r1, lr, r1 + 80056d6: f840 1022 str.w r1, [r0, r2, lsl #2] + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + 80056da: fa26 f107 lsr.w r1, r6, r7 + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple, word_shift); + if (bit_shift > 0) { + for(index = 0; index < (uECC_word_t)num_words; ++index) { + 80056de: 3201 adds r2, #1 + 80056e0: e7f1 b.n 80056c6 + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod, num_words); + 80056e2: ab14 add r3, sp, #80 ; 0x50 + 80056e4: 4622 mov r2, r4 + 80056e6: 4649 mov r1, r9 + 80056e8: eb03 0080 add.w r0, r3, r0, lsl #2 + 80056ec: f7ff ff84 bl 80055f8 + 80056f0: b227 sxth r7, r4 + 80056f2: 007b lsls r3, r7, #1 + 80056f4: 9301 str r3, [sp, #4] + v[1 - index][i] = diff; + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + uECC_vli_rshift1(mod_multiple + num_words, num_words); + 80056f6: ab14 add r3, sp, #80 ; 0x50 + 80056f8: eb03 0787 add.w r7, r3, r7, lsl #2 + } + v[1 - index][i] = diff; + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + 80056fc: f104 39ff add.w r9, r4, #4294967295 ; 0xffffffff + 8005700: ab34 add r3, sp, #208 ; 0xd0 + uECC_vli_rshift1(mod_multiple + num_words, num_words); + 8005702: 2601 movs r6, #1 + } + v[1 - index][i] = diff; + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + 8005704: eb03 0989 add.w r9, r3, r9, lsl #2 + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod, num_words); + } + + for (index = 1; shift >= 0; --shift) { + 8005708: 042b lsls r3, r5, #16 + 800570a: d442 bmi.n 8005792 + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + 800570c: ab34 add r3, sp, #208 ; 0xd0 + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod, num_words); + } + + for (index = 1; shift >= 0; --shift) { + 800570e: 2200 movs r2, #0 + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + 8005710: f1c6 0001 rsb r0, r6, #1 + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod, num_words); + } + + for (index = 1; shift >= 0; --shift) { + 8005714: 4696 mov lr, r2 + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + 8005716: eb03 0a86 add.w sl, r3, r6, lsl #2 + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + 800571a: eb03 0080 add.w r0, r3, r0, lsl #2 + } + + for (index = 1; shift >= 0; --shift) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + 800571e: 9b01 ldr r3, [sp, #4] + 8005720: b251 sxtb r1, r2 + 8005722: 4299 cmp r1, r3 + 8005724: da1b bge.n 800575e + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + 8005726: fa0f fc81 sxth.w ip, r1 + 800572a: f85a 3cc8 ldr.w r3, [sl, #-200] + 800572e: f853 b02c ldr.w fp, [r3, ip, lsl #2] + 8005732: ab34 add r3, sp, #208 ; 0xd0 + 8005734: eb03 0181 add.w r1, r3, r1, lsl #2 + 8005738: f851 3c80 ldr.w r3, [r1, #-128] + 800573c: ebc3 030b rsb r3, r3, fp + 8005740: ebce 0303 rsb r3, lr, r3 + if (diff != v[index][i]) { + 8005744: 459b cmp fp, r3 + 8005746: d004 beq.n 8005752 + borrow = (diff > v[index][i]); + 8005748: bf34 ite cc + 800574a: f04f 0e01 movcc.w lr, #1 + 800574e: f04f 0e00 movcs.w lr, #0 + } + v[1 - index][i] = diff; + 8005752: f850 1cc8 ldr.w r1, [r0, #-200] + 8005756: 3201 adds r2, #1 + 8005758: f841 302c str.w r3, [r1, ip, lsl #2] + 800575c: e7df b.n 800571e + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + 800575e: ebce 0206 rsb r2, lr, r6 + 8005762: 4256 negs r6, r2 + uECC_vli_rshift1(mod_multiple, num_words); + 8005764: 4621 mov r1, r4 + 8005766: a814 add r0, sp, #80 ; 0x50 + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + 8005768: 4156 adcs r6, r2 + uECC_vli_rshift1(mod_multiple, num_words); + 800576a: f7ff ff67 bl 800563c + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + 800576e: ab34 add r3, sp, #208 ; 0xd0 + 8005770: eb03 0384 add.w r3, r3, r4, lsl #2 + uECC_vli_rshift1(mod_multiple + num_words, num_words); + 8005774: 4621 mov r1, r4 + } + v[1 - index][i] = diff; + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + 8005776: f853 2c80 ldr.w r2, [r3, #-128] + 800577a: f859 3c80 ldr.w r3, [r9, #-128] + uECC_vli_rshift1(mod_multiple + num_words, num_words); + 800577e: 4638 mov r0, r7 + } + v[1 - index][i] = diff; + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + 8005780: ea43 73c2 orr.w r3, r3, r2, lsl #31 + 8005784: 3d01 subs r5, #1 + 8005786: f849 3c80 str.w r3, [r9, #-128] + 800578a: b2ad uxth r5, r5 + uECC_vli_rshift1(mod_multiple + num_words, num_words); + 800578c: f7ff ff56 bl 800563c + 8005790: e7ba b.n 8005708 + } + uECC_vli_set(result, v[index], num_words); + 8005792: ab34 add r3, sp, #208 ; 0xd0 + 8005794: eb03 0686 add.w r6, r3, r6, lsl #2 + 8005798: 4622 mov r2, r4 + 800579a: f856 1cc8 ldr.w r1, [r6, #-200] + 800579e: 4640 mov r0, r8 + 80057a0: f7ff ff2a bl 80055f8 + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_mult(product, left, right, num_words); + uECC_vli_mmod(result, product, mod, num_words); +} + 80057a4: b035 add sp, #212 ; 0xd4 + 80057a6: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 80057aa: bf00 nop + 80057ac: 8000001f .word 0x8000001f + +080057b0 : + +uECC_VLI_API void uECC_vli_modMult_fast(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + uECC_Curve curve) { + 80057b0: b530 push {r4, r5, lr} + 80057b2: 461c mov r4, r3 + 80057b4: b091 sub sp, #68 ; 0x44 + 80057b6: 4605 mov r5, r0 + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_mult(product, left, right, curve->num_words); + 80057b8: f993 3000 ldrsb.w r3, [r3] + 80057bc: 4668 mov r0, sp + 80057be: f7ff fe94 bl 80054ea +#if (uECC_OPTIMIZATION_LEVEL > 0) + curve->mmod_fast(result, product); + 80057c2: f8d4 30b0 ldr.w r3, [r4, #176] ; 0xb0 + 80057c6: 4669 mov r1, sp + 80057c8: 4628 mov r0, r5 + 80057ca: 4798 blx r3 +#else + uECC_vli_mmod(result, product, curve->p, curve->num_words); +#endif +} + 80057cc: b011 add sp, #68 ; 0x44 + 80057ce: bd30 pop {r4, r5, pc} + +080057d0 : +#endif /* uECC_ENABLE_VLI_API */ + +uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result, + const uECC_word_t *left, + uECC_Curve curve) { + uECC_vli_modMult_fast(result, left, left, curve); + 80057d0: 4613 mov r3, r2 + 80057d2: 460a mov r2, r1 + 80057d4: f7ff bfec b.w 80057b0 + +080057d8 : + +/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */ +static void apply_z(uECC_word_t * X1, + uECC_word_t * Y1, + const uECC_word_t * const Z, + uECC_Curve curve) { + 80057d8: b5f0 push {r4, r5, r6, r7, lr} + 80057da: 4615 mov r5, r2 + 80057dc: b089 sub sp, #36 ; 0x24 + 80057de: 461c mov r4, r3 + 80057e0: 4607 mov r7, r0 + 80057e2: 460e mov r6, r1 + uECC_word_t t1[uECC_MAX_WORDS]; + + uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */ + 80057e4: 461a mov r2, r3 + 80057e6: 4629 mov r1, r5 + 80057e8: 4668 mov r0, sp + 80057ea: f7ff fff1 bl 80057d0 + uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ + 80057ee: 4623 mov r3, r4 + 80057f0: 466a mov r2, sp + 80057f2: 4639 mov r1, r7 + 80057f4: 4638 mov r0, r7 + 80057f6: f7ff ffdb bl 80057b0 + uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ + 80057fa: 4623 mov r3, r4 + 80057fc: 462a mov r2, r5 + 80057fe: 4669 mov r1, sp + 8005800: 4668 mov r0, sp + 8005802: f7ff ffd5 bl 80057b0 + uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ + 8005806: 4623 mov r3, r4 + 8005808: 466a mov r2, sp + 800580a: 4631 mov r1, r6 + 800580c: 4630 mov r0, r6 + 800580e: f7ff ffcf bl 80057b0 +} + 8005812: b009 add sp, #36 ; 0x24 + 8005814: bdf0 pop {r4, r5, r6, r7, pc} + +08005816 : + +#else + +uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, + int num_bytes, + const uECC_word_t *native) { + 8005816: b5f0 push {r4, r5, r6, r7, lr} + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + 8005818: 2500 movs r5, #0 + unsigned b = num_bytes - 1 - i; + 800581a: 1e4f subs r7, r1, #1 + +uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, + int num_bytes, + const uECC_word_t *native) { + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + 800581c: b26c sxtb r4, r5 + 800581e: 428c cmp r4, r1 + 8005820: f105 0501 add.w r5, r5, #1 + 8005824: da0a bge.n 800583c + unsigned b = num_bytes - 1 - i; + 8005826: 1b3b subs r3, r7, r4 + bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); + 8005828: 089e lsrs r6, r3, #2 + 800582a: f003 0303 and.w r3, r3, #3 + 800582e: f852 6026 ldr.w r6, [r2, r6, lsl #2] + 8005832: 00db lsls r3, r3, #3 + 8005834: fa26 f303 lsr.w r3, r6, r3 + 8005838: 5503 strb r3, [r0, r4] + 800583a: e7ef b.n 800581c + } +} + 800583c: bdf0 pop {r4, r5, r6, r7, pc} + +0800583e : + +uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, + const uint8_t *bytes, + int num_bytes) { + 800583e: b5f8 push {r3, r4, r5, r6, r7, lr} + 8005840: 4616 mov r6, r2 + wordcount_t i; + uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + 8005842: 1cd3 adds r3, r2, #3 + } +} + +uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, + const uint8_t *bytes, + int num_bytes) { + 8005844: 460d mov r5, r1 + wordcount_t i; + uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + 8005846: 2104 movs r1, #4 + 8005848: fb93 f1f1 sdiv r1, r3, r1 + 800584c: b249 sxtb r1, r1 + } +} + +uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, + const uint8_t *bytes, + int num_bytes) { + 800584e: 4604 mov r4, r0 + wordcount_t i; + uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + 8005850: 1e77 subs r7, r6, #1 + +uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, + const uint8_t *bytes, + int num_bytes) { + wordcount_t i; + uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + 8005852: f7ff fe8a bl 800556a + for (i = 0; i < num_bytes; ++i) { + 8005856: 2200 movs r2, #0 + 8005858: b251 sxtb r1, r2 + 800585a: 428e cmp r6, r1 + 800585c: f102 0201 add.w r2, r2, #1 + 8005860: dd0d ble.n 800587e + unsigned b = num_bytes - 1 - i; + 8005862: 1a7b subs r3, r7, r1 + native[b / uECC_WORD_SIZE] |= + 8005864: 0898 lsrs r0, r3, #2 + 8005866: 5c69 ldrb r1, [r5, r1] + 8005868: f003 0303 and.w r3, r3, #3 + 800586c: 00db lsls r3, r3, #3 + 800586e: fa01 f303 lsl.w r3, r1, r3 + 8005872: f854 1020 ldr.w r1, [r4, r0, lsl #2] + 8005876: 430b orrs r3, r1 + 8005878: f844 3020 str.w r3, [r4, r0, lsl #2] + 800587c: e7ec b.n 8005858 + (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); + } +} + 800587e: bdf8 pop {r3, r4, r5, r6, r7, pc} + +08005880 : + #define RESUME_SYNTAX ".syntax divided \n\t" +#endif + +#if (uECC_OPTIMIZATION_LEVEL >= 2) + +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + 8005880: b530 push {r4, r5, lr} +#endif + uint32_t carry; + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + 8005882: 4603 mov r3, r0 + 8005884: 2000 movs r0, #0 + 8005886: c910 ldmia r1!, {r4} + 8005888: ca20 ldmia r2!, {r5} + 800588a: 1964 adds r4, r4, r5 + 800588c: c310 stmia r3!, {r4} + 800588e: c910 ldmia r1!, {r4} + 8005890: ca20 ldmia r2!, {r5} + 8005892: 416c adcs r4, r5 + 8005894: c310 stmia r3!, {r4} + 8005896: c910 ldmia r1!, {r4} + 8005898: ca20 ldmia r2!, {r5} + 800589a: 416c adcs r4, r5 + 800589c: c310 stmia r3!, {r4} + 800589e: c910 ldmia r1!, {r4} + 80058a0: ca20 ldmia r2!, {r5} + 80058a2: 416c adcs r4, r5 + 80058a4: c310 stmia r3!, {r4} + 80058a6: c910 ldmia r1!, {r4} + 80058a8: ca20 ldmia r2!, {r5} + 80058aa: 416c adcs r4, r5 + 80058ac: c310 stmia r3!, {r4} + 80058ae: c910 ldmia r1!, {r4} + 80058b0: ca20 ldmia r2!, {r5} + 80058b2: 416c adcs r4, r5 + 80058b4: c310 stmia r3!, {r4} + 80058b6: c910 ldmia r1!, {r4} + 80058b8: ca20 ldmia r2!, {r5} + 80058ba: 416c adcs r4, r5 + 80058bc: c310 stmia r3!, {r4} + 80058be: c910 ldmia r1!, {r4} + 80058c0: ca20 ldmia r2!, {r5} + 80058c2: 416c adcs r4, r5 + 80058c4: c310 stmia r3!, {r4} + 80058c6: 4140 adcs r0, r0 + [right] REG_WRITE_LO (right_word) + : + : "cc", "memory" + ); + return carry; +} + 80058c8: bd30 pop {r4, r5, pc} + +080058ca : + +#if uECC_SUPPORT_COMPRESSED_POINT +#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ + uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1 +/* Compute a = sqrt(a) (mod curve_p). */ +static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { + 80058ca: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 80058ce: b090 sub sp, #64 ; 0x40 + 80058d0: 460e mov r6, r1 + bitcount_t i; + uECC_word_t p1[uECC_MAX_WORDS] = {1}; + 80058d2: 2220 movs r2, #32 + 80058d4: 2100 movs r1, #0 + +#if uECC_SUPPORT_COMPRESSED_POINT +#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ + uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1 +/* Compute a = sqrt(a) (mod curve_p). */ +static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { + 80058d6: 4607 mov r7, r0 + bitcount_t i; + uECC_word_t p1[uECC_MAX_WORDS] = {1}; + 80058d8: 4668 mov r0, sp + 80058da: f000 fff9 bl 80068d0 + uECC_word_t l_result[uECC_MAX_WORDS] = {1}; + 80058de: 2220 movs r2, #32 +#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ + uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1 +/* Compute a = sqrt(a) (mod curve_p). */ +static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { + bitcount_t i; + uECC_word_t p1[uECC_MAX_WORDS] = {1}; + 80058e0: 2401 movs r4, #1 + uECC_word_t l_result[uECC_MAX_WORDS] = {1}; + 80058e2: 2100 movs r1, #0 + 80058e4: eb0d 0002 add.w r0, sp, r2 +#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ + uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1 +/* Compute a = sqrt(a) (mod curve_p). */ +static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { + bitcount_t i; + uECC_word_t p1[uECC_MAX_WORDS] = {1}; + 80058e8: 9400 str r4, [sp, #0] + uECC_word_t l_result[uECC_MAX_WORDS] = {1}; + 80058ea: f000 fff1 bl 80068d0 + wordcount_t num_words = curve->num_words; + 80058ee: 4631 mov r1, r6 + + /* When curve->p == 3 (mod 4), we can compute + sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */ + uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */ + 80058f0: 466a mov r2, sp +/* Compute a = sqrt(a) (mod curve_p). */ +static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { + bitcount_t i; + uECC_word_t p1[uECC_MAX_WORDS] = {1}; + uECC_word_t l_result[uECC_MAX_WORDS] = {1}; + wordcount_t num_words = curve->num_words; + 80058f2: f811 5b04 ldrb.w r5, [r1], #4 + uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1 +/* Compute a = sqrt(a) (mod curve_p). */ +static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { + bitcount_t i; + uECC_word_t p1[uECC_MAX_WORDS] = {1}; + uECC_word_t l_result[uECC_MAX_WORDS] = {1}; + 80058f6: 9408 str r4, [sp, #32] + wordcount_t num_words = curve->num_words; + + /* When curve->p == 3 (mod 4), we can compute + sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */ + uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */ + 80058f8: 4668 mov r0, sp + for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) { + 80058fa: b26d sxtb r5, r5 + uECC_word_t l_result[uECC_MAX_WORDS] = {1}; + wordcount_t num_words = curve->num_words; + + /* When curve->p == 3 (mod 4), we can compute + sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */ + uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */ + 80058fc: f7ff ffc0 bl 8005880 + for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) { + 8005900: 4629 mov r1, r5 + 8005902: 4668 mov r0, sp + 8005904: f7ff fe56 bl 80055b4 + 8005908: 3801 subs r0, #1 + 800590a: b284 uxth r4, r0 + 800590c: fa0f f884 sxth.w r8, r4 + 8005910: f1b8 0f01 cmp.w r8, #1 + 8005914: dd12 ble.n 800593c + uECC_vli_modSquare_fast(l_result, l_result, curve); + 8005916: a908 add r1, sp, #32 + 8005918: 4608 mov r0, r1 + 800591a: 4632 mov r2, r6 + 800591c: f7ff ff58 bl 80057d0 + if (uECC_vli_testBit(p1, i)) { + 8005920: 4641 mov r1, r8 + 8005922: 4668 mov r0, sp + 8005924: f7ff fe3c bl 80055a0 + 8005928: b128 cbz r0, 8005936 + uECC_vli_modMult_fast(l_result, l_result, a, curve); + 800592a: a908 add r1, sp, #32 + 800592c: 4633 mov r3, r6 + 800592e: 463a mov r2, r7 + 8005930: 4608 mov r0, r1 + 8005932: f7ff ff3d bl 80057b0 + 8005936: 3c01 subs r4, #1 + 8005938: b2a4 uxth r4, r4 + 800593a: e7e7 b.n 800590c + } + } + uECC_vli_set(a, l_result, num_words); + 800593c: 462a mov r2, r5 + 800593e: a908 add r1, sp, #32 + 8005940: 4638 mov r0, r7 + 8005942: f7ff fe59 bl 80055f8 +} + 8005946: b010 add sp, #64 ; 0x40 + 8005948: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +0800594c : + /* add the 2^32 multiple */ + result[4 + num_words_secp256k1] = + uECC_vli_add(result + 4, result + 4, right, num_words_secp256k1); +} +#elif uECC_WORD_SIZE == 4 +static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) { + 800594c: b5f8 push {r3, r4, r5, r6, r7, lr} + 800594e: 460a mov r2, r1 + 8005950: 4604 mov r4, r0 + 8005952: 1f0d subs r5, r1, #4 + 8005954: 1f06 subs r6, r0, #4 + 8005956: f101 071c add.w r7, r1, #28 + /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + uint32_t carry = 0; + 800595a: 2300 movs r3, #0 + wordcount_t k; + + for (k = 0; k < num_words_secp256k1; ++k) { + uint64_t p = (uint64_t)0x3D1 * right[k] + carry; + 800595c: f240 3ed1 movw lr, #977 ; 0x3d1 + 8005960: f855 cf04 ldr.w ip, [r5, #4]! + 8005964: 4618 mov r0, r3 + 8005966: 2100 movs r1, #0 + 8005968: fbee 010c umlal r0, r1, lr, ip +static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) { + /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + uint32_t carry = 0; + wordcount_t k; + + for (k = 0; k < num_words_secp256k1; ++k) { + 800596c: 42af cmp r7, r5 + uint64_t p = (uint64_t)0x3D1 * right[k] + carry; + result[k] = p; + 800596e: f846 0f04 str.w r0, [r6, #4]! + carry = p >> 32; + 8005972: 460b mov r3, r1 +static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) { + /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + uint32_t carry = 0; + wordcount_t k; + + for (k = 0; k < num_words_secp256k1; ++k) { + 8005974: d1f4 bne.n 8005960 + uint64_t p = (uint64_t)0x3D1 * right[k] + carry; + result[k] = p; + carry = p >> 32; + } + result[num_words_secp256k1] = carry; + 8005976: 6221 str r1, [r4, #32] + /* add the 2^32 multiple */ + result[1 + num_words_secp256k1] = + uECC_vli_add(result + 1, result + 1, right, num_words_secp256k1); + 8005978: 1d21 adds r1, r4, #4 + 800597a: 4608 mov r0, r1 + 800597c: f7ff ff80 bl 8005880 + result[k] = p; + carry = p >> 32; + } + result[num_words_secp256k1] = carry; + /* add the 2^32 multiple */ + result[1 + num_words_secp256k1] = + 8005980: 6260 str r0, [r4, #36] ; 0x24 + 8005982: bdf8 pop {r3, r4, r5, r6, r7, pc} + +08005984 : +} + +static uECC_word_t regularize_k(const uECC_word_t * const k, + uECC_word_t *k0, + uECC_word_t *k1, + uECC_Curve curve) { + 8005984: b5f8 push {r3, r4, r5, r6, r7, lr} + 8005986: 460e mov r6, r1 + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + 8005988: f103 0524 add.w r5, r3, #36 ; 0x24 +} + +static uECC_word_t regularize_k(const uECC_word_t * const k, + uECC_word_t *k0, + uECC_word_t *k1, + uECC_Curve curve) { + 800598c: 4617 mov r7, r2 + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + 800598e: 4601 mov r1, r0 + 8005990: 462a mov r2, r5 + 8005992: 4630 mov r0, r6 + +static uECC_word_t regularize_k(const uECC_word_t * const k, + uECC_word_t *k0, + uECC_word_t *k1, + uECC_Curve curve) { + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + 8005994: 885c ldrh r4, [r3, #2] + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + 8005996: f7ff ff73 bl 8005880 + 800599a: b980 cbnz r0, 80059be + +static uECC_word_t regularize_k(const uECC_word_t * const k, + uECC_word_t *k0, + uECC_word_t *k1, + uECC_Curve curve) { + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + 800599c: b221 sxth r1, r4 + 800599e: f101 031f add.w r3, r1, #31 + 80059a2: 2220 movs r2, #32 + 80059a4: fb93 f3f2 sdiv r3, r3, r2 + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + 80059a8: b25b sxtb r3, r3 + 80059aa: ebb1 1f43 cmp.w r1, r3, lsl #5 + 80059ae: da08 bge.n 80059c2 + (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && + uECC_vli_testBit(k0, num_n_bits)); + 80059b0: 4630 mov r0, r6 + 80059b2: f7ff fdf5 bl 80055a0 + uECC_word_t *k0, + uECC_word_t *k1, + uECC_Curve curve) { + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + 80059b6: 1c04 adds r4, r0, #0 + 80059b8: bf18 it ne + 80059ba: 2401 movne r4, #1 + 80059bc: e002 b.n 80059c4 + 80059be: 2401 movs r4, #1 + 80059c0: e000 b.n 80059c4 + 80059c2: 4604 mov r4, r0 + (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && + uECC_vli_testBit(k0, num_n_bits)); + uECC_vli_add(k1, k0, curve->n, num_n_words); + 80059c4: 462a mov r2, r5 + 80059c6: 4631 mov r1, r6 + 80059c8: 4638 mov r0, r7 + 80059ca: f7ff ff59 bl 8005880 + return carry; +} + 80059ce: 4620 mov r0, r4 + 80059d0: bdf8 pop {r3, r4, r5, r6, r7, pc} + +080059d2 : +#define asm_add 1 + +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + 80059d2: b530 push {r4, r5, lr} +#endif + uint32_t carry; + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + 80059d4: 2300 movs r3, #0 + 80059d6: c910 ldmia r1!, {r4} + 80059d8: ca20 ldmia r2!, {r5} + 80059da: 1b64 subs r4, r4, r5 + 80059dc: c010 stmia r0!, {r4} + 80059de: c910 ldmia r1!, {r4} + 80059e0: ca20 ldmia r2!, {r5} + 80059e2: 41ac sbcs r4, r5 + 80059e4: c010 stmia r0!, {r4} + 80059e6: c910 ldmia r1!, {r4} + 80059e8: ca20 ldmia r2!, {r5} + 80059ea: 41ac sbcs r4, r5 + 80059ec: c010 stmia r0!, {r4} + 80059ee: c910 ldmia r1!, {r4} + 80059f0: ca20 ldmia r2!, {r5} + 80059f2: 41ac sbcs r4, r5 + 80059f4: c010 stmia r0!, {r4} + 80059f6: c910 ldmia r1!, {r4} + 80059f8: ca20 ldmia r2!, {r5} + 80059fa: 41ac sbcs r4, r5 + 80059fc: c010 stmia r0!, {r4} + 80059fe: c910 ldmia r1!, {r4} + 8005a00: ca20 ldmia r2!, {r5} + 8005a02: 41ac sbcs r4, r5 + 8005a04: c010 stmia r0!, {r4} + 8005a06: c910 ldmia r1!, {r4} + 8005a08: ca20 ldmia r2!, {r5} + 8005a0a: 41ac sbcs r4, r5 + 8005a0c: c010 stmia r0!, {r4} + 8005a0e: c910 ldmia r1!, {r4} + 8005a10: ca20 ldmia r2!, {r5} + 8005a12: 41ac sbcs r4, r5 + 8005a14: c010 stmia r0!, {r4} + 8005a16: 415b adcs r3, r3 + : + : "cc", "memory" + ); + return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting + (for some reason...) */ +} + 8005a18: fab3 f083 clz r0, r3 + 8005a1c: 0940 lsrs r0, r0, #5 + 8005a1e: bd30 pop {r4, r5, pc} + +08005a20 : + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +uECC_VLI_API void uECC_vli_modAdd(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + 8005a20: b570 push {r4, r5, r6, lr} + 8005a22: 4604 mov r4, r0 + 8005a24: 461d mov r5, r3 + 8005a26: f99d 6010 ldrsb.w r6, [sp, #16] + uECC_word_t carry = uECC_vli_add(result, left, right, num_words); + 8005a2a: f7ff ff29 bl 8005880 + if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { + 8005a2e: b930 cbnz r0, 8005a3e + 8005a30: 4632 mov r2, r6 + 8005a32: 4621 mov r1, r4 + 8005a34: 4628 mov r0, r5 + 8005a36: f7ff fdec bl 8005612 + 8005a3a: 2801 cmp r0, #1 + 8005a3c: d006 beq.n 8005a4c + /* result > mod (result = mod + remainder), so subtract mod to get remainder. */ + uECC_vli_sub(result, result, mod, num_words); + 8005a3e: 462a mov r2, r5 + 8005a40: 4621 mov r1, r4 + 8005a42: 4620 mov r0, r4 + } +} + 8005a44: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t carry = uECC_vli_add(result, left, right, num_words); + if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { + /* result > mod (result = mod + remainder), so subtract mod to get remainder. */ + uECC_vli_sub(result, result, mod, num_words); + 8005a48: f7ff bfc3 b.w 80059d2 + 8005a4c: bd70 pop {r4, r5, r6, pc} + +08005a4e : + uECC_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */ + uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */ +} + +/* Computes result = x^3 + b. result must not overlap x. */ +static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) { + 8005a4e: b573 push {r0, r1, r4, r5, r6, lr} + 8005a50: 4604 mov r4, r0 + 8005a52: 4615 mov r5, r2 + 8005a54: 460e mov r6, r1 + uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ + 8005a56: f7ff febb bl 80057d0 + uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 */ + 8005a5a: 462b mov r3, r5 + 8005a5c: 4632 mov r2, r6 + 8005a5e: 4621 mov r1, r4 + 8005a60: 4620 mov r0, r4 + 8005a62: f7ff fea5 bl 80057b0 + uECC_vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */ + 8005a66: 2308 movs r3, #8 + 8005a68: 9300 str r3, [sp, #0] + 8005a6a: f105 0284 add.w r2, r5, #132 ; 0x84 + 8005a6e: 1d2b adds r3, r5, #4 + 8005a70: 4621 mov r1, r4 + 8005a72: 4620 mov r0, r4 + 8005a74: f7ff ffd4 bl 8005a20 +} + 8005a78: b002 add sp, #8 + 8005a7a: bd70 pop {r4, r5, r6, pc} + +08005a7c : + +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right); +static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { + 8005a7c: b570 push {r4, r5, r6, lr} + 8005a7e: b090 sub sp, #64 ; 0x40 + 8005a80: 460e mov r6, r1 + 8005a82: 4604 mov r4, r0 + uECC_word_t tmp[2 * num_words_secp256k1]; + uECC_word_t carry; + + uECC_vli_clear(tmp, num_words_secp256k1); + 8005a84: 2108 movs r1, #8 + 8005a86: 4668 mov r0, sp + 8005a88: f7ff fd6f bl 800556a + uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1); + 8005a8c: 2108 movs r1, #8 + 8005a8e: a808 add r0, sp, #32 + 8005a90: f7ff fd6b bl 800556a + + omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */ + 8005a94: f106 0120 add.w r1, r6, #32 + 8005a98: 4668 mov r0, sp + 8005a9a: f7ff ff57 bl 800594c + + carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q */ + 8005a9e: 466a mov r2, sp + 8005aa0: 4631 mov r1, r6 + 8005aa2: 4620 mov r0, r4 + 8005aa4: f7ff feec bl 8005880 + uECC_vli_clear(product, num_words_secp256k1); + 8005aa8: 2108 movs r1, #8 + uECC_vli_clear(tmp, num_words_secp256k1); + uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1); + + omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */ + + carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q */ + 8005aaa: 4605 mov r5, r0 + uECC_vli_clear(product, num_words_secp256k1); + 8005aac: 4630 mov r0, r6 + 8005aae: f7ff fd5c bl 800556a + omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */ + 8005ab2: a908 add r1, sp, #32 + 8005ab4: 4630 mov r0, r6 + 8005ab6: f7ff ff49 bl 800594c + carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */ + 8005aba: 4632 mov r2, r6 + 8005abc: 4621 mov r1, r4 + 8005abe: 4620 mov r0, r4 + 8005ac0: f7ff fede bl 8005880 + 8005ac4: 4405 add r5, r0 + + while (carry > 0) { + 8005ac6: b135 cbz r5, 8005ad6 + --carry; + uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); + 8005ac8: 4a0a ldr r2, [pc, #40] ; (8005af4 ) + 8005aca: 4621 mov r1, r4 + 8005acc: 4620 mov r0, r4 + uECC_vli_clear(product, num_words_secp256k1); + omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */ + carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */ + + while (carry > 0) { + --carry; + 8005ace: 3d01 subs r5, #1 + uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); + 8005ad0: f7ff ff7f bl 80059d2 + 8005ad4: e7f7 b.n 8005ac6 + } + if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) > 0) { + 8005ad6: 2208 movs r2, #8 + 8005ad8: 4906 ldr r1, [pc, #24] ; (8005af4 ) + 8005ada: 4620 mov r0, r4 + 8005adc: f7ff fd99 bl 8005612 + 8005ae0: 2800 cmp r0, #0 + 8005ae2: dd04 ble.n 8005aee + uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); + 8005ae4: 4a03 ldr r2, [pc, #12] ; (8005af4 ) + 8005ae6: 4621 mov r1, r4 + 8005ae8: 4620 mov r0, r4 + 8005aea: f7ff ff72 bl 80059d2 + } +} + 8005aee: b010 add sp, #64 ; 0x40 + 8005af0: bd70 pop {r4, r5, r6, pc} + 8005af2: bf00 nop + 8005af4: 080074b8 .word 0x080074b8 + +08005af8 : + } +} + +/* Computes result = (left - right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +uECC_VLI_API void uECC_vli_modSub(uECC_word_t *result, + 8005af8: b538 push {r3, r4, r5, lr} + 8005afa: 4604 mov r4, r0 + 8005afc: 461d mov r5, r3 + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); + 8005afe: f7ff ff68 bl 80059d2 + if (l_borrow) { + 8005b02: b130 cbz r0, 8005b12 + /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, + we can get the correct result from result + mod (with overflow). */ + uECC_vli_add(result, result, mod, num_words); + 8005b04: 462a mov r2, r5 + 8005b06: 4621 mov r1, r4 + 8005b08: 4620 mov r0, r4 + } +} + 8005b0a: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} + wordcount_t num_words) { + uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); + if (l_borrow) { + /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, + we can get the correct result from result + mod (with overflow). */ + uECC_vli_add(result, result, mod, num_words); + 8005b0e: f7ff beb7 b.w 8005880 + 8005b12: bd38 pop {r3, r4, r5, pc} + +08005b14 : +*/ +static void XYcZ_add(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + uECC_Curve curve) { + 8005b14: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 8005b18: b089 sub sp, #36 ; 0x24 + 8005b1a: 4614 mov r4, r2 + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + 8005b1c: 9d10 ldr r5, [sp, #64] ; 0x40 + 8005b1e: f815 9b04 ldrb.w r9, [r5], #4 +*/ +static void XYcZ_add(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + uECC_Curve curve) { + 8005b22: 461e mov r6, r3 + 8005b24: 4607 mov r7, r0 + 8005b26: 4688 mov r8, r1 + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + 8005b28: 462b mov r3, r5 + 8005b2a: 4602 mov r2, r0 + 8005b2c: 4621 mov r1, r4 + 8005b2e: 4668 mov r0, sp + 8005b30: f7ff ffe2 bl 8005af8 + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + 8005b34: 9a10 ldr r2, [sp, #64] ; 0x40 + 8005b36: 4669 mov r1, sp + 8005b38: 4668 mov r0, sp + 8005b3a: f7ff fe49 bl 80057d0 + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + 8005b3e: 9b10 ldr r3, [sp, #64] ; 0x40 + 8005b40: 466a mov r2, sp + 8005b42: 4639 mov r1, r7 + 8005b44: 4638 mov r0, r7 + 8005b46: f7ff fe33 bl 80057b0 + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + 8005b4a: 9b10 ldr r3, [sp, #64] ; 0x40 + 8005b4c: 466a mov r2, sp + 8005b4e: 4621 mov r1, r4 + 8005b50: 4620 mov r0, r4 + 8005b52: f7ff fe2d bl 80057b0 + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + 8005b56: 462b mov r3, r5 + 8005b58: 4642 mov r2, r8 + 8005b5a: 4631 mov r1, r6 + 8005b5c: 4630 mov r0, r6 + 8005b5e: f7ff ffcb bl 8005af8 + uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ + 8005b62: 9a10 ldr r2, [sp, #64] ; 0x40 + 8005b64: 4631 mov r1, r6 + 8005b66: 4668 mov r0, sp + 8005b68: f7ff fe32 bl 80057d0 + + uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ + 8005b6c: 462b mov r3, r5 + 8005b6e: 463a mov r2, r7 + 8005b70: 4669 mov r1, sp + 8005b72: 4668 mov r0, sp + 8005b74: f7ff ffc0 bl 8005af8 + uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ + 8005b78: 462b mov r3, r5 + 8005b7a: 4622 mov r2, r4 + 8005b7c: 4669 mov r1, sp + 8005b7e: 4668 mov r0, sp + 8005b80: f7ff ffba bl 8005af8 + uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ + 8005b84: 462b mov r3, r5 + 8005b86: 463a mov r2, r7 + 8005b88: 4621 mov r1, r4 + 8005b8a: 4620 mov r0, r4 + 8005b8c: f7ff ffb4 bl 8005af8 + uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ + 8005b90: 9b10 ldr r3, [sp, #64] ; 0x40 + 8005b92: 4622 mov r2, r4 + 8005b94: 4641 mov r1, r8 + 8005b96: 4640 mov r0, r8 + 8005b98: f7ff fe0a bl 80057b0 + uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ + 8005b9c: 462b mov r3, r5 + 8005b9e: 466a mov r2, sp + 8005ba0: 4639 mov r1, r7 + 8005ba2: 4620 mov r0, r4 + 8005ba4: f7ff ffa8 bl 8005af8 + uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ + 8005ba8: 9b10 ldr r3, [sp, #64] ; 0x40 + 8005baa: 4622 mov r2, r4 + 8005bac: 4631 mov r1, r6 + 8005bae: 4630 mov r0, r6 + 8005bb0: f7ff fdfe bl 80057b0 + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ + 8005bb4: 462b mov r3, r5 + 8005bb6: 4642 mov r2, r8 + 8005bb8: 4631 mov r1, r6 + 8005bba: 4630 mov r0, r6 + 8005bbc: f7ff ff9c bl 8005af8 + + uECC_vli_set(X2, t5, num_words); + 8005bc0: fa4f f289 sxtb.w r2, r9 + 8005bc4: 4669 mov r1, sp + 8005bc6: 4620 mov r0, r4 + 8005bc8: f7ff fd16 bl 80055f8 +} + 8005bcc: b009 add sp, #36 ; 0x24 + 8005bce: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +08005bd2 : +*/ +static void XYcZ_addC(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + uECC_Curve curve) { + 8005bd2: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 8005bd6: b09b sub sp, #108 ; 0x6c + 8005bd8: 4615 mov r5, r2 + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[uECC_MAX_WORDS]; + uECC_word_t t6[uECC_MAX_WORDS]; + uECC_word_t t7[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + 8005bda: 9c22 ldr r4, [sp, #136] ; 0x88 + 8005bdc: f814 9b04 ldrb.w r9, [r4], #4 +*/ +static void XYcZ_addC(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + uECC_Curve curve) { + 8005be0: 461f mov r7, r3 + 8005be2: 4606 mov r6, r0 + 8005be4: 4688 mov r8, r1 + uECC_word_t t5[uECC_MAX_WORDS]; + uECC_word_t t6[uECC_MAX_WORDS]; + uECC_word_t t7[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + 8005be6: 4623 mov r3, r4 + 8005be8: 4602 mov r2, r0 + 8005bea: 4629 mov r1, r5 + 8005bec: a802 add r0, sp, #8 + 8005bee: f7ff ff83 bl 8005af8 + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + 8005bf2: a902 add r1, sp, #8 + 8005bf4: 9a22 ldr r2, [sp, #136] ; 0x88 + 8005bf6: 4608 mov r0, r1 + 8005bf8: f7ff fdea bl 80057d0 + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + 8005bfc: 9b22 ldr r3, [sp, #136] ; 0x88 + 8005bfe: aa02 add r2, sp, #8 + 8005c00: 4631 mov r1, r6 + 8005c02: 4630 mov r0, r6 + 8005c04: f7ff fdd4 bl 80057b0 + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ + 8005c08: fa4f f989 sxtb.w r9, r9 + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + 8005c0c: 9b22 ldr r3, [sp, #136] ; 0x88 + 8005c0e: aa02 add r2, sp, #8 + 8005c10: 4629 mov r1, r5 + 8005c12: 4628 mov r0, r5 + 8005c14: f7ff fdcc bl 80057b0 + uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ + 8005c18: 4623 mov r3, r4 + 8005c1a: 4642 mov r2, r8 + 8005c1c: 4639 mov r1, r7 + 8005c1e: a802 add r0, sp, #8 + 8005c20: f8cd 9000 str.w r9, [sp] + 8005c24: f7ff fefc bl 8005a20 + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + 8005c28: 4623 mov r3, r4 + 8005c2a: 4642 mov r2, r8 + 8005c2c: 4639 mov r1, r7 + 8005c2e: 4638 mov r0, r7 + 8005c30: f7ff ff62 bl 8005af8 + + uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ + 8005c34: 4623 mov r3, r4 + 8005c36: 4632 mov r2, r6 + 8005c38: 4629 mov r1, r5 + 8005c3a: a80a add r0, sp, #40 ; 0x28 + 8005c3c: f7ff ff5c bl 8005af8 + uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */ + 8005c40: 9b22 ldr r3, [sp, #136] ; 0x88 + 8005c42: aa0a add r2, sp, #40 ; 0x28 + 8005c44: 4641 mov r1, r8 + 8005c46: 4640 mov r0, r8 + 8005c48: f7ff fdb2 bl 80057b0 + uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ + 8005c4c: 4623 mov r3, r4 + 8005c4e: 462a mov r2, r5 + 8005c50: 4631 mov r1, r6 + 8005c52: a80a add r0, sp, #40 ; 0x28 + 8005c54: f8cd 9000 str.w r9, [sp] + 8005c58: f7ff fee2 bl 8005a20 + uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */ + 8005c5c: 9a22 ldr r2, [sp, #136] ; 0x88 + 8005c5e: 4639 mov r1, r7 + 8005c60: 4628 mov r0, r5 + 8005c62: f7ff fdb5 bl 80057d0 + uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ + 8005c66: 4623 mov r3, r4 + 8005c68: aa0a add r2, sp, #40 ; 0x28 + 8005c6a: 4629 mov r1, r5 + 8005c6c: 4628 mov r0, r5 + 8005c6e: f7ff ff43 bl 8005af8 + + uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ + 8005c72: 4623 mov r3, r4 + 8005c74: 462a mov r2, r5 + 8005c76: 4631 mov r1, r6 + 8005c78: a812 add r0, sp, #72 ; 0x48 + 8005c7a: f7ff ff3d bl 8005af8 + uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */ + 8005c7e: 9b22 ldr r3, [sp, #136] ; 0x88 + 8005c80: aa12 add r2, sp, #72 ; 0x48 + 8005c82: 4639 mov r1, r7 + 8005c84: 4638 mov r0, r7 + 8005c86: f7ff fd93 bl 80057b0 + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = (y2 - y1)*(B - x3) - E = y3 */ + 8005c8a: 4623 mov r3, r4 + 8005c8c: 4642 mov r2, r8 + 8005c8e: 4639 mov r1, r7 + 8005c90: 4638 mov r0, r7 + 8005c92: f7ff ff31 bl 8005af8 + + uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */ + 8005c96: 9a22 ldr r2, [sp, #136] ; 0x88 + 8005c98: a902 add r1, sp, #8 + 8005c9a: a812 add r0, sp, #72 ; 0x48 + 8005c9c: f7ff fd98 bl 80057d0 + uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ + 8005ca0: a912 add r1, sp, #72 ; 0x48 + 8005ca2: 4623 mov r3, r4 + 8005ca4: aa0a add r2, sp, #40 ; 0x28 + 8005ca6: 4608 mov r0, r1 + 8005ca8: f7ff ff26 bl 8005af8 + uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ + 8005cac: 4623 mov r3, r4 + 8005cae: 4632 mov r2, r6 + 8005cb0: a912 add r1, sp, #72 ; 0x48 + 8005cb2: a80a add r0, sp, #40 ; 0x28 + 8005cb4: f7ff ff20 bl 8005af8 + uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */ + 8005cb8: a90a add r1, sp, #40 ; 0x28 + 8005cba: 9b22 ldr r3, [sp, #136] ; 0x88 + 8005cbc: aa02 add r2, sp, #8 + 8005cbe: 4608 mov r0, r1 + 8005cc0: f7ff fd76 bl 80057b0 + uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); /* t2 = (y2+y1)*(x3' - B) - E = y3' */ + 8005cc4: 4623 mov r3, r4 + 8005cc6: 4642 mov r2, r8 + 8005cc8: a90a add r1, sp, #40 ; 0x28 + 8005cca: 4640 mov r0, r8 + 8005ccc: f7ff ff14 bl 8005af8 + + uECC_vli_set(X1, t7, num_words); + 8005cd0: 464a mov r2, r9 + 8005cd2: a912 add r1, sp, #72 ; 0x48 + 8005cd4: 4630 mov r0, r6 + 8005cd6: f7ff fc8f bl 80055f8 +} + 8005cda: b01b add sp, #108 ; 0x6c + 8005cdc: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +08005ce0 : +#define EVEN(vli) (!(vli[0] & 1)) +static void vli_modInv_update(uECC_word_t *uv, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t carry = 0; + if (!EVEN(uv)) { + 8005ce0: 6803 ldr r3, [r0, #0] +#endif /* uECC_SQUARE_FUNC */ + +#define EVEN(vli) (!(vli[0] & 1)) +static void vli_modInv_update(uECC_word_t *uv, + const uECC_word_t *mod, + wordcount_t num_words) { + 8005ce2: b570 push {r4, r5, r6, lr} + uECC_word_t carry = 0; + if (!EVEN(uv)) { + 8005ce4: f013 0501 ands.w r5, r3, #1 +#endif /* uECC_SQUARE_FUNC */ + +#define EVEN(vli) (!(vli[0] & 1)) +static void vli_modInv_update(uECC_word_t *uv, + const uECC_word_t *mod, + wordcount_t num_words) { + 8005ce8: 4606 mov r6, r0 + 8005cea: 4614 mov r4, r2 + uECC_word_t carry = 0; + if (!EVEN(uv)) { + 8005cec: d004 beq.n 8005cf8 + carry = uECC_vli_add(uv, uv, mod, num_words); + 8005cee: 460a mov r2, r1 + 8005cf0: 4601 mov r1, r0 + 8005cf2: f7ff fdc5 bl 8005880 + 8005cf6: 4605 mov r5, r0 + } + uECC_vli_rshift1(uv, num_words); + 8005cf8: 4621 mov r1, r4 + 8005cfa: 4630 mov r0, r6 + 8005cfc: f7ff fc9e bl 800563c + if (carry) { + 8005d00: b145 cbz r5, 8005d14 + uv[num_words - 1] |= HIGH_BIT_SET; + 8005d02: f104 4280 add.w r2, r4, #1073741824 ; 0x40000000 + 8005d06: 3a01 subs r2, #1 + 8005d08: f856 3022 ldr.w r3, [r6, r2, lsl #2] + 8005d0c: f043 4300 orr.w r3, r3, #2147483648 ; 0x80000000 + 8005d10: f846 3022 str.w r3, [r6, r2, lsl #2] + 8005d14: bd70 pop {r4, r5, r6, pc} + +08005d16 : +/* Computes result = (1 / input) % mod. All VLIs are the same size. + See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */ +uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result, + const uECC_word_t *input, + const uECC_word_t *mod, + wordcount_t num_words) { + 8005d16: b5f0 push {r4, r5, r6, r7, lr} + 8005d18: 460f mov r7, r1 + 8005d1a: b0a1 sub sp, #132 ; 0x84 + 8005d1c: 4606 mov r6, r0 + uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS]; + cmpresult_t cmpResult; + + if (uECC_vli_isZero(input, num_words)) { + 8005d1e: 4619 mov r1, r3 + 8005d20: 4638 mov r0, r7 +/* Computes result = (1 / input) % mod. All VLIs are the same size. + See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */ +uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result, + const uECC_word_t *input, + const uECC_word_t *mod, + wordcount_t num_words) { + 8005d22: 4615 mov r5, r2 + 8005d24: 461c mov r4, r3 + uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS]; + cmpresult_t cmpResult; + + if (uECC_vli_isZero(input, num_words)) { + 8005d26: f7ff fc2c bl 8005582 + 8005d2a: b120 cbz r0, 8005d36 + uECC_vli_clear(result, num_words); + 8005d2c: 4621 mov r1, r4 + 8005d2e: 4630 mov r0, r6 + 8005d30: f7ff fc1b bl 800556a + 8005d34: e06f b.n 8005e16 + return; + } + + uECC_vli_set(a, input, num_words); + 8005d36: 4622 mov r2, r4 + 8005d38: 4639 mov r1, r7 + 8005d3a: 4668 mov r0, sp + 8005d3c: f7ff fc5c bl 80055f8 + uECC_vli_set(b, mod, num_words); + 8005d40: 4622 mov r2, r4 + 8005d42: 4629 mov r1, r5 + 8005d44: a808 add r0, sp, #32 + 8005d46: f7ff fc57 bl 80055f8 + uECC_vli_clear(u, num_words); + 8005d4a: 4621 mov r1, r4 + 8005d4c: a810 add r0, sp, #64 ; 0x40 + 8005d4e: f7ff fc0c bl 800556a + u[0] = 1; + 8005d52: 2301 movs r3, #1 + uECC_vli_clear(v, num_words); + 8005d54: 4621 mov r1, r4 + 8005d56: a818 add r0, sp, #96 ; 0x60 + } + + uECC_vli_set(a, input, num_words); + uECC_vli_set(b, mod, num_words); + uECC_vli_clear(u, num_words); + u[0] = 1; + 8005d58: 9310 str r3, [sp, #64] ; 0x40 + uECC_vli_clear(v, num_words); + 8005d5a: f7ff fc06 bl 800556a + while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { + 8005d5e: 4622 mov r2, r4 + 8005d60: a908 add r1, sp, #32 + 8005d62: 4668 mov r0, sp + 8005d64: f7ff fc55 bl 8005612 + 8005d68: 2800 cmp r0, #0 + 8005d6a: d04f beq.n 8005e0c + if (EVEN(a)) { + 8005d6c: 9b00 ldr r3, [sp, #0] + 8005d6e: 07da lsls r2, r3, #31 + 8005d70: d404 bmi.n 8005d7c + uECC_vli_rshift1(a, num_words); + 8005d72: 4621 mov r1, r4 + 8005d74: 4668 mov r0, sp + 8005d76: f7ff fc61 bl 800563c + 8005d7a: e023 b.n 8005dc4 + vli_modInv_update(u, mod, num_words); + } else if (EVEN(b)) { + 8005d7c: 9b08 ldr r3, [sp, #32] + 8005d7e: 07db lsls r3, r3, #31 + 8005d80: d404 bmi.n 8005d8c + uECC_vli_rshift1(b, num_words); + 8005d82: 4621 mov r1, r4 + 8005d84: a808 add r0, sp, #32 + 8005d86: f7ff fc59 bl 800563c + 8005d8a: e039 b.n 8005e00 + vli_modInv_update(v, mod, num_words); + } else if (cmpResult > 0) { + 8005d8c: 2800 cmp r0, #0 + 8005d8e: dd1d ble.n 8005dcc + uECC_vli_sub(a, a, b, num_words); + 8005d90: aa08 add r2, sp, #32 + 8005d92: 4669 mov r1, sp + 8005d94: 4668 mov r0, sp + 8005d96: f7ff fe1c bl 80059d2 + uECC_vli_rshift1(a, num_words); + 8005d9a: 4621 mov r1, r4 + 8005d9c: 4668 mov r0, sp + 8005d9e: f7ff fc4d bl 800563c + if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { + 8005da2: 4622 mov r2, r4 + 8005da4: a918 add r1, sp, #96 ; 0x60 + 8005da6: a810 add r0, sp, #64 ; 0x40 + 8005da8: f7ff fc33 bl 8005612 + 8005dac: 2800 cmp r0, #0 + 8005dae: da04 bge.n 8005dba + uECC_vli_add(u, u, mod, num_words); + 8005db0: a910 add r1, sp, #64 ; 0x40 + 8005db2: 462a mov r2, r5 + 8005db4: 4608 mov r0, r1 + 8005db6: f7ff fd63 bl 8005880 + } + uECC_vli_sub(u, u, v, num_words); + 8005dba: a910 add r1, sp, #64 ; 0x40 + 8005dbc: aa18 add r2, sp, #96 ; 0x60 + 8005dbe: 4608 mov r0, r1 + 8005dc0: f7ff fe07 bl 80059d2 + vli_modInv_update(u, mod, num_words); + 8005dc4: 4622 mov r2, r4 + 8005dc6: 4629 mov r1, r5 + 8005dc8: a810 add r0, sp, #64 ; 0x40 + 8005dca: e01c b.n 8005e06 + } else { + uECC_vli_sub(b, b, a, num_words); + 8005dcc: a908 add r1, sp, #32 + 8005dce: 466a mov r2, sp + 8005dd0: 4608 mov r0, r1 + 8005dd2: f7ff fdfe bl 80059d2 + uECC_vli_rshift1(b, num_words); + 8005dd6: 4621 mov r1, r4 + 8005dd8: a808 add r0, sp, #32 + 8005dda: f7ff fc2f bl 800563c + if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { + 8005dde: 4622 mov r2, r4 + 8005de0: a910 add r1, sp, #64 ; 0x40 + 8005de2: a818 add r0, sp, #96 ; 0x60 + 8005de4: f7ff fc15 bl 8005612 + 8005de8: 2800 cmp r0, #0 + 8005dea: da04 bge.n 8005df6 + uECC_vli_add(v, v, mod, num_words); + 8005dec: a918 add r1, sp, #96 ; 0x60 + 8005dee: 462a mov r2, r5 + 8005df0: 4608 mov r0, r1 + 8005df2: f7ff fd45 bl 8005880 + } + uECC_vli_sub(v, v, u, num_words); + 8005df6: a918 add r1, sp, #96 ; 0x60 + 8005df8: aa10 add r2, sp, #64 ; 0x40 + 8005dfa: 4608 mov r0, r1 + 8005dfc: f7ff fde9 bl 80059d2 + vli_modInv_update(v, mod, num_words); + 8005e00: 4622 mov r2, r4 + 8005e02: 4629 mov r1, r5 + 8005e04: a818 add r0, sp, #96 ; 0x60 + 8005e06: f7ff ff6b bl 8005ce0 + 8005e0a: e7a8 b.n 8005d5e + } + } + uECC_vli_set(result, u, num_words); + 8005e0c: 4622 mov r2, r4 + 8005e0e: a910 add r1, sp, #64 ; 0x40 + 8005e10: 4630 mov r0, r6 + 8005e12: f7ff fbf1 bl 80055f8 +} + 8005e16: b021 add sp, #132 ; 0x84 + 8005e18: bdf0 pop {r4, r5, r6, r7, pc} + +08005e1a : +static void EccPoint_mult(uECC_word_t * result, + const uECC_word_t * point, + const uECC_word_t * scalar, + const uECC_word_t * initial_Z, + bitcount_t num_bits, + uECC_Curve curve) { + 8005e1a: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 8005e1e: b0b1 sub sp, #196 ; 0xc4 + 8005e20: 461e mov r6, r3 + 8005e22: 9c3b ldr r4, [sp, #236] ; 0xec + 8005e24: 9004 str r0, [sp, #16] + uECC_word_t z[uECC_MAX_WORDS]; + bitcount_t i; + uECC_word_t nb; + wordcount_t num_words = curve->num_words; + + uECC_vli_set(Rx[1], point, num_words); + 8005e26: f994 8000 ldrsb.w r8, [r4] +static void EccPoint_mult(uECC_word_t * result, + const uECC_word_t * point, + const uECC_word_t * scalar, + const uECC_word_t * initial_Z, + bitcount_t num_bits, + uECC_Curve curve) { + 8005e2a: 9206 str r2, [sp, #24] + uECC_word_t z[uECC_MAX_WORDS]; + bitcount_t i; + uECC_word_t nb; + wordcount_t num_words = curve->num_words; + + uECC_vli_set(Rx[1], point, num_words); + 8005e2c: a818 add r0, sp, #96 ; 0x60 + 8005e2e: 4642 mov r2, r8 +static void EccPoint_mult(uECC_word_t * result, + const uECC_word_t * point, + const uECC_word_t * scalar, + const uECC_word_t * initial_Z, + bitcount_t num_bits, + uECC_Curve curve) { + 8005e30: 9105 str r1, [sp, #20] + uECC_word_t z[uECC_MAX_WORDS]; + bitcount_t i; + uECC_word_t nb; + wordcount_t num_words = curve->num_words; + + uECC_vli_set(Rx[1], point, num_words); + 8005e32: f7ff fbe1 bl 80055f8 + uECC_vli_set(Ry[1], point + num_words, num_words); + 8005e36: ea4f 0388 mov.w r3, r8, lsl #2 + 8005e3a: 9302 str r3, [sp, #8] + 8005e3c: 9a02 ldr r2, [sp, #8] + 8005e3e: 9b05 ldr r3, [sp, #20] + 8005e40: 4413 add r3, r2 + 8005e42: 4619 mov r1, r3 + 8005e44: 4642 mov r2, r8 + 8005e46: a828 add r0, sp, #160 ; 0xa0 + 8005e48: 9303 str r3, [sp, #12] + 8005e4a: f7ff fbd5 bl 80055f8 + 8005e4e: f994 5000 ldrsb.w r5, [r4] + uECC_word_t * Y2, + const uECC_word_t * const initial_Z, + uECC_Curve curve) { + uECC_word_t z[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + if (initial_Z) { + 8005e52: b12e cbz r6, 8005e60 + uECC_vli_set(z, initial_Z, num_words); + 8005e54: 462a mov r2, r5 + 8005e56: 4631 mov r1, r6 + 8005e58: a808 add r0, sp, #32 + 8005e5a: f7ff fbcd bl 80055f8 + 8005e5e: e005 b.n 8005e6c + } else { + uECC_vli_clear(z, num_words); + 8005e60: 4629 mov r1, r5 + 8005e62: a808 add r0, sp, #32 + 8005e64: f7ff fb81 bl 800556a + z[0] = 1; + 8005e68: 2301 movs r3, #1 + 8005e6a: 9308 str r3, [sp, #32] + } + + uECC_vli_set(X2, X1, num_words); + 8005e6c: af10 add r7, sp, #64 ; 0x40 + 8005e6e: 462a mov r2, r5 + 8005e70: a918 add r1, sp, #96 ; 0x60 + 8005e72: 4638 mov r0, r7 + uECC_vli_set(Y2, Y1, num_words); + 8005e74: f10d 0980 add.w r9, sp, #128 ; 0x80 + } else { + uECC_vli_clear(z, num_words); + z[0] = 1; + } + + uECC_vli_set(X2, X1, num_words); + 8005e78: f7ff fbbe bl 80055f8 + uECC_vli_set(Y2, Y1, num_words); + 8005e7c: 462a mov r2, r5 + 8005e7e: a928 add r1, sp, #160 ; 0xa0 + 8005e80: 4648 mov r0, r9 + 8005e82: f7ff fbb9 bl 80055f8 + + apply_z(X1, Y1, z, curve); + 8005e86: 4623 mov r3, r4 + 8005e88: aa08 add r2, sp, #32 + 8005e8a: a928 add r1, sp, #160 ; 0xa0 + 8005e8c: a818 add r0, sp, #96 ; 0x60 + 8005e8e: f7ff fca3 bl 80057d8 + curve->double_jacobian(X1, Y1, z, curve); + 8005e92: 4623 mov r3, r4 + 8005e94: aa08 add r2, sp, #32 + 8005e96: a928 add r1, sp, #160 ; 0xa0 + 8005e98: a818 add r0, sp, #96 ; 0x60 + 8005e9a: f8d4 50a4 ldr.w r5, [r4, #164] ; 0xa4 + 8005e9e: 47a8 blx r5 + apply_z(X2, Y2, z, curve); + 8005ea0: 4623 mov r3, r4 + 8005ea2: aa08 add r2, sp, #32 + 8005ea4: 4649 mov r1, r9 + 8005ea6: 4638 mov r0, r7 + 8005ea8: f7ff fc96 bl 80057d8 + uECC_vli_set(Rx[1], point, num_words); + uECC_vli_set(Ry[1], point + num_words, num_words); + + XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); + + for (i = num_bits - 2; i > 0; --i) { + 8005eac: f9bd 60e8 ldrsh.w r6, [sp, #232] ; 0xe8 + nb = !uECC_vli_testBit(scalar, i); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + 8005eb0: 9707 str r7, [sp, #28] + uECC_vli_set(Rx[1], point, num_words); + uECC_vli_set(Ry[1], point + num_words, num_words); + + XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); + + for (i = num_bits - 2; i > 0; --i) { + 8005eb2: 3e02 subs r6, #2 + 8005eb4: b2b6 uxth r6, r6 + 8005eb6: b231 sxth r1, r6 + 8005eb8: 2900 cmp r1, #0 + 8005eba: dd22 ble.n 8005f02 + nb = !uECC_vli_testBit(scalar, i); + 8005ebc: 9806 ldr r0, [sp, #24] + 8005ebe: f7ff fb6f bl 80055a0 + 8005ec2: fab0 f080 clz r0, r0 + 8005ec6: 0940 lsrs r0, r0, #5 + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + 8005ec8: 9b07 ldr r3, [sp, #28] + 8005eca: 9400 str r4, [sp, #0] + 8005ecc: f1c0 0701 rsb r7, r0, #1 + 8005ed0: 017f lsls r7, r7, #5 + 8005ed2: 0140 lsls r0, r0, #5 + 8005ed4: eb03 0b07 add.w fp, r3, r7 + 8005ed8: eb03 0a00 add.w sl, r3, r0 + 8005edc: eb09 0500 add.w r5, r9, r0 + 8005ee0: 444f add r7, r9 + 8005ee2: 462b mov r3, r5 + 8005ee4: 4652 mov r2, sl + 8005ee6: 4639 mov r1, r7 + 8005ee8: 4658 mov r0, fp + 8005eea: f7ff fe72 bl 8005bd2 + 8005eee: 3e01 subs r6, #1 + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + 8005ef0: 9400 str r4, [sp, #0] + 8005ef2: 463b mov r3, r7 + 8005ef4: 465a mov r2, fp + 8005ef6: 4629 mov r1, r5 + 8005ef8: 4650 mov r0, sl + 8005efa: f7ff fe0b bl 8005b14 + 8005efe: b2b6 uxth r6, r6 + 8005f00: e7d9 b.n 8005eb6 + 8005f02: 9b06 ldr r3, [sp, #24] + 8005f04: 681d ldr r5, [r3, #0] + } + + nb = !uECC_vli_testBit(scalar, 0); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + 8005f06: 9400 str r4, [sp, #0] + 8005f08: f005 0501 and.w r5, r5, #1 + 8005f0c: f085 0501 eor.w r5, r5, #1 + 8005f10: f1c5 0601 rsb r6, r5, #1 + 8005f14: ab10 add r3, sp, #64 ; 0x40 + 8005f16: 0176 lsls r6, r6, #5 + 8005f18: 199f adds r7, r3, r6 + 8005f1a: ab20 add r3, sp, #128 ; 0x80 + 8005f1c: 441e add r6, r3 + 8005f1e: 016d lsls r5, r5, #5 + 8005f20: ab10 add r3, sp, #64 ; 0x40 + 8005f22: eb03 0905 add.w r9, r3, r5 + 8005f26: ab20 add r3, sp, #128 ; 0x80 + 8005f28: 441d add r5, r3 + + /* Find final 1/Z value. */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ + 8005f2a: f104 0a04 add.w sl, r4, #4 + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + } + + nb = !uECC_vli_testBit(scalar, 0); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + 8005f2e: 462b mov r3, r5 + 8005f30: 464a mov r2, r9 + 8005f32: 4631 mov r1, r6 + 8005f34: 4638 mov r0, r7 + 8005f36: f7ff fe4c bl 8005bd2 + + /* Find final 1/Z value. */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ + 8005f3a: 4653 mov r3, sl + 8005f3c: aa10 add r2, sp, #64 ; 0x40 + 8005f3e: a918 add r1, sp, #96 ; 0x60 + 8005f40: a808 add r0, sp, #32 + 8005f42: f7ff fdd9 bl 8005af8 + uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */ + 8005f46: a908 add r1, sp, #32 + 8005f48: 4623 mov r3, r4 + 8005f4a: 4632 mov r2, r6 + 8005f4c: 4608 mov r0, r1 + 8005f4e: f7ff fc2f bl 80057b0 + uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */ + 8005f52: a908 add r1, sp, #32 + 8005f54: 4623 mov r3, r4 + 8005f56: 9a05 ldr r2, [sp, #20] + 8005f58: 4608 mov r0, r1 + 8005f5a: f7ff fc29 bl 80057b0 + uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0)) */ + 8005f5e: a908 add r1, sp, #32 + 8005f60: 4643 mov r3, r8 + 8005f62: 4652 mov r2, sl + 8005f64: 4608 mov r0, r1 + 8005f66: f7ff fed6 bl 8005d16 + /* yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, point + num_words, curve); + 8005f6a: a908 add r1, sp, #32 + 8005f6c: 4623 mov r3, r4 + 8005f6e: 9a03 ldr r2, [sp, #12] + 8005f70: 4608 mov r0, r1 + 8005f72: f7ff fc1d bl 80057b0 + uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); /* Xb * yP / (xP * Yb * (X1 - X0)) */ + 8005f76: a908 add r1, sp, #32 + 8005f78: 4623 mov r3, r4 + 8005f7a: 463a mov r2, r7 + 8005f7c: 4608 mov r0, r1 + 8005f7e: f7ff fc17 bl 80057b0 + /* End 1/Z calculation */ + + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + 8005f82: 9400 str r4, [sp, #0] + 8005f84: 4633 mov r3, r6 + 8005f86: 463a mov r2, r7 + 8005f88: 4629 mov r1, r5 + 8005f8a: 4648 mov r0, r9 + 8005f8c: f7ff fdc2 bl 8005b14 + apply_z(Rx[0], Ry[0], z, curve); + 8005f90: 4623 mov r3, r4 + 8005f92: aa08 add r2, sp, #32 + 8005f94: a920 add r1, sp, #128 ; 0x80 + 8005f96: a810 add r0, sp, #64 ; 0x40 + 8005f98: f7ff fc1e bl 80057d8 + + uECC_vli_set(result, Rx[0], num_words); + 8005f9c: 4642 mov r2, r8 + 8005f9e: a910 add r1, sp, #64 ; 0x40 + 8005fa0: 9804 ldr r0, [sp, #16] + 8005fa2: f7ff fb29 bl 80055f8 + uECC_vli_set(result + num_words, Ry[0], num_words); + 8005fa6: 9b04 ldr r3, [sp, #16] + 8005fa8: 9c02 ldr r4, [sp, #8] + 8005faa: 4423 add r3, r4 + 8005fac: 4642 mov r2, r8 + 8005fae: a920 add r1, sp, #128 ; 0x80 + 8005fb0: 4618 mov r0, r3 + 8005fb2: f7ff fb21 bl 80055f8 +} + 8005fb6: b031 add sp, #196 ; 0xc4 + 8005fb8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +08005fbc : + return carry; +} + +static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private, + uECC_Curve curve) { + 8005fbc: b530 push {r4, r5, lr} + 8005fbe: 4614 mov r4, r2 + 8005fc0: b095 sub sp, #84 ; 0x54 + 8005fc2: 4605 mov r5, r0 + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {tmp1, tmp2}; + 8005fc4: aa0c add r2, sp, #48 ; 0x30 + uECC_word_t carry; + + /* Regularize the bitcount for the private key so that attackers cannot use a side channel + attack to learn the number of leading zeros. */ + carry = regularize_k(private, tmp1, tmp2, curve); + 8005fc6: 4623 mov r3, r4 + return carry; +} + +static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private, + uECC_Curve curve) { + 8005fc8: 4608 mov r0, r1 + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {tmp1, tmp2}; + 8005fca: a904 add r1, sp, #16 + 8005fcc: 9102 str r1, [sp, #8] + 8005fce: 9203 str r2, [sp, #12] + uECC_word_t carry; + + /* Regularize the bitcount for the private key so that attackers cannot use a side channel + attack to learn the number of leading zeros. */ + carry = regularize_k(private, tmp1, tmp2, curve); + 8005fd0: f7ff fcd8 bl 8005984 + + EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); + 8005fd4: fab0 f080 clz r0, r0 + 8005fd8: ab14 add r3, sp, #80 ; 0x50 + 8005fda: 0940 lsrs r0, r0, #5 + 8005fdc: eb03 0080 add.w r0, r3, r0, lsl #2 + 8005fe0: 8863 ldrh r3, [r4, #2] + 8005fe2: 9401 str r4, [sp, #4] + 8005fe4: 3301 adds r3, #1 + 8005fe6: b21b sxth r3, r3 + 8005fe8: 9300 str r3, [sp, #0] + 8005fea: f850 2c48 ldr.w r2, [r0, #-72] + 8005fee: 2300 movs r3, #0 + 8005ff0: f104 0144 add.w r1, r4, #68 ; 0x44 + 8005ff4: 4628 mov r0, r5 + 8005ff6: f7ff ff10 bl 8005e1a + + if (EccPoint_isZero(result, curve)) { + 8005ffa: 7821 ldrb r1, [r4, #0] + 8005ffc: 0049 lsls r1, r1, #1 + 8005ffe: b249 sxtb r1, r1 + 8006000: 4628 mov r0, r5 + 8006002: f7ff fabe bl 8005582 + return 0; + } + return 1; +} + 8006006: fab0 f080 clz r0, r0 + 800600a: 0940 lsrs r0, r0, #5 + 800600c: b015 add sp, #84 ; 0x54 + 800600e: bd30 pop {r4, r5, pc} + +08006010 : + +/* Double in place */ +static void double_jacobian_secp256k1(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve) { + 8006010: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 8006014: 4605 mov r5, r0 + 8006016: b093 sub sp, #76 ; 0x4c + 8006018: 460c mov r4, r1 + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[num_words_secp256k1]; + uECC_word_t t5[num_words_secp256k1]; + + if (uECC_vli_isZero(Z1, num_words_secp256k1)) { + 800601a: 4610 mov r0, r2 + 800601c: 2108 movs r1, #8 + +/* Double in place */ +static void double_jacobian_secp256k1(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve) { + 800601e: 4617 mov r7, r2 + 8006020: 461e mov r6, r3 + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[num_words_secp256k1]; + uECC_word_t t5[num_words_secp256k1]; + + if (uECC_vli_isZero(Z1, num_words_secp256k1)) { + 8006022: f7ff faae bl 8005582 + 8006026: 2800 cmp r0, #0 + 8006028: d166 bne.n 80060f8 + return; + } + + uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */ + 800602a: 4632 mov r2, r6 + 800602c: 4621 mov r1, r4 + 800602e: a80a add r0, sp, #40 ; 0x28 + 8006030: f7ff fbce bl 80057d0 + uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */ + 8006034: 4633 mov r3, r6 + 8006036: aa0a add r2, sp, #40 ; 0x28 + 8006038: 4629 mov r1, r5 + 800603a: a802 add r0, sp, #8 + 800603c: f7ff fbb8 bl 80057b0 + uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */ + 8006040: 4632 mov r2, r6 + 8006042: 4629 mov r1, r5 + 8006044: 4628 mov r0, r5 + 8006046: f7ff fbc3 bl 80057d0 + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */ + 800604a: a90a add r1, sp, #40 ; 0x28 + 800604c: 4608 mov r0, r1 + 800604e: 4632 mov r2, r6 + 8006050: f7ff fbbe bl 80057d0 + uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */ + + uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */ + 8006054: f04f 0808 mov.w r8, #8 + + uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */ + uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */ + uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */ + uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */ + 8006058: 463a mov r2, r7 + 800605a: 4638 mov r0, r7 + 800605c: 4633 mov r3, r6 + 800605e: 4621 mov r1, r4 + + uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */ + 8006060: 1d37 adds r7, r6, #4 + + uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */ + uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */ + uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */ + uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */ + 8006062: f7ff fba5 bl 80057b0 + + uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */ + 8006066: 463b mov r3, r7 + 8006068: 462a mov r2, r5 + 800606a: 4629 mov r1, r5 + 800606c: 4620 mov r0, r4 + 800606e: f8cd 8000 str.w r8, [sp] + 8006072: f7ff fcd5 bl 8005a20 + uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */ + 8006076: 463b mov r3, r7 + 8006078: f8cd 8000 str.w r8, [sp] + 800607c: 462a mov r2, r5 + 800607e: 4621 mov r1, r4 + 8006080: 4620 mov r0, r4 + 8006082: f7ff fccd bl 8005a20 + if (uECC_vli_testBit(Y1, 0)) { + 8006086: 6823 ldr r3, [r4, #0] + 8006088: 07db lsls r3, r3, #31 + 800608a: d50e bpl.n 80060aa + uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1); + 800608c: 463a mov r2, r7 + 800608e: 4621 mov r1, r4 + 8006090: 4620 mov r0, r4 + 8006092: f7ff fbf5 bl 8005880 + uECC_vli_rshift1(Y1, num_words_secp256k1); + 8006096: 4641 mov r1, r8 + uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */ + + uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */ + uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */ + if (uECC_vli_testBit(Y1, 0)) { + uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1); + 8006098: 4681 mov r9, r0 + uECC_vli_rshift1(Y1, num_words_secp256k1); + 800609a: 4620 mov r0, r4 + 800609c: f7ff face bl 800563c + Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1); + 80060a0: 69e0 ldr r0, [r4, #28] + 80060a2: ea40 70c9 orr.w r0, r0, r9, lsl #31 + 80060a6: 61e0 str r0, [r4, #28] + 80060a8: e003 b.n 80060b2 + } else { + uECC_vli_rshift1(Y1, num_words_secp256k1); + 80060aa: 4641 mov r1, r8 + 80060ac: 4620 mov r0, r4 + 80060ae: f7ff fac5 bl 800563c + } + /* t2 = 3/2*(x1^2) = B */ + + uECC_vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */ + 80060b2: 4632 mov r2, r6 + 80060b4: 4621 mov r1, r4 + 80060b6: 4628 mov r0, r5 + 80060b8: f7ff fb8a bl 80057d0 + uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */ + 80060bc: 463b mov r3, r7 + 80060be: aa02 add r2, sp, #8 + 80060c0: 4629 mov r1, r5 + 80060c2: 4628 mov r0, r5 + 80060c4: f7ff fd18 bl 8005af8 + uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */ + 80060c8: 463b mov r3, r7 + 80060ca: aa02 add r2, sp, #8 + 80060cc: 4629 mov r1, r5 + 80060ce: 4628 mov r0, r5 + 80060d0: f7ff fd12 bl 8005af8 + + uECC_vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */ + 80060d4: a902 add r1, sp, #8 + 80060d6: 4608 mov r0, r1 + 80060d8: 463b mov r3, r7 + 80060da: 462a mov r2, r5 + 80060dc: f7ff fd0c bl 8005af8 + uECC_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */ + 80060e0: 4633 mov r3, r6 + 80060e2: aa02 add r2, sp, #8 + 80060e4: 4621 mov r1, r4 + 80060e6: 4620 mov r0, r4 + 80060e8: f7ff fb62 bl 80057b0 + uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */ + 80060ec: 463b mov r3, r7 + 80060ee: aa0a add r2, sp, #40 ; 0x28 + 80060f0: 4621 mov r1, r4 + 80060f2: 4620 mov r0, r4 + 80060f4: f7ff fd00 bl 8005af8 +} + 80060f8: b013 add sp, #76 ; 0x4c + 80060fa: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + ... + +08006100 : + +/* Generates a random integer in the range 0 < random < top. + Both random and top have num_words words. */ +uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random, + const uECC_word_t *top, + wordcount_t num_words) { + 8006100: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 8006104: 468a mov sl, r1 + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top, num_words); + + if (!g_rng_function) { + 8006106: 4f24 ldr r7, [pc, #144] ; (8006198 ) + +/* Generates a random integer in the range 0 < random < top. + Both random and top have num_words words. */ +uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random, + const uECC_word_t *top, + wordcount_t num_words) { + 8006108: b08b sub sp, #44 ; 0x2c + 800610a: 4606 mov r6, r0 + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top, num_words); + 800610c: 4611 mov r1, r2 + 800610e: 4650 mov r0, sl + +/* Generates a random integer in the range 0 < random < top. + Both random and top have num_words words. */ +uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random, + const uECC_word_t *top, + wordcount_t num_words) { + 8006110: 4615 mov r5, r2 + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top, num_words); + 8006112: f7ff fa4f bl 80055b4 + + if (!g_rng_function) { + 8006116: 683b ldr r3, [r7, #0] + 8006118: b90b cbnz r3, 800611e + return 0; + 800611a: 2000 movs r0, #0 + 800611c: e038 b.n 8006190 + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + 800611e: 2404 movs r4, #4 + return 0; + } + random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + 8006120: ebc0 1045 rsb r0, r0, r5, lsl #5 + if (!g_rng_function) { + return 0; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + 8006124: fb15 fb04 smulbb fp, r5, r4 + return 0; + } + random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + 8006128: b200 sxth r0, r0 + 800612a: fb04 6405 mla r4, r4, r5, r6 + 800612e: f04f 39ff mov.w r9, #4294967295 ; 0xffffffff + 8006132: 3c04 subs r4, #4 + 8006134: fa29 f900 lsr.w r9, r9, r0 + 8006138: f04f 0840 mov.w r8, #64 ; 0x40 + if (!g_rng_function) { + return 0; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + 800613c: 683b ldr r3, [r7, #0] + 800613e: 4659 mov r1, fp + 8006140: 4630 mov r0, r6 + 8006142: 4798 blx r3 + 8006144: 2800 cmp r0, #0 + 8006146: d0e8 beq.n 800611a + return 0; + } + random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + 8006148: 6823 ldr r3, [r4, #0] + 800614a: ea03 0309 and.w r3, r3, r9 + 800614e: 6023 str r3, [r4, #0] + if (!uECC_vli_isZero(random, num_words) && + 8006150: 4629 mov r1, r5 + 8006152: 4630 mov r0, r6 + 8006154: f7ff fa15 bl 8005582 + 8006158: b118 cbz r0, 8006162 + + if (!g_rng_function) { + return 0; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + 800615a: f1b8 0801 subs.w r8, r8, #1 + 800615e: d1ed bne.n 800613c + 8006160: e7db b.n 800611a +/* Returns sign of left - right, in constant time. */ +uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + 8006162: 4632 mov r2, r6 + 8006164: 4651 mov r1, sl + 8006166: a802 add r0, sp, #8 + 8006168: f7ff fc33 bl 80059d2 + uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + 800616c: 4629 mov r1, r5 +/* Returns sign of left - right, in constant time. */ +uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + 800616e: 9001 str r0, [sp, #4] + uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + 8006170: a802 add r0, sp, #8 + 8006172: f7ff fa06 bl 8005582 + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + return 0; + } + random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random, num_words) && + 8006176: 9b01 ldr r3, [sp, #4] + 8006178: 3300 adds r3, #0 + 800617a: bf18 it ne + 800617c: 2301 movne r3, #1 + 800617e: 005b lsls r3, r3, #1 + 8006180: 2800 cmp r0, #0 + 8006182: bf14 ite ne + 8006184: 4258 negne r0, r3 + 8006186: f1c3 0001 rsbeq r0, r3, #1 + 800618a: b2c0 uxtb r0, r0 + 800618c: 2801 cmp r0, #1 + 800618e: d1e4 bne.n 800615a + uECC_vli_cmp(top, random, num_words) == 1) { + return 1; + } + } + return 0; +} + 8006190: b00b add sp, #44 ; 0x2c + 8006192: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 8006196: bf00 nop + 8006198: 10006344 .word 0x10006344 + +0800619c : + +// PDG: added prototype +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve); + +void uECC_set_rng(uECC_RNG_Function rng_function) { + g_rng_function = rng_function; + 800619c: 4b01 ldr r3, [pc, #4] ; (80061a4 ) + 800619e: 6018 str r0, [r3, #0] + 80061a0: 4770 bx lr + 80061a2: bf00 nop + 80061a4: 10006344 .word 0x10006344 + +080061a8 : +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp256k1 +#endif +}; + +uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; } + 80061a8: 4800 ldr r0, [pc, #0] ; (80061ac ) + 80061aa: 4770 bx lr + 80061ac: 080074b4 .word 0x080074b4 + +080061b0 : + return 0; +} + +int uECC_make_key(uint8_t *public_key, + uint8_t *private_key, + uECC_Curve curve) { + 80061b0: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 80061b4: 4606 mov r6, r0 + 80061b6: b099 sub sp, #100 ; 0x64 + 80061b8: 460f mov r7, r1 + 80061ba: 4614 mov r4, r2 + 80061bc: 2540 movs r5, #64 ; 0x40 + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t public[uECC_MAX_WORDS * 2]; + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!uECC_generate_random_int(private, curve->n, BITS_TO_WORDS(curve->num_n_bits))) { + 80061be: f04f 0820 mov.w r8, #32 + 80061c2: f102 0924 add.w r9, r2, #36 ; 0x24 + 80061c6: f9b4 2002 ldrsh.w r2, [r4, #2] + 80061ca: 4649 mov r1, r9 + 80061cc: 321f adds r2, #31 + 80061ce: 4668 mov r0, sp + 80061d0: fb92 f2f8 sdiv r2, r2, r8 + 80061d4: b252 sxtb r2, r2 + 80061d6: f7ff ff93 bl 8006100 + 80061da: b908 cbnz r0, 80061e0 + return 0; + 80061dc: 2000 movs r0, #0 + 80061de: e024 b.n 800622a + } + + if (EccPoint_compute_public_key(public, private, curve)) { + 80061e0: 4622 mov r2, r4 + 80061e2: 4669 mov r1, sp + 80061e4: a808 add r0, sp, #32 + 80061e6: f7ff fee9 bl 8005fbc + 80061ea: b1d8 cbz r0, 8006224 + uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(curve->num_n_bits), private); + 80061ec: f9b4 3002 ldrsh.w r3, [r4, #2] + 80061f0: 466a mov r2, sp + 80061f2: 3307 adds r3, #7 + 80061f4: 4638 mov r0, r7 + 80061f6: 2108 movs r1, #8 + 80061f8: fb93 f1f1 sdiv r1, r3, r1 + 80061fc: f7ff fb0b bl 8005816 + uECC_vli_nativeToBytes(public_key, curve->num_bytes, public); + 8006200: aa08 add r2, sp, #32 + 8006202: f994 1001 ldrsb.w r1, [r4, #1] + 8006206: 4630 mov r0, r6 + 8006208: f7ff fb05 bl 8005816 + uECC_vli_nativeToBytes( + 800620c: f994 2000 ldrsb.w r2, [r4] + 8006210: f994 1001 ldrsb.w r1, [r4, #1] + 8006214: ab08 add r3, sp, #32 + 8006216: 1870 adds r0, r6, r1 + 8006218: eb03 0282 add.w r2, r3, r2, lsl #2 + 800621c: f7ff fafb bl 8005816 + public_key + curve->num_bytes, curve->num_bytes, public + curve->num_words); + return 1; + 8006220: 2001 movs r0, #1 + 8006222: e002 b.n 800622a + uECC_Curve curve) { + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t public[uECC_MAX_WORDS * 2]; + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + 8006224: 3d01 subs r5, #1 + 8006226: d1ce bne.n 80061c6 + 8006228: e7d8 b.n 80061dc + public_key + curve->num_bytes, curve->num_bytes, public + curve->num_words); + return 1; + } + } + return 0; +} + 800622a: b019 add sp, #100 ; 0x64 + 800622c: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +08006230 : + +int uECC_shared_secret(const uint8_t *public_key, + const uint8_t *private_key, + uint8_t *secret, + uECC_Curve curve) { + 8006230: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 8006234: 461c mov r4, r3 + 8006236: b0a4 sub sp, #144 ; 0x90 + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {private, tmp}; + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + 8006238: f893 9000 ldrb.w r9, [r3] + wordcount_t num_bytes = curve->num_bytes; + 800623c: 785e ldrb r6, [r3, #1] + + uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + 800623e: f9b3 3002 ldrsh.w r3, [r3, #2] + uint8_t *secret, + uECC_Curve curve) { + uECC_word_t public[uECC_MAX_WORDS * 2]; + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {private, tmp}; + 8006242: ad04 add r5, sp, #16 + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_bytes = curve->num_bytes; + + uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + 8006244: 3307 adds r3, #7 +} + +int uECC_shared_secret(const uint8_t *public_key, + const uint8_t *private_key, + uint8_t *secret, + uECC_Curve curve) { + 8006246: 4682 mov sl, r0 + uECC_word_t public[uECC_MAX_WORDS * 2]; + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {private, tmp}; + 8006248: af0c add r7, sp, #48 ; 0x30 + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_bytes = curve->num_bytes; + + uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + 800624a: 4628 mov r0, r5 + uECC_vli_bytesToNative(public, public_key, num_bytes); + 800624c: b276 sxtb r6, r6 +} + +int uECC_shared_secret(const uint8_t *public_key, + const uint8_t *private_key, + uint8_t *secret, + uECC_Curve curve) { + 800624e: 4690 mov r8, r2 + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_bytes = curve->num_bytes; + + uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + 8006250: 2208 movs r2, #8 + 8006252: fb93 f2f2 sdiv r2, r3, r2 + uint8_t *secret, + uECC_Curve curve) { + uECC_word_t public[uECC_MAX_WORDS * 2]; + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {private, tmp}; + 8006256: 9502 str r5, [sp, #8] + 8006258: 9703 str r7, [sp, #12] + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_bytes = curve->num_bytes; + + uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + 800625a: f7ff faf0 bl 800583e + uECC_vli_bytesToNative(public, public_key, num_bytes); + 800625e: 4632 mov r2, r6 + 8006260: 4651 mov r1, sl + 8006262: a814 add r0, sp, #80 ; 0x50 + 8006264: f7ff faeb bl 800583e + uECC_vli_bytesToNative(public + num_words, public_key + num_bytes, num_bytes); + 8006268: fa4f f989 sxtb.w r9, r9 + 800626c: ab14 add r3, sp, #80 ; 0x50 + 800626e: eb03 0089 add.w r0, r3, r9, lsl #2 + 8006272: 4632 mov r2, r6 + 8006274: eb0a 0106 add.w r1, sl, r6 + 8006278: f7ff fae1 bl 800583e + + /* Regularize the bitcount for the private key so that attackers cannot use a side channel + attack to learn the number of leading zeros. */ + carry = regularize_k(private, private, tmp, curve); + 800627c: 4623 mov r3, r4 + 800627e: 463a mov r2, r7 + 8006280: 4629 mov r1, r5 + 8006282: 4628 mov r0, r5 + 8006284: f7ff fb7e bl 8005984 + + /* If an RNG function was specified, try to get a random initial Z value to improve + protection against side-channel attacks. */ + if (g_rng_function) { + 8006288: 4b18 ldr r3, [pc, #96] ; (80062ec ) + 800628a: 681f ldr r7, [r3, #0] + uECC_vli_bytesToNative(public, public_key, num_bytes); + uECC_vli_bytesToNative(public + num_words, public_key + num_bytes, num_bytes); + + /* Regularize the bitcount for the private key so that attackers cannot use a side channel + attack to learn the number of leading zeros. */ + carry = regularize_k(private, private, tmp, curve); + 800628c: 4605 mov r5, r0 + + /* If an RNG function was specified, try to get a random initial Z value to improve + protection against side-channel attacks. */ + if (g_rng_function) { + 800628e: b157 cbz r7, 80062a6 + if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) { + 8006290: ab24 add r3, sp, #144 ; 0x90 + 8006292: eb03 0380 add.w r3, r3, r0, lsl #2 + 8006296: 464a mov r2, r9 + 8006298: f853 7c88 ldr.w r7, [r3, #-136] + 800629c: 1d21 adds r1, r4, #4 + 800629e: 4638 mov r0, r7 + 80062a0: f7ff ff2e bl 8006100 + 80062a4: b1f8 cbz r0, 80062e6 + return 0; + } + initial_Z = p2[carry]; + } + + EccPoint_mult(public, public, p2[!carry], initial_Z, curve->num_n_bits + 1, curve); + 80062a6: fab5 f085 clz r0, r5 + 80062aa: ab24 add r3, sp, #144 ; 0x90 + 80062ac: 0940 lsrs r0, r0, #5 + 80062ae: eb03 0080 add.w r0, r3, r0, lsl #2 + 80062b2: 8863 ldrh r3, [r4, #2] + 80062b4: 9401 str r4, [sp, #4] + 80062b6: 3301 adds r3, #1 + 80062b8: b21b sxth r3, r3 + 80062ba: 9300 str r3, [sp, #0] + 80062bc: a914 add r1, sp, #80 ; 0x50 + 80062be: 463b mov r3, r7 + 80062c0: f850 2c88 ldr.w r2, [r0, #-136] + 80062c4: 4608 mov r0, r1 + 80062c6: f7ff fda8 bl 8005e1a + uECC_vli_nativeToBytes(secret, num_bytes, public); + 80062ca: aa14 add r2, sp, #80 ; 0x50 + 80062cc: 4631 mov r1, r6 + 80062ce: 4640 mov r0, r8 + 80062d0: f7ff faa1 bl 8005816 + return !EccPoint_isZero(public, curve); + 80062d4: 7821 ldrb r1, [r4, #0] + 80062d6: 0049 lsls r1, r1, #1 + 80062d8: b249 sxtb r1, r1 + 80062da: a814 add r0, sp, #80 ; 0x50 + 80062dc: f7ff f951 bl 8005582 + 80062e0: fab0 f080 clz r0, r0 + 80062e4: 0940 lsrs r0, r0, #5 +} + 80062e6: b024 add sp, #144 ; 0x90 + 80062e8: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 80062ec: 10006344 .word 0x10006344 + +080062f0 : + +#if uECC_SUPPORT_COMPRESSED_POINT +void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve) { + 80062f0: b530 push {r4, r5, lr} + wordcount_t i; + for (i = 0; i < curve->num_bytes; ++i) { + 80062f2: 2400 movs r4, #0 + 80062f4: b2e3 uxtb r3, r4 + 80062f6: f992 5001 ldrsb.w r5, [r2, #1] + 80062fa: b25b sxtb r3, r3 + 80062fc: 42ab cmp r3, r5 + 80062fe: f104 0401 add.w r4, r4, #1 + 8006302: da03 bge.n 800630c + compressed[i+1] = public_key[i]; + 8006304: 5cc5 ldrb r5, [r0, r3] + 8006306: 440b add r3, r1 + 8006308: 705d strb r5, [r3, #1] + 800630a: e7f3 b.n 80062f4 + } + compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01); + 800630c: eb00 0045 add.w r0, r0, r5, lsl #1 + 8006310: f810 3c01 ldrb.w r3, [r0, #-1] + 8006314: f003 0301 and.w r3, r3, #1 + 8006318: 3302 adds r3, #2 + 800631a: 700b strb r3, [r1, #0] + 800631c: bd30 pop {r4, r5, pc} + +0800631e : +} + +void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) { + 800631e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + uECC_word_t point[uECC_MAX_WORDS * 2]; + uECC_word_t *y = point + curve->num_words; + 8006322: f992 7000 ldrsb.w r7, [r2] + compressed[i+1] = public_key[i]; + } + compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01); +} + +void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) { + 8006326: b090 sub sp, #64 ; 0x40 + 8006328: 4614 mov r4, r2 + 800632a: 4680 mov r8, r0 + uECC_word_t point[uECC_MAX_WORDS * 2]; + uECC_word_t *y = point + curve->num_words; + 800632c: eb0d 0587 add.w r5, sp, r7, lsl #2 + uECC_vli_bytesToNative(point, compressed + 1, curve->num_bytes); + 8006330: f992 2001 ldrsb.w r2, [r2, #1] + compressed[i+1] = public_key[i]; + } + compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01); +} + +void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) { + 8006334: 460e mov r6, r1 + uECC_word_t point[uECC_MAX_WORDS * 2]; + uECC_word_t *y = point + curve->num_words; + uECC_vli_bytesToNative(point, compressed + 1, curve->num_bytes); + 8006336: 1c41 adds r1, r0, #1 + 8006338: 4668 mov r0, sp + 800633a: f7ff fa80 bl 800583e + curve->x_side(y, point, curve); + 800633e: 4622 mov r2, r4 + 8006340: f8d4 30ac ldr.w r3, [r4, #172] ; 0xac + 8006344: 4669 mov r1, sp + 8006346: 4628 mov r0, r5 + 8006348: 4798 blx r3 + curve->mod_sqrt(y, curve); + 800634a: f8d4 30a8 ldr.w r3, [r4, #168] ; 0xa8 + 800634e: 4621 mov r1, r4 + 8006350: 4628 mov r0, r5 + 8006352: 4798 blx r3 + + if ((y[0] & 0x01) != (compressed[0] & 0x01)) { + 8006354: f898 2000 ldrb.w r2, [r8] + 8006358: f85d 3027 ldr.w r3, [sp, r7, lsl #2] + 800635c: 4053 eors r3, r2 + 800635e: 07db lsls r3, r3, #31 + 8006360: d504 bpl.n 800636c + uECC_vli_sub(y, curve->p, y, curve->num_words); + 8006362: 462a mov r2, r5 + 8006364: 1d21 adds r1, r4, #4 + 8006366: 4628 mov r0, r5 + 8006368: f7ff fb33 bl 80059d2 + } + + uECC_vli_nativeToBytes(public_key, curve->num_bytes, point); + 800636c: 466a mov r2, sp + 800636e: f994 1001 ldrsb.w r1, [r4, #1] + 8006372: 4630 mov r0, r6 + 8006374: f7ff fa4f bl 8005816 + uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y); + 8006378: f994 1001 ldrsb.w r1, [r4, #1] + 800637c: 462a mov r2, r5 + 800637e: 1870 adds r0, r6, r1 + 8006380: f7ff fa49 bl 8005816 +} + 8006384: b010 add sp, #64 ; 0x40 + 8006386: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +0800638a : +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { + 800638a: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + 800638e: 780e ldrb r6, [r1, #0] + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + 8006390: b2f5 uxtb r5, r6 + uECC_vli_nativeToBytes(public_key, curve->num_bytes, point); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y); +} +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { + 8006392: 460f mov r7, r1 + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + 8006394: 0069 lsls r1, r5, #1 + uECC_vli_nativeToBytes(public_key, curve->num_bytes, point); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y); +} +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { + 8006396: b090 sub sp, #64 ; 0x40 + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + 8006398: b249 sxtb r1, r1 + uECC_vli_nativeToBytes(public_key, curve->num_bytes, point); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y); +} +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { + 800639a: 4680 mov r8, r0 + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + 800639c: f7ff f8f1 bl 8005582 + 80063a0: 4604 mov r4, r0 + 80063a2: bb98 cbnz r0, 800640c + return 0; + } + + /* x and y must be smaller than p. */ + if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || + 80063a4: f107 0a04 add.w sl, r7, #4 + 80063a8: b276 sxtb r6, r6 + 80063aa: 4632 mov r2, r6 + 80063ac: 4641 mov r1, r8 + 80063ae: 4650 mov r0, sl + 80063b0: f7ff f92f bl 8005612 + 80063b4: 2801 cmp r0, #1 + 80063b6: d12b bne.n 8006410 + uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { + 80063b8: eb08 0986 add.w r9, r8, r6, lsl #2 + 80063bc: 4632 mov r2, r6 + 80063be: 4649 mov r1, r9 + 80063c0: 4650 mov r0, sl + 80063c2: f7ff f926 bl 8005612 + if (EccPoint_isZero(point, curve)) { + return 0; + } + + /* x and y must be smaller than p. */ + if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || + 80063c6: 2801 cmp r0, #1 + 80063c8: d122 bne.n 8006410 + uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { + return 0; + } + + uECC_vli_modSquare_fast(tmp1, point + num_words, curve); + 80063ca: 463a mov r2, r7 + 80063cc: 4649 mov r1, r9 + 80063ce: 4668 mov r0, sp + 80063d0: f7ff f9fe bl 80057d0 + curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ + 80063d4: f8d7 30ac ldr.w r3, [r7, #172] ; 0xac + 80063d8: a808 add r0, sp, #32 + 80063da: 463a mov r2, r7 + 80063dc: 4641 mov r1, r8 + 80063de: 4798 blx r3 +uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t diff = 0; + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + 80063e0: 1e6b subs r3, r5, #1 + 80063e2: b2db uxtb r3, r3 +/* Constant-time comparison function - secure way to compare long integers */ +/* Returns one if left == right, zero otherwise. */ +uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t diff = 0; + 80063e4: 4620 mov r0, r4 + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + 80063e6: b25a sxtb r2, r3 + 80063e8: 2a00 cmp r2, #0 + 80063ea: db0b blt.n 8006404 + diff |= (left[i] ^ right[i]); + 80063ec: a910 add r1, sp, #64 ; 0x40 + 80063ee: eb01 0282 add.w r2, r1, r2, lsl #2 + 80063f2: 3b01 subs r3, #1 + 80063f4: f852 1c40 ldr.w r1, [r2, #-64] + 80063f8: f852 2c20 ldr.w r2, [r2, #-32] + 80063fc: 404a eors r2, r1 + 80063fe: 4310 orrs r0, r2 + 8006400: b2db uxtb r3, r3 + 8006402: e7f0 b.n 80063e6 + + uECC_vli_modSquare_fast(tmp1, point + num_words, curve); + curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ + + /* Make sure that y^2 == x^3 + ax + b */ + return (int)(uECC_vli_equal(tmp1, tmp2, num_words)); + 8006404: fab0 f080 clz r0, r0 + 8006408: 0940 lsrs r0, r0, #5 + 800640a: e002 b.n 8006412 + uECC_word_t tmp2[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + return 0; + 800640c: 2000 movs r0, #0 + 800640e: e000 b.n 8006412 + 8006410: 4620 mov r0, r4 + uECC_vli_modSquare_fast(tmp1, point + num_words, curve); + curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ + + /* Make sure that y^2 == x^3 + ax + b */ + return (int)(uECC_vli_equal(tmp1, tmp2, num_words)); +} + 8006412: b010 add sp, #64 ; 0x40 + 8006414: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +08006418 : + +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) { + 8006418: b530 push {r4, r5, lr} + 800641a: 460c mov r4, r1 + 800641c: b091 sub sp, #68 ; 0x44 + 800641e: 4605 mov r5, r0 + uECC_word_t public[uECC_MAX_WORDS * 2]; + + uECC_vli_bytesToNative(public, public_key, curve->num_bytes); + 8006420: f991 2001 ldrsb.w r2, [r1, #1] + 8006424: 4601 mov r1, r0 + 8006426: 4668 mov r0, sp + 8006428: f7ff fa09 bl 800583e + uECC_vli_bytesToNative( + 800642c: f994 2001 ldrsb.w r2, [r4, #1] + 8006430: f994 0000 ldrsb.w r0, [r4] + 8006434: 18a9 adds r1, r5, r2 + 8006436: eb0d 0080 add.w r0, sp, r0, lsl #2 + 800643a: f7ff fa00 bl 800583e + public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes); + return uECC_valid_point(public, curve); + 800643e: 4621 mov r1, r4 + 8006440: 4668 mov r0, sp + 8006442: f7ff ffa2 bl 800638a +} + 8006446: b011 add sp, #68 ; 0x44 + 8006448: bd30 pop {r4, r5, pc} + +0800644a : + +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) { + 800644a: b5f0 push {r4, r5, r6, r7, lr} + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t public[uECC_MAX_WORDS * 2]; + + uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + 800644c: f9b2 3002 ldrsh.w r3, [r2, #2] + uECC_vli_bytesToNative( + public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes); + return uECC_valid_point(public, curve); +} + +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) { + 8006450: b099 sub sp, #100 ; 0x64 + 8006452: 4616 mov r6, r2 + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t public[uECC_MAX_WORDS * 2]; + + uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + 8006454: 3307 adds r3, #7 + uECC_vli_bytesToNative( + public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes); + return uECC_valid_point(public, curve); +} + +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) { + 8006456: 460f mov r7, r1 + uECC_word_t private[uECC_MAX_WORDS]; + uECC_word_t public[uECC_MAX_WORDS * 2]; + + uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + 8006458: 2208 movs r2, #8 + 800645a: 4601 mov r1, r0 + 800645c: fb93 f2f2 sdiv r2, r3, r2 + 8006460: 4668 mov r0, sp + 8006462: f7ff f9ec bl 800583e + + /* Make sure the private key is in the range [1, n-1]. */ + if (uECC_vli_isZero(private, BITS_TO_WORDS(curve->num_n_bits))) { + 8006466: f9b6 5002 ldrsh.w r5, [r6, #2] + 800646a: 2320 movs r3, #32 + 800646c: 351f adds r5, #31 + 800646e: fb95 f5f3 sdiv r5, r5, r3 + 8006472: b26d sxtb r5, r5 + 8006474: 4629 mov r1, r5 + 8006476: 4668 mov r0, sp + 8006478: f7ff f883 bl 8005582 + 800647c: b108 cbz r0, 8006482 + return 0; + 800647e: 2000 movs r0, #0 + 8006480: e02e b.n 80064e0 +/* Returns sign of left - right, in constant time. */ +uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + 8006482: 466a mov r2, sp + 8006484: f106 0124 add.w r1, r6, #36 ; 0x24 + 8006488: a808 add r0, sp, #32 + 800648a: f7ff faa2 bl 80059d2 + uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + 800648e: 4629 mov r1, r5 +/* Returns sign of left - right, in constant time. */ +uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + 8006490: 4604 mov r4, r0 + uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + 8006492: a808 add r0, sp, #32 + 8006494: f7ff f875 bl 8005582 + /* Make sure the private key is in the range [1, n-1]. */ + if (uECC_vli_isZero(private, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (uECC_vli_cmp(curve->n, private, BITS_TO_WORDS(curve->num_n_bits)) != 1) { + 8006498: 3400 adds r4, #0 + 800649a: bf18 it ne + 800649c: 2401 movne r4, #1 + 800649e: 0064 lsls r4, r4, #1 + 80064a0: 2800 cmp r0, #0 + 80064a2: bf14 ite ne + 80064a4: 4260 negne r0, r4 + 80064a6: f1c4 0001 rsbeq r0, r4, #1 + 80064aa: b2c4 uxtb r4, r0 + 80064ac: 2c01 cmp r4, #1 + 80064ae: d1e6 bne.n 800647e + return 0; + } + + /* Compute public key. */ + if (!EccPoint_compute_public_key(public, private, curve)) { + 80064b0: 4632 mov r2, r6 + 80064b2: 4669 mov r1, sp + 80064b4: a808 add r0, sp, #32 + 80064b6: f7ff fd81 bl 8005fbc + 80064ba: 2800 cmp r0, #0 + 80064bc: d0df beq.n 800647e + return 0; + } + + uECC_vli_nativeToBytes(public_key, curve->num_bytes, public); + 80064be: aa08 add r2, sp, #32 + 80064c0: f996 1001 ldrsb.w r1, [r6, #1] + 80064c4: 4638 mov r0, r7 + 80064c6: f7ff f9a6 bl 8005816 + uECC_vli_nativeToBytes( + 80064ca: f996 2000 ldrsb.w r2, [r6] + 80064ce: f996 1001 ldrsb.w r1, [r6, #1] + 80064d2: ab08 add r3, sp, #32 + 80064d4: 1878 adds r0, r7, r1 + 80064d6: eb03 0282 add.w r2, r3, r2, lsl #2 + 80064da: f7ff f99c bl 8005816 + public_key + curve->num_bytes, curve->num_bytes, public + curve->num_words); + return 1; + 80064de: 4620 mov r0, r4 +} + 80064e0: b019 add sp, #100 ; 0x64 + 80064e2: bdf0 pop {r4, r5, r6, r7, pc} + +080064e4 : + +int uECC_verify(const uint8_t *public_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *signature, + uECC_Curve curve) { + 80064e4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 80064e8: b0fd sub sp, #500 ; 0x1f4 + 80064ea: 461d mov r5, r3 + 80064ec: 9c86 ldr r4, [sp, #536] ; 0x218 + 80064ee: 9106 str r1, [sp, #24] + const uECC_word_t *points[4]; + const uECC_word_t *point; + bitcount_t num_bits; + bitcount_t i; + uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + 80064f0: 7823 ldrb r3, [r4, #0] + 80064f2: 9302 str r3, [sp, #8] + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + 80064f4: f9b4 3002 ldrsh.w r3, [r4, #2] + +int uECC_verify(const uint8_t *public_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *signature, + uECC_Curve curve) { + 80064f8: 9207 str r2, [sp, #28] + const uECC_word_t *point; + bitcount_t num_bits; + bitcount_t i; + uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + 80064fa: 331f adds r3, #31 + 80064fc: f04f 0a20 mov.w sl, #32 + 8006500: fb93 f3fa sdiv r3, r3, sl + 8006504: b2db uxtb r3, r3 + 8006506: 9304 str r3, [sp, #16] + + rx[num_n_words - 1] = 0; + 8006508: f99d 7010 ldrsb.w r7, [sp, #16] + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + + uECC_vli_bytesToNative(public, public_key, curve->num_bytes); + 800650c: f994 2001 ldrsb.w r2, [r4, #1] + bitcount_t i; + uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + + rx[num_n_words - 1] = 0; + 8006510: f107 38ff add.w r8, r7, #4294967295 ; 0xffffffff + 8006514: ab24 add r3, sp, #144 ; 0x90 + 8006516: 2600 movs r6, #0 + 8006518: f843 6028 str.w r6, [r3, r8, lsl #2] + r[num_n_words - 1] = 0; + 800651c: ab7c add r3, sp, #496 ; 0x1f0 + 800651e: eb03 0388 add.w r3, r3, r8, lsl #2 + s[num_n_words - 1] = 0; + + uECC_vli_bytesToNative(public, public_key, curve->num_bytes); + 8006522: 4601 mov r1, r0 + +int uECC_verify(const uint8_t *public_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *signature, + uECC_Curve curve) { + 8006524: 4681 mov r9, r0 + + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + + uECC_vli_bytesToNative(public, public_key, curve->num_bytes); + 8006526: a85c add r0, sp, #368 ; 0x170 + uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + 8006528: f843 6cc0 str.w r6, [r3, #-192] + s[num_n_words - 1] = 0; + 800652c: f843 6ca0 str.w r6, [r3, #-160] + + uECC_vli_bytesToNative(public, public_key, curve->num_bytes); + 8006530: f7ff f985 bl 800583e + uECC_vli_bytesToNative( + public + num_words, public_key + curve->num_bytes, curve->num_bytes); + 8006534: f99d b008 ldrsb.w fp, [sp, #8] + 8006538: ea4f 038b mov.w r3, fp, lsl #2 + 800653c: 9303 str r3, [sp, #12] + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + + uECC_vli_bytesToNative(public, public_key, curve->num_bytes); + uECC_vli_bytesToNative( + 800653e: 9a03 ldr r2, [sp, #12] + 8006540: ab5c add r3, sp, #368 ; 0x170 + 8006542: 4413 add r3, r2 + 8006544: f994 2001 ldrsb.w r2, [r4, #1] + 8006548: 9305 str r3, [sp, #20] + 800654a: 4618 mov r0, r3 + 800654c: eb09 0102 add.w r1, r9, r2 + 8006550: f7ff f975 bl 800583e + public + num_words, public_key + curve->num_bytes, curve->num_bytes); + uECC_vli_bytesToNative(r, signature, curve->num_bytes); + 8006554: 4629 mov r1, r5 + 8006556: f994 2001 ldrsb.w r2, [r4, #1] + 800655a: a84c add r0, sp, #304 ; 0x130 + 800655c: f7ff f96f bl 800583e + uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); + 8006560: f994 2001 ldrsb.w r2, [r4, #1] + 8006564: a854 add r0, sp, #336 ; 0x150 + 8006566: 18a9 adds r1, r5, r2 + 8006568: f7ff f969 bl 800583e + + /* r, s must not be 0. */ + if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { + 800656c: 4659 mov r1, fp + 800656e: a84c add r0, sp, #304 ; 0x130 + 8006570: f7ff f807 bl 8005582 + 8006574: 4605 mov r5, r0 + 8006576: 2800 cmp r0, #0 + 8006578: f040 8171 bne.w 800685e + 800657c: 4659 mov r1, fp + 800657e: a854 add r0, sp, #336 ; 0x150 + 8006580: f7fe ffff bl 8005582 + 8006584: 4606 mov r6, r0 + 8006586: 2800 cmp r0, #0 + 8006588: f040 8167 bne.w 800685a + return 0; + } + + /* r, s must be < n. */ + if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || + 800658c: f104 0924 add.w r9, r4, #36 ; 0x24 + 8006590: 463a mov r2, r7 + 8006592: a94c add r1, sp, #304 ; 0x130 + 8006594: 4648 mov r0, r9 + 8006596: f7ff f83c bl 8005612 + 800659a: 2801 cmp r0, #1 + 800659c: f040 815f bne.w 800685e + uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { + 80065a0: 463a mov r2, r7 + 80065a2: a954 add r1, sp, #336 ; 0x150 + 80065a4: 4648 mov r0, r9 + 80065a6: f7ff f834 bl 8005612 + if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { + return 0; + } + + /* r, s must be < n. */ + if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || + 80065aa: 2801 cmp r0, #1 + 80065ac: f040 8157 bne.w 800685e + uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { + return 0; + } + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + 80065b0: ad1c add r5, sp, #112 ; 0x70 + 80065b2: 463b mov r3, r7 + 80065b4: 464a mov r2, r9 + 80065b6: a954 add r1, sp, #336 ; 0x150 + 80065b8: 4628 mov r0, r5 + 80065ba: f7ff fbac bl 8005d16 + +static void bits2int(uECC_word_t *native, + const uint8_t *bits, + unsigned bits_size, + uECC_Curve curve) { + unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); + 80065be: f9b4 3002 ldrsh.w r3, [r4, #2] + return 0; + } + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + u1[num_n_words - 1] = 0; + 80065c2: af0c add r7, sp, #48 ; 0x30 + +static void bits2int(uECC_word_t *native, + const uint8_t *bits, + unsigned bits_size, + uECC_Curve curve) { + unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); + 80065c4: 1dda adds r2, r3, #7 + unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits); + 80065c6: 331f adds r3, #31 + 80065c8: fb93 fafa sdiv sl, r3, sl + 80065cc: 9b07 ldr r3, [sp, #28] + return 0; + } + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + u1[num_n_words - 1] = 0; + 80065ce: f847 6028 str.w r6, [r7, r8, lsl #2] + +static void bits2int(uECC_word_t *native, + const uint8_t *bits, + unsigned bits_size, + uECC_Curve curve) { + unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); + 80065d2: f04f 0808 mov.w r8, #8 + 80065d6: fb92 f8f8 sdiv r8, r2, r8 + 80065da: 4543 cmp r3, r8 + 80065dc: bf28 it cs + 80065de: 4643 movcs r3, r8 + unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits); + if (bits_size > num_n_bytes) { + bits_size = num_n_bytes; + } + uECC_vli_clear(native, num_n_words); + 80065e0: fa4f fb8a sxtb.w fp, sl + 80065e4: 4698 mov r8, r3 + 80065e6: 4659 mov r1, fp + 80065e8: 4638 mov r0, r7 + 80065ea: f7fe ffbe bl 800556a + uECC_vli_bytesToNative(native, bits, bits_size); + 80065ee: 4642 mov r2, r8 + 80065f0: 9906 ldr r1, [sp, #24] + 80065f2: 4638 mov r0, r7 + 80065f4: f7ff f923 bl 800583e + if (bits_size * 8 <= (unsigned)curve->num_n_bits) { + 80065f8: f9b4 3002 ldrsh.w r3, [r4, #2] + 80065fc: ea4f 08c8 mov.w r8, r8, lsl #3 + 8006600: 4598 cmp r8, r3 + 8006602: d91d bls.n 8006640 + return; + } + int shift = bits_size * 8 - curve->num_n_bits; + 8006604: ebc3 0808 rsb r8, r3, r8 + 8006608: eb07 0a8a add.w sl, r7, sl, lsl #2 + uECC_word_t carry = 0; + uECC_word_t *ptr = native + num_n_words; + while (ptr-- > native) { + uECC_word_t temp = *ptr; + *ptr = (temp >> shift) | carry; + carry = temp << (uECC_WORD_BITS - shift); + 800660c: f1c8 0120 rsb r1, r8, #32 + return; + } + int shift = bits_size * 8 - curve->num_n_bits; + uECC_word_t carry = 0; + uECC_word_t *ptr = native + num_n_words; + while (ptr-- > native) { + 8006610: 4557 cmp r7, sl + 8006612: d209 bcs.n 8006628 + uECC_word_t temp = *ptr; + 8006614: f85a 2d04 ldr.w r2, [sl, #-4]! + *ptr = (temp >> shift) | carry; + 8006618: fa22 f308 lsr.w r3, r2, r8 + 800661c: 431e orrs r6, r3 + 800661e: f8ca 6000 str.w r6, [sl] + carry = temp << (uECC_WORD_BITS - shift); + 8006622: fa02 f601 lsl.w r6, r2, r1 + 8006626: e7f3 b.n 8006610 + } + + /* Reduce mod curve_n */ + if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) { + 8006628: 465a mov r2, fp + 800662a: 4639 mov r1, r7 + 800662c: 4648 mov r0, r9 + 800662e: f7fe fff0 bl 8005612 + 8006632: 2801 cmp r0, #1 + 8006634: d004 beq.n 8006640 + uECC_vli_sub(native, native, curve->n, num_n_words); + 8006636: 464a mov r2, r9 + 8006638: 4639 mov r1, r7 + 800663a: 4638 mov r0, r7 + 800663c: f7ff f9c9 bl 80059d2 + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + u1[num_n_words - 1] = 0; + bits2int(u1, message_hash, hash_size, curve); + uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */ + 8006640: f99d 8010 ldrsb.w r8, [sp, #16] + 8006644: f8cd 8000 str.w r8, [sp] + 8006648: 4639 mov r1, r7 + 800664a: 4638 mov r0, r7 + 800664c: 464b mov r3, r9 + 800664e: 462a mov r2, r5 + 8006650: f7ff f802 bl 8005658 + uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ + 8006654: 464b mov r3, r9 + 8006656: f8cd 8000 str.w r8, [sp] + 800665a: 462a mov r2, r5 + 800665c: a94c add r1, sp, #304 ; 0x130 + 800665e: a814 add r0, sp, #80 ; 0x50 + 8006660: f7fe fffa bl 8005658 + + /* Calculate sum = G + Q. */ + uECC_vli_set(sum, public, num_words); + 8006664: f99d a008 ldrsb.w sl, [sp, #8] + 8006668: ae6c add r6, sp, #432 ; 0x1b0 + 800666a: 4652 mov r2, sl + 800666c: 4630 mov r0, r6 + 800666e: a95c add r1, sp, #368 ; 0x170 + 8006670: f7fe ffc2 bl 80055f8 + uECC_vli_set(sum + num_words, public + num_words, num_words); + 8006674: 9b03 ldr r3, [sp, #12] + 8006676: 9905 ldr r1, [sp, #20] + 8006678: eb06 0b03 add.w fp, r6, r3 + 800667c: 4652 mov r2, sl + 800667e: 4658 mov r0, fp + 8006680: f7fe ffba bl 80055f8 + uECC_vli_set(tx, curve->G, num_words); + 8006684: f104 0344 add.w r3, r4, #68 ; 0x44 + 8006688: 4652 mov r2, sl + 800668a: 4619 mov r1, r3 + 800668c: a834 add r0, sp, #208 ; 0xd0 + 800668e: 9305 str r3, [sp, #20] + 8006690: f7fe ffb2 bl 80055f8 + uECC_vli_set(ty, curve->G + num_words, num_words); + 8006694: 9b05 ldr r3, [sp, #20] + 8006696: 9903 ldr r1, [sp, #12] + 8006698: 4652 mov r2, sl + 800669a: 1859 adds r1, r3, r1 + 800669c: a83c add r0, sp, #240 ; 0xf0 + 800669e: f7fe ffab bl 80055f8 + uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ + 80066a2: 1d23 adds r3, r4, #4 + 80066a4: 4631 mov r1, r6 + 80066a6: aa34 add r2, sp, #208 ; 0xd0 + 80066a8: 4628 mov r0, r5 + 80066aa: 9306 str r3, [sp, #24] + 80066ac: f7ff fa24 bl 8005af8 + XYcZ_add(tx, ty, sum, sum + num_words, curve); + 80066b0: 465b mov r3, fp + 80066b2: 4632 mov r2, r6 + 80066b4: a93c add r1, sp, #240 ; 0xf0 + 80066b6: a834 add r0, sp, #208 ; 0xd0 + 80066b8: 9400 str r4, [sp, #0] + 80066ba: f7ff fa2b bl 8005b14 + uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ + 80066be: 4653 mov r3, sl + 80066c0: 1d22 adds r2, r4, #4 + 80066c2: 4629 mov r1, r5 + 80066c4: 4628 mov r0, r5 + 80066c6: f7ff fb26 bl 8005d16 + apply_z(sum, sum + num_words, z, curve); + 80066ca: 462a mov r2, r5 + 80066cc: 4659 mov r1, fp + 80066ce: 4630 mov r0, r6 + 80066d0: 4623 mov r3, r4 + 80066d2: f7ff f881 bl 80057d8 + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + 80066d6: 2300 movs r3, #0 + 80066d8: 9308 str r3, [sp, #32] + points[1] = curve->G; + 80066da: 9b05 ldr r3, [sp, #20] + 80066dc: 9309 str r3, [sp, #36] ; 0x24 + points[2] = public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + 80066de: 4641 mov r1, r8 + apply_z(sum, sum + num_words, z, curve); + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + points[1] = curve->G; + points[2] = public; + 80066e0: ab5c add r3, sp, #368 ; 0x170 + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + 80066e2: 4638 mov r0, r7 + apply_z(sum, sum + num_words, z, curve); + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + points[1] = curve->G; + points[2] = public; + 80066e4: 930a str r3, [sp, #40] ; 0x28 + points[3] = sum; + 80066e6: 960b str r6, [sp, #44] ; 0x2c + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + 80066e8: f7fe ff64 bl 80055b4 + 80066ec: 4641 mov r1, r8 + 80066ee: 4606 mov r6, r0 + 80066f0: a814 add r0, sp, #80 ; 0x50 + 80066f2: f7fe ff5f bl 80055b4 + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + 80066f6: 42b0 cmp r0, r6 + 80066f8: bfb8 it lt + 80066fa: 4630 movlt r0, r6 + 80066fc: b286 uxth r6, r0 + 80066fe: f106 38ff add.w r8, r6, #4294967295 ; 0xffffffff + 8006702: fa0f f888 sxth.w r8, r8 + 8006706: 4641 mov r1, r8 + 8006708: 4638 mov r0, r7 + 800670a: f7fe ff49 bl 80055a0 + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + 800670e: 4641 mov r1, r8 + points[2] = public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + 8006710: 1c07 adds r7, r0, #0 + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + 8006712: a814 add r0, sp, #80 ; 0x50 + points[2] = public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + 8006714: bf18 it ne + 8006716: 2701 movne r7, #1 + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + 8006718: f7fe ff42 bl 80055a0 + 800671c: 2800 cmp r0, #0 + 800671e: bf14 ite ne + 8006720: 2302 movne r3, #2 + 8006722: 2300 moveq r3, #0 + points[2] = public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + 8006724: 431f orrs r7, r3 + XYcZ_add(tx, ty, sum, sum + num_words, curve); + uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ + apply_z(sum, sum + num_words, z, curve); + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + 8006726: f10d 0b20 add.w fp, sp, #32 + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point, num_words); + 800672a: f10d 0890 add.w r8, sp, #144 ; 0x90 + points[2] = public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + 800672e: f85b b027 ldr.w fp, [fp, r7, lsl #2] + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point, num_words); + 8006732: 4652 mov r2, sl + 8006734: 4659 mov r1, fp + 8006736: 4640 mov r0, r8 + 8006738: f7fe ff5e bl 80055f8 + uECC_vli_set(ry, point + num_words, num_words); + 800673c: 9b03 ldr r3, [sp, #12] + 800673e: af2c add r7, sp, #176 ; 0xb0 + 8006740: eb0b 0103 add.w r1, fp, r3 + 8006744: 4652 mov r2, sl + 8006746: 4638 mov r0, r7 + 8006748: f7fe ff56 bl 80055f8 + uECC_vli_clear(z, num_words); + 800674c: 4651 mov r1, sl + 800674e: 4628 mov r0, r5 + 8006750: f7fe ff0b bl 800556a + z[0] = 1; + + for (i = num_bits - 2; i >= 0; --i) { + 8006754: 3e02 subs r6, #2 + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point, num_words); + uECC_vli_set(ry, point + num_words, num_words); + uECC_vli_clear(z, num_words); + z[0] = 1; + 8006756: 2301 movs r3, #1 + 8006758: 602b str r3, [r5, #0] + + for (i = num_bits - 2; i >= 0; --i) { + 800675a: b2b6 uxth r6, r6 + 800675c: 46ba mov sl, r7 + 800675e: fa0f fb86 sxth.w fp, r6 + 8006762: f1bb 0f00 cmp.w fp, #0 + 8006766: db46 blt.n 80067f6 + uECC_word_t index; + curve->double_jacobian(rx, ry, z, curve); + 8006768: 4623 mov r3, r4 + 800676a: 462a mov r2, r5 + 800676c: f8d4 70a4 ldr.w r7, [r4, #164] ; 0xa4 + 8006770: 4651 mov r1, sl + 8006772: 4640 mov r0, r8 + 8006774: 47b8 blx r7 + + index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); + 8006776: 4659 mov r1, fp + 8006778: a80c add r0, sp, #48 ; 0x30 + 800677a: f7fe ff11 bl 80055a0 + 800677e: 4659 mov r1, fp + 8006780: 1c07 adds r7, r0, #0 + 8006782: a814 add r0, sp, #80 ; 0x50 + 8006784: bf18 it ne + 8006786: 2701 movne r7, #1 + 8006788: f7fe ff0a bl 80055a0 + 800678c: 2800 cmp r0, #0 + 800678e: bf14 ite ne + 8006790: 2302 movne r3, #2 + 8006792: 2300 moveq r3, #0 + point = points[index]; + 8006794: 431f orrs r7, r3 + 8006796: ab08 add r3, sp, #32 + 8006798: f853 b027 ldr.w fp, [r3, r7, lsl #2] + if (point) { + 800679c: f1bb 0f00 cmp.w fp, #0 + 80067a0: d026 beq.n 80067f0 + uECC_vli_set(tx, point, num_words); + 80067a2: f99d 7008 ldrsb.w r7, [sp, #8] + 80067a6: 4659 mov r1, fp + 80067a8: 463a mov r2, r7 + 80067aa: a834 add r0, sp, #208 ; 0xd0 + 80067ac: f7fe ff24 bl 80055f8 + uECC_vli_set(ty, point + num_words, num_words); + 80067b0: 9b03 ldr r3, [sp, #12] + 80067b2: 463a mov r2, r7 + 80067b4: eb0b 0103 add.w r1, fp, r3 + 80067b8: a83c add r0, sp, #240 ; 0xf0 + 80067ba: f7fe ff1d bl 80055f8 + apply_z(tx, ty, z, curve); + 80067be: 4623 mov r3, r4 + 80067c0: 462a mov r2, r5 + 80067c2: a93c add r1, sp, #240 ; 0xf0 + 80067c4: a834 add r0, sp, #208 ; 0xd0 + 80067c6: f7ff f807 bl 80057d8 + uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ + 80067ca: 9b06 ldr r3, [sp, #24] + 80067cc: aa34 add r2, sp, #208 ; 0xd0 + 80067ce: 4641 mov r1, r8 + 80067d0: a844 add r0, sp, #272 ; 0x110 + 80067d2: f7ff f991 bl 8005af8 + XYcZ_add(tx, ty, rx, ry, curve); + 80067d6: 4653 mov r3, sl + 80067d8: 4642 mov r2, r8 + 80067da: a93c add r1, sp, #240 ; 0xf0 + 80067dc: a834 add r0, sp, #208 ; 0xd0 + 80067de: 9400 str r4, [sp, #0] + 80067e0: f7ff f998 bl 8005b14 + uECC_vli_modMult_fast(z, z, tz, curve); + 80067e4: 4623 mov r3, r4 + 80067e6: aa44 add r2, sp, #272 ; 0x110 + 80067e8: 4629 mov r1, r5 + 80067ea: 4628 mov r0, r5 + 80067ec: f7fe ffe0 bl 80057b0 + 80067f0: 3e01 subs r6, #1 + 80067f2: b2b6 uxth r6, r6 + 80067f4: e7b3 b.n 800675e + } + } + + uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ + 80067f6: f99d 3008 ldrsb.w r3, [sp, #8] + 80067fa: 9a06 ldr r2, [sp, #24] + 80067fc: 4629 mov r1, r5 + 80067fe: 4628 mov r0, r5 + 8006800: f7ff fa89 bl 8005d16 + apply_z(rx, ry, z, curve); + 8006804: 4623 mov r3, r4 + 8006806: 462a mov r2, r5 + 8006808: 4651 mov r1, sl + 800680a: 4640 mov r0, r8 + 800680c: f7fe ffe4 bl 80057d8 + + /* v = x1 (mod n) */ + if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { + 8006810: f99d 2010 ldrsb.w r2, [sp, #16] + 8006814: 4641 mov r1, r8 + 8006816: 4648 mov r0, r9 + 8006818: f7fe fefb bl 8005612 + 800681c: 2801 cmp r0, #1 + 800681e: d004 beq.n 800682a + uECC_vli_sub(rx, rx, curve->n, num_n_words); + 8006820: 464a mov r2, r9 + 8006822: 4641 mov r1, r8 + 8006824: 4640 mov r0, r8 + 8006826: f7ff f8d4 bl 80059d2 +uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t diff = 0; + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + 800682a: 9b02 ldr r3, [sp, #8] + 800682c: 3b01 subs r3, #1 + 800682e: b2db uxtb r3, r3 +/* Constant-time comparison function - secure way to compare long integers */ +/* Returns one if left == right, zero otherwise. */ +uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t diff = 0; + 8006830: 2600 movs r6, #0 + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + 8006832: b25a sxtb r2, r3 + 8006834: 2a00 cmp r2, #0 + 8006836: db0c blt.n 8006852 + diff |= (left[i] ^ right[i]); + 8006838: b212 sxth r2, r2 + 800683a: a97c add r1, sp, #496 ; 0x1f0 + 800683c: eb01 0082 add.w r0, r1, r2, lsl #2 + 8006840: f858 1022 ldr.w r1, [r8, r2, lsl #2] + 8006844: f850 2cc0 ldr.w r2, [r0, #-192] + 8006848: 3b01 subs r3, #1 + 800684a: 404a eors r2, r1 + 800684c: 4316 orrs r6, r2 + 800684e: b2db uxtb r3, r3 + 8006850: e7ef b.n 8006832 + if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { + uECC_vli_sub(rx, rx, curve->n, num_n_words); + } + + /* Accept only if v == r. */ + return (int)(uECC_vli_equal(rx, r, num_words)); + 8006852: fab6 f086 clz r0, r6 + 8006856: 0940 lsrs r0, r0, #5 + 8006858: e002 b.n 8006860 + uECC_vli_bytesToNative(r, signature, curve->num_bytes); + uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); + + /* r, s must not be 0. */ + if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { + return 0; + 800685a: 4628 mov r0, r5 + 800685c: e000 b.n 8006860 + 800685e: 4630 mov r0, r6 + uECC_vli_sub(rx, rx, curve->n, num_n_words); + } + + /* Accept only if v == r. */ + return (int)(uECC_vli_equal(rx, r, num_words)); +} + 8006860: b07d add sp, #500 ; 0x1f4 + 8006862: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +08006866 : + 8006866: b510 push {r4, lr} + 8006868: 3901 subs r1, #1 + 800686a: 4402 add r2, r0 + 800686c: 4290 cmp r0, r2 + 800686e: d007 beq.n 8006880 + 8006870: f810 3b01 ldrb.w r3, [r0], #1 + 8006874: f811 4f01 ldrb.w r4, [r1, #1]! + 8006878: 42a3 cmp r3, r4 + 800687a: d0f7 beq.n 800686c + 800687c: 1b18 subs r0, r3, r4 + 800687e: bd10 pop {r4, pc} + 8006880: 2000 movs r0, #0 + 8006882: bd10 pop {r4, pc} + +08006884 : + 8006884: b510 push {r4, lr} + 8006886: 1e43 subs r3, r0, #1 + 8006888: 440a add r2, r1 + 800688a: 4291 cmp r1, r2 + 800688c: d004 beq.n 8006898 + 800688e: f811 4b01 ldrb.w r4, [r1], #1 + 8006892: f803 4f01 strb.w r4, [r3, #1]! + 8006896: e7f8 b.n 800688a + 8006898: bd10 pop {r4, pc} + +0800689a : + 800689a: 4288 cmp r0, r1 + 800689c: b510 push {r4, lr} + 800689e: eb01 0302 add.w r3, r1, r2 + 80068a2: d801 bhi.n 80068a8 + 80068a4: 1e42 subs r2, r0, #1 + 80068a6: e00b b.n 80068c0 + 80068a8: 4298 cmp r0, r3 + 80068aa: d2fb bcs.n 80068a4 + 80068ac: 1881 adds r1, r0, r2 + 80068ae: 1ad2 subs r2, r2, r3 + 80068b0: 42d3 cmn r3, r2 + 80068b2: d004 beq.n 80068be + 80068b4: f813 4d01 ldrb.w r4, [r3, #-1]! + 80068b8: f801 4d01 strb.w r4, [r1, #-1]! + 80068bc: e7f8 b.n 80068b0 + 80068be: bd10 pop {r4, pc} + 80068c0: 4299 cmp r1, r3 + 80068c2: d004 beq.n 80068ce + 80068c4: f811 4b01 ldrb.w r4, [r1], #1 + 80068c8: f802 4f01 strb.w r4, [r2, #1]! + 80068cc: e7f8 b.n 80068c0 + 80068ce: bd10 pop {r4, pc} + +080068d0 : + 80068d0: 4402 add r2, r0 + 80068d2: 4603 mov r3, r0 + 80068d4: 4293 cmp r3, r2 + 80068d6: d002 beq.n 80068de + 80068d8: f803 1b01 strb.w r1, [r3], #1 + 80068dc: e7fa b.n 80068d4 + 80068de: 4770 bx lr + +080068e0 : + 80068e0: b510 push {r4, lr} + 80068e2: 460b mov r3, r1 + 80068e4: b152 cbz r2, 80068fc + 80068e6: 3a01 subs r2, #1 + 80068e8: d006 beq.n 80068f8 + 80068ea: f813 4b01 ldrb.w r4, [r3], #1 + 80068ee: f800 4b01 strb.w r4, [r0], #1 + 80068f2: 2c00 cmp r4, #0 + 80068f4: d1f7 bne.n 80068e6 + 80068f6: e005 b.n 8006904 + 80068f8: 2200 movs r2, #0 + 80068fa: 7002 strb r2, [r0, #0] + 80068fc: f813 2b01 ldrb.w r2, [r3], #1 + 8006900: 2a00 cmp r2, #0 + 8006902: d1fb bne.n 80068fc + 8006904: 1a58 subs r0, r3, r1 + 8006906: 3801 subs r0, #1 + 8006908: bd10 pop {r4, pc} + +0800690a : + 800690a: 4603 mov r3, r0 + 800690c: f813 2b01 ldrb.w r2, [r3], #1 + 8006910: 2a00 cmp r2, #0 + 8006912: d1fb bne.n 800690c + 8006914: 1a18 subs r0, r3, r0 + 8006916: 3801 subs r0, #1 + 8006918: 4770 bx lr + 800691a: 0000 movs r0, r0 + 800691c: 0000 movs r0, r0 + ... + +08006920 <__flash_burn_veneer>: + 8006920: b401 push {r0} + 8006922: 4802 ldr r0, [pc, #8] ; (800692c <__flash_burn_veneer+0xc>) + 8006924: 4684 mov ip, r0 + 8006926: bc01 pop {r0} + 8006928: 4760 bx ip + 800692a: bf00 nop + 800692c: 10006001 .word 0x10006001 + +08006930 <__flash_page_erase_veneer>: + 8006930: b401 push {r0} + 8006932: 4802 ldr r0, [pc, #8] ; (800693c <__flash_page_erase_veneer+0xc>) + 8006934: 4684 mov ip, r0 + 8006936: bc01 pop {r0} + 8006938: 4760 bx ip + 800693a: bf00 nop + 800693c: 10006105 .word 0x10006105 + 8006940: 65737361 .word 0x65737361 + 8006944: 42007472 .word 0x42007472 + 8006948: 32746f6f .word 0x32746f6f + 800694c: 00554644 .word 0x00554644 + +08006950 : + ... + 8006958: 04030201 09080706 ........ + +08006960 : + 8006960: 00000000 04030201 ........ + +08006968 : + 8006968: 000186a0 00030d40 00061a80 000c3500 ....@........5.. + 8006978: 000f4240 001e8480 003d0900 007a1200 @B........=...z. + 8006988: 00f42400 016e3600 01e84800 02dc6c00 .$...6n..H...l.. + 8006998: 00000150 00000001 00000000 00000001 P............... + 80069a8: 00000000 .... + +080069ac : + 80069ac: 227f0021 20ae0700 !..".. + +080069b2 : + 80069b2: 400020ae c83fa8a1 12da00d3 f1d980d5 . .@..?......... + 80069c2: ff8130db 148da6a4 35007faf .0....... + +080069cb : + 80069cb: 0035007f c0078081 00064081 6f808082 ..5......@.....o + 80069db: ffff8200 c0070006 c7c3c189 f0f8dcce ................ + 80069eb: 0068c0e0 07ff7f82 88000680 1c387060 ..h.........`p8. + 80069fb: 0103070e 0050007f 0006f881 40048081 ......P........@ + 8006a0b: 80008083 80844003 048000c0 00808340 .....@......@... + 8006a1b: 840004c0 f04000c0 00094003 0803f881 ......@..@...... + 8006a2b: 00e01084 84400480 80c00080 80834003 ......@......@.. + 8006a3b: 40048000 00348081 10051f81 040f0082 ...@..4......... + 8006a4b: 000f8310 84880347 0f007f84 0f831004 ....G........... + 8006a5b: 10030f00 001f0885 10030f00 00080881 ................ + 8006a6b: 10031f81 00070884 8310040f 041f000f ................ + 8006a7b: 001f8300 8112040f 1b007f13 007f0000 .............. + +08006a89 : + 8006a89: 007f007f 0034007f 000d8081 000d8081 ......4......... + 8006a99: 00628081 01030183 0183000b 000b0103 ..b............. + 8006aa9: 01030183 007f007f 0034007f 38007f00 ..........4.. + +08006ab6 : + 8006ab6: 0038007f 60c0808a 10303060 03181810 ..8....``00..... + 8006ac6: 20308510 6b80c060 fce08400 0007030f ..0 `..k........ + 8006ad6: 07ffff82 07018400 0068e0fc 3c0f0187 ..........h....< + 8006ae6: 8080c060 018c0005 00060703 70c08080 `..............p + 8006af6: 6d010f38 01018e00 02020303 02020606 8..m............ + 8006b06: 01010303 f881005a f8830004 40048000 ....Z..........@ + 8006b16: c0008084 86400380 40000080 0004d840 ......@....@@... + 8006b26: 0803f081 c0001083 c0860004 40400000 ..............@@ + 8006b36: 820003d8 400380c0 80008083 80824003 .......@.....@.. + 8006b46: 880042c0 18180601 0f000106 13831204 .B.............. + 8006b56: 00091f00 00031f81 031f0182 00008301 ................ + 8006b66: 82880347 00047f84 00031f81 00041f81 G............... + 8006b76: 47001f83 84828803 22007f7f 007f0000 ...G.......".. + +08006b84 : + 8006b84: 0035007f 0e80c082 6a800600 ffff8200 ..5........j.... + 8006b94: 80900005 603060c0 63c080c0 30181c37 .....`0`...c7..0 + 8006ba4: 691f3f20 ffff8800 8e8c8080 80058183 ?.i............ + 8006bb4: 800a8181 0056007f 0004f881 c000f884 ......V......... + 8006bc4: 83400380 03800080 c0808540 0380c000 ..@.....@....... + 8006bd4: 00808340 83400400 03800080 f8808740 @.....@.....@... + 8006be4: 40400000 820003d8 400380c0 80008083 ..@@.......@.... + 8006bf4: 80824003 810042c0 8410040f 047f000f .@...B.......... + 8006c04: 07830803 88034700 007f8484 8100061f .....G.......... + 8006c14: 8411030e 0f001f09 08821003 8100041f ................ + 8006c24: 8100031f 8300041f 0347001f 7f848288 ..........G..... + 8006c34: 0022007f 7f007f00 ..".. + +08006c39 : + 8006c39: 007f007f 002b007f 40f04089 0040f040 ......+..@.@@.@. + 8006c49: 0803f000 c0001083 c0840004 03f00000 ................ + 8006c59: 00108308 86400400 40000080 0004d840 ......@....@@... + 8006c69: 0054f881 020f0289 00020f02 01031f01 ..T............. + 8006c79: 0f00008b 100f0810 1f01000f 00830103 ................ + 8006c89: 11030e00 041f0982 041f8100 030f8100 ................ + 8006c99: 7f007f10 2c007f00 007f0000 .......,.. + +08006ca3 : + 8006ca3: 007f007f 0039007f 0803f881 00e01084 ......9......... + 8006cb3: 838804f8 04f80008 6cf88100 031f8100 ...........l.... + 8006cc3: 07088410 00061f00 10040f81 007f0f81 ................ + 8006cd3: 007f007f 7f000039 ....9.. + +08006cda : + 8006cda: 007f007f 002f007f 0804f881 8000f083 ....../......... + 8006cea: 80844004 0380c000 00808440 0005f800 .@......@....... + 8006cfa: 0004c081 8000c083 80824003 880057c0 .........@...W.. + 8006d0a: 0503011f 0f001009 13841204 03047f00 ................ + 8006d1a: 00078408 10030f00 0f000083 08841003 ................ + 8006d2a: 0347001f 7f848288 007f007f 002e007f ..G............. + ... + +08006d3b : + 8006d3b: 007f007f 002b007f 8803f881 0000f085 ......+......... + 8006d4b: 400380c0 00008086 03d84040 04808100 ...@....@@...... + 8006d5b: 00808a40 800000f8 80000040 80834004 @.......@....@.. + 8006d6b: 40038000 50f88082 041f8100 000f8310 ...@...P........ + 8006d7b: 8100091f 8100031f 8a10040f 021f0008 ................ + 8006d8b: 10080403 12040f00 0f001383 08821003 ................ + 8006d9b: 7f007f1f 2b007f00 007f0000 .......+.. + +08006da5 : + 8006da5: 002e007f 00888003 98f09000 1540d0a0 ..............@. + 8006db5: 80808400 180330e0 18031081 80e03084 .....0.......0.. + 8006dc5: 89004480 0c18f0c0 191373e6 89010519 .D.......s...... + 8006dd5: 07030100 000039ef 92001401 f9cdc702 .....9.......... + 8006de5: 783818c8 78381838 f9c81838 0043e7ed ..8x8.8x8.....C. + 8006df5: e03f0f85 000a0180 70c08085 0016023f ..?........p?... + 8006e05: 07fcf883 7e870304 640464fc 03047efc .......~.d.d.~.. + 8006e15: f0fc0783 01840044 06020301 03028306 ....D........... + 8006e25: 82001a01 04060703 04030781 04060781 ................ + 8006e35: 2a030782 03f88100 e0108408 40040000 ...*...........@ + 8006e45: c0008084 83400380 03800080 c0808440 ......@.....@... + 8006e55: 40048000 c0008084 81400380 81000380 ...@......@..... + 8006e65: 81000bf8 830804f0 04000030 00808340 ........0...@... + 8006e75: 840004c0 f04000c0 00034003 d8404083 ......@..@...@@. + 8006e85: 80810003 80844004 0380c000 03808140 .....@......@... + 8006e95: 14f88100 031f8100 07088410 11030e00 ................ + 8006ea5: 001f0984 8300041f 0347001f 7f848488 ..........G..... + 8006eb5: 12040f00 1f001383 1b810008 0f81000b ................ + 8006ec5: 0c831004 11030e00 001f0984 8510030f ................ + 8006ed5: 00001f08 8110030f 81000408 8100031f ................ + 8006ee5: 8310040f 041f000f 031f8100 7f1b8100 ................ + 8006ef5: 00000c00 .... + +08006ef9 : + 8006ef9: 0035007f 00f0f095 6060c080 10103030 ..5.......``00.. + 8006f09: 10101818 60603030 006b80c0 0c040f04 ....00``..k..... + 8006f19: ff820003 840007ff e0fc0f03 c083006c ............l... + 8006f29: 00058080 0603018c 80800006 0f3c70c0 .............p<. + 8006f39: 8e006d01 03030101 06060202 03030202 .m.............. + 8006f49: 00570101 0803f881 00e01084 83400480 ..W...........@. + 8006f59: 04c00080 00c08400 400380c0 80008083 ...........@.... + 8006f69: 80854003 80c000c0 80834003 40040000 .@.......@.....@ + 8006f79: 80008083 80844003 048000f8 00808740 .....@......@... + 8006f89: 48880808 81003c30 8410031f 0f000708 ...H0<.......... + 8006f99: 0f8a1004 08100f00 000f100f 8300041f ................ + 8006fa9: 0347001f 7f848488 00061f00 11030e81 ..G............. + 8006fb9: 001f0984 8410030f 0f001f08 13841204 ................ + 8006fc9: 7f1b0000 00002200 .....".. + +08006fd1 : + 8006fd1: 0039007f c0808085 20036060 20053081 ..9.....``. .0. + 8006fe1: 30103085 0069c060 0e38f08c 0c1871c3 .0.0`.i...8..q.. + 8006ff1: 01030206 82000901 0068c1ff 00ff8285 ..........h..... + 8007001: 000d0100 70c08085 00690f3c 0c070385 .......p<.i..... + 8007011: 04050c08 04030c81 03060685 005b0101 ..............[. + 8007021: 8804f881 00000886 03d84040 80c08200 ........@@...... + 8007031: 808a4003 4040c000 00804080 830004c0 .@....@@.@...... + 8007041: 040000c0 00808440 400380c0 80008083 ....@......@.... + 8007051: 80874004 88080800 00433048 00091f81 .@......H0C..... + 8007061: 00031f81 00061f81 00001f8f 001f0007 ................ + 8007071: 0f08100f 0e000f10 09841103 061f001f ................ + 8007081: 040f8100 00138412 007f1b00 b4000026 ............&.. + +08007090 : + 8007090: 2641cbb4 f36ce1f7 71b4f28f 0123fb1d ..A&..l....q..#. + 80070a0: 66d6760d 6ca38aa7 f6f9539b 0518587b .v.f...l.S..{X.. + 80070b0: e93b0b58 b89fc431 113c0444 470f0896 X.;.1...D.<....G + 80070c0: 37ed2581 4a9e237a 3818b7af da0438ba .%.7z#.J...8.8.. + 80070d0: 1dc8a2d6 df5e811c 6d290ca6 8d8f57b8 ......^...)m.W.. + 80070e0: 9269295e c178d1ce 31d7207b b596a17b ^)i...x.{ .1{... + 80070f0: 0c1bef3d c31a79aa c8c45845 ffeb2d8a =....y..EX...-.. + 8007100: 01829bfe bc5e5f87 4fe5a596 9ffe68c7 ....._^....O.h.. + 8007110: 0166ef42 95cfc456 38f0b5f4 c5261164 B.f.V......8d.&. + 8007120: 66c13999 14120632 689c254c bad38c35 .9.f2...L%.h5... + 8007130: 8cde7824 6cdfab52 7809bfb8 3a63bb03 $x..R..l...x..c: + 8007140: 0ed90111 8f737aa4 7f3b18bf c87b0af0 .....zs...;...{. + 8007150: 56546067 c5ec0c82 0882bc1d ef39c116 g`TV..........9. + 8007160: 32babff5 e35fce7c d7621e74 4cc5fce9 ...2|._.t.b....L + 8007170: 8d11e88a 13c2adc3 2a4f2992 a4f8d2ea .........)O*.... + 8007180: fe7cd5c4 3b450512 07598954 88d7d6da ..|...E;T.Y..... + 8007190: 37cfb143 1f897cd2 f3acfe5b 95fc33ba C..7.|..[....3.. + 80071a0: dde7d981 14ef9525 bb97efdd a7d8f333 ....%.......3... + 80071b0: 977a2b34 73aab3ba 32419de7 17a1fcd8 4+z....s..A2.... + 80071c0: fe0bb566 89214063 8e7b92c9 590bdf72 f...c@!...{.r..Y + ... + 8007210: 6f636e69 2301006e incon..# + +08007218 : + 8007218: 64640103 0e646464 64646464 64646464 ..ddddd.dddddddd + 8007228: 64641a17 64201e0b 32176464 0a646464 ..dd.. ddd.2ddd. + 8007238: 14646464 0d646464 64646464 02646464 ddd.ddd.ddddddd. + 8007248: 64646464 64646464 64646464 73646464 ddddddddddddddds + 8007258: 643a6432 e109303a 2d:d:0. + +0800725f : + 800725f: 005500e1 2d8f0000 438f808f 4300448f ..U....-...C.D.C + 800726f: 478f4400 43c3488f 47c744c4 4d8f48c8 .D.G.H.C.D.G.H.M + 800727f: 0000438f ffffffff 00000000 ffffffff .C.............. + 800728f: 00000000 ffffffff ffffffff ffffffff ................ + 800729f: ffffffff 79706f43 68676972 30322074 ....Copyright 20 + 80072af: 202d3831 43207962 6b6e696f 20657469 18- by Coinkite + 80072bf: 2e636e49 206b7700 6e006c66 6573206f Inc..wk fl.no se + 80072cf: 00000072 r. + +080072d1 : + 80072d1: 00000000 003c0000 01bc005c 01fc01fc ......<.\....... + 80072e1: 019c019c 01fc01fc 04dc03dc 08dc07dc ................ + 80072f1: 01dc01fc 0100003c 12000000 00000000 ....<........... + 8007301: 01000000 08000000 00000000 ........... + +0800730c : + 800730c: 001e0000 0078001e 02580078 02580258 ......x.x.X.X.X. + 800731c: 02580258 0e100e10 0e100e10 0e100e10 X.X............. + 800732c: 0e100e10 0e100e10 38403840 38403840 ........@8@8@8@8 + 800733c: 38403840 38403840 38403840 38403840 @8@8@8@8@8@8@8@8 + 800734c: 38403840 38403840 38403840 38403840 @8@8@8@8@8@8@8@8 + 800735c: 38403840 38403840 38403840 38403840 @8@8@8@8@8@8@8@8 + 800736c: 38403840 @8@8 + +08007370 : + 8007370: 2e302e31 69742031 323d656d 30383130 1.0.1 time=20180 + 8007380: 2e373038 30323131 67203231 6d3d7469 807.112012 git=m + 8007390: 65747361 65364072 34306637 00000034 aster@6e7f044... + 80073a0: 00000200 00000001 00000000 00000001 ................ + 80073b0: 00000000 .... + +080073b4 : + 80073b4: 428a2f98 71374491 b5c0fbcf e9b5dba5 ./.B.D7q........ + 80073c4: 3956c25b 59f111f1 923f82a4 ab1c5ed5 [.V9...Y..?..^.. + 80073d4: d807aa98 12835b01 243185be 550c7dc3 .....[....1$.}.U + 80073e4: 72be5d74 80deb1fe 9bdc06a7 c19bf174 t].r........t... + 80073f4: e49b69c1 efbe4786 0fc19dc6 240ca1cc .i...G.........$ + 8007404: 2de92c6f 4a7484aa 5cb0a9dc 76f988da o,.-..tJ...\...v + 8007414: 983e5152 a831c66d b00327c8 bf597fc7 RQ>.m.1..'....Y. + 8007424: c6e00bf3 d5a79147 06ca6351 14292967 ....G...Qc..g)). + 8007434: 27b70a85 2e1b2138 4d2c6dfc 53380d13 ...'8!...m,M..8S + 8007444: 650a7354 766a0abb 81c2c92e 92722c85 Ts.e..jv.....,r. + 8007454: a2bfe8a1 a81a664b c24b8b70 c76c51a3 ....Kf..p.K..Ql. + 8007464: d192e819 d6990624 f40e3585 106aa070 ....$....5..p.j. + 8007474: 19a4c116 1e376c08 2748774c 34b0bcb5 .....l7.LwH'...4 + 8007484: 391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3 ...9J..NO..[.o.h + 8007494: 748f82ee 78a5636f 84c87814 8cc70208 ...toc.x.x...... + 80074a4: 90befffa a4506ceb bef9a3f7 c67178f2 .....lP......xq. + +080074b4 : + 80074b4: 01002008 fffffc2f fffffffe ffffffff . ../........... + 80074c4: ffffffff ffffffff ffffffff ffffffff ................ + 80074d4: ffffffff d0364141 bfd25e8c af48a03b ....AA6..^..;.H. + 80074e4: baaedce6 fffffffe ffffffff ffffffff ................ + 80074f4: ffffffff 16f81798 59f2815b 2dce28d9 ........[..Y.(.- + 8007504: 029bfcdb ce870b07 55a06295 f9dcbbac .........b.U.... + 8007514: 79be667e fb10d4b8 9c47d08f a6855419 ~f.y......G..T.. + 8007524: fd17b448 0e1108a8 5da4fbfc 26a3c465 H..........]e..& + 8007534: 483ada77 00000007 00000000 00000000 w.:H............ + ... + 8007558: 08006011 080058cb 08005a4f 08005a7d .`...X..OZ..}Z.. + +Disassembly of section .relocate: + +10006000 : +// + __attribute__((section(".ramfunc"))) + __attribute__((noinline)) + int +flash_burn(uint32_t address, uint64_t val) +{ +10006000: b530 push {r4, r5, lr} + __attribute__((section(".ramfunc"))) + __attribute__((always_inline)) + static inline uint32_t +_flash_wait_done(void) +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { +10006002: 4d3f ldr r5, [pc, #252] ; (10006100 ) +10006004: 692c ldr r4, [r5, #16] +10006006: 493e ldr r1, [pc, #248] ; (10006100 ) +10006008: 03e4 lsls r4, r4, #15 +1000600a: d4fb bmi.n 10006004 + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || +1000600c: 690c ldr r4, [r1, #16] +1000600e: 07a5 lsls r5, r4, #30 +10006010: d41e bmi.n 10006050 +10006012: 690c ldr r4, [r1, #16] +10006014: 0724 lsls r4, r4, #28 +10006016: d41b bmi.n 10006050 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +10006018: 690c ldr r4, [r1, #16] +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || +1000601a: 06e5 lsls r5, r4, #27 +1000601c: d418 bmi.n 10006050 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +1000601e: 690c ldr r4, [r1, #16] +10006020: 06a4 lsls r4, r4, #26 +10006022: d415 bmi.n 10006050 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +10006024: 690c ldr r4, [r1, #16] + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +10006026: 0665 lsls r5, r4, #25 +10006028: d412 bmi.n 10006050 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +1000602a: 690c ldr r4, [r1, #16] +1000602c: 0624 lsls r4, r4, #24 +1000602e: d40f bmi.n 10006050 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +10006030: 690c ldr r4, [r1, #16] + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +10006032: 05e5 lsls r5, r4, #23 +10006034: d40c bmi.n 10006050 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +10006036: 690c ldr r4, [r1, #16] +10006038: 05a4 lsls r4, r4, #22 +1000603a: d409 bmi.n 10006050 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +1000603c: 6909 ldr r1, [r1, #16] + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +1000603e: 0449 lsls r1, r1, #17 +10006040: d406 bmi.n 10006050 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +10006042: 492f ldr r1, [pc, #188] ; (10006100 ) +10006044: 690c ldr r4, [r1, #16] +10006046: 0425 lsls r5, r4, #16 +10006048: d402 bmi.n 10006050 +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +1000604a: 698c ldr r4, [r1, #24] + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +1000604c: 2c00 cmp r4, #0 +1000604e: da02 bge.n 10006056 +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +#endif + ) { + // Save an error code; somewhat random + return FLASH->SR; +10006050: 492b ldr r1, [pc, #172] ; (10006100 ) +10006052: 6909 ldr r1, [r1, #16] +10006054: e004 b.n 10006060 + } + + // Check FLASH End of Operation flag + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) { +10006056: 690c ldr r4, [r1, #16] +10006058: 07e4 lsls r4, r4, #31 + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); +1000605a: bf44 itt mi +1000605c: 2401 movmi r4, #1 +1000605e: 610c strmi r4, [r1, #16] + + // just in case? + _flash_wait_done(); + + // clear any and all errors + FLASH->SR = FLASH->SR & 0xffff; +10006060: 4927 ldr r1, [pc, #156] ; (10006100 ) +10006062: 690c ldr r4, [r1, #16] +10006064: b2a4 uxth r4, r4 +10006066: 610c str r4, [r1, #16] + + // disable data cache + __HAL_FLASH_DATA_CACHE_DISABLE(); +10006068: 680c ldr r4, [r1, #0] +1000606a: f424 6480 bic.w r4, r4, #1024 ; 0x400 +1000606e: 600c str r4, [r1, #0] + + // Program double-word (64-bit) at a specified address + // see FLASH_Program_DoubleWord(Address, Data); + + // Set PG bit + SET_BIT(FLASH->CR, FLASH_CR_PG); +10006070: 694c ldr r4, [r1, #20] +10006072: f044 0401 orr.w r4, r4, #1 +10006076: 614c str r4, [r1, #20] + + // Program a double word + *(__IO uint32_t *)(address) = (uint32_t)val; +10006078: 6002 str r2, [r0, #0] + *(__IO uint32_t *)(address+4) = (uint32_t)(val >> 32); +1000607a: 6043 str r3, [r0, #4] + __attribute__((section(".ramfunc"))) + __attribute__((always_inline)) + static inline uint32_t +_flash_wait_done(void) +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { +1000607c: 690a ldr r2, [r1, #16] +1000607e: 4b20 ldr r3, [pc, #128] ; (10006100 ) +10006080: 03d0 lsls r0, r2, #15 +10006082: d4fb bmi.n 1000607c + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || +10006084: 691a ldr r2, [r3, #16] +10006086: 0792 lsls r2, r2, #30 +10006088: d41e bmi.n 100060c8 +1000608a: 691a ldr r2, [r3, #16] +1000608c: 0715 lsls r5, r2, #28 +1000608e: d41b bmi.n 100060c8 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +10006090: 691a ldr r2, [r3, #16] +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || +10006092: 06d4 lsls r4, r2, #27 +10006094: d418 bmi.n 100060c8 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +10006096: 691a ldr r2, [r3, #16] +10006098: 0690 lsls r0, r2, #26 +1000609a: d415 bmi.n 100060c8 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +1000609c: 691a ldr r2, [r3, #16] + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +1000609e: 0651 lsls r1, r2, #25 +100060a0: d412 bmi.n 100060c8 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +100060a2: 691a ldr r2, [r3, #16] +100060a4: 0612 lsls r2, r2, #24 +100060a6: d40f bmi.n 100060c8 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +100060a8: 691a ldr r2, [r3, #16] + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +100060aa: 05d5 lsls r5, r2, #23 +100060ac: d40c bmi.n 100060c8 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +100060ae: 691a ldr r2, [r3, #16] +100060b0: 0594 lsls r4, r2, #22 +100060b2: d409 bmi.n 100060c8 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +100060b4: 691b ldr r3, [r3, #16] + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +100060b6: 0458 lsls r0, r3, #17 +100060b8: d406 bmi.n 100060c8 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +100060ba: 4b11 ldr r3, [pc, #68] ; (10006100 ) +100060bc: 691a ldr r2, [r3, #16] +100060be: 0411 lsls r1, r2, #16 +100060c0: d402 bmi.n 100060c8 +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +100060c2: 699a ldr r2, [r3, #24] + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +100060c4: 2a00 cmp r2, #0 +100060c6: da03 bge.n 100060d0 +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +#endif + ) { + // Save an error code; somewhat random + return FLASH->SR; +100060c8: 4b0d ldr r3, [pc, #52] ; (10006100 ) +100060ca: 6918 ldr r0, [r3, #16] + // Program a double word + *(__IO uint32_t *)(address) = (uint32_t)val; + *(__IO uint32_t *)(address+4) = (uint32_t)(val >> 32); + + rv = _flash_wait_done(); + if(rv) return rv; +100060cc: b128 cbz r0, 100060da +100060ce: bd30 pop {r4, r5, pc} + // Save an error code; somewhat random + return FLASH->SR; + } + + // Check FLASH End of Operation flag + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) { +100060d0: 691a ldr r2, [r3, #16] +100060d2: 07d2 lsls r2, r2, #31 + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); +100060d4: bf44 itt mi +100060d6: 2201 movmi r2, #1 +100060d8: 611a strmi r2, [r3, #16] + + rv = _flash_wait_done(); + if(rv) return rv; + + // If the program operation is completed, disable the PG or FSTPG Bit + CLEAR_BIT(FLASH->CR, FLASH_CR_PG); +100060da: 4b09 ldr r3, [pc, #36] ; (10006100 ) +100060dc: 695a ldr r2, [r3, #20] +100060de: f022 0201 bic.w r2, r2, #1 +100060e2: 615a str r2, [r3, #20] + + // Flush the caches to be sure of data consistency, and reenable. + __HAL_FLASH_DATA_CACHE_RESET(); +100060e4: 681a ldr r2, [r3, #0] +100060e6: f442 5280 orr.w r2, r2, #4096 ; 0x1000 +100060ea: 601a str r2, [r3, #0] +100060ec: 681a ldr r2, [r3, #0] +100060ee: f422 5280 bic.w r2, r2, #4096 ; 0x1000 +100060f2: 601a str r2, [r3, #0] + __HAL_FLASH_DATA_CACHE_ENABLE(); +100060f4: 681a ldr r2, [r3, #0] +100060f6: f442 6280 orr.w r2, r2, #1024 ; 0x400 +100060fa: 601a str r2, [r3, #0] + + return 0; +100060fc: 2000 movs r0, #0 +} +100060fe: bd30 pop {r4, r5, pc} +10006100: 40022000 .word 0x40022000 + +10006104 : +// + __attribute__((section(".ramfunc"))) + __attribute__((noinline)) + int +flash_page_erase(uint32_t address) +{ +10006104: 0ac0 lsrs r0, r0, #11 +10006106: b510 push {r4, lr} + uint32_t page_num = (address & 0x7ffffff) / FLASH_PAGE_SIZE; // 2k pages +10006108: b284 uxth r4, r0 + + // protect ourselves! + if(page_num < ((BL_FLASH_SIZE + BL_NVROM_SIZE) / FLASH_PAGE_SIZE)) { +1000610a: 2c0f cmp r4, #15 +1000610c: f240 8099 bls.w 10006242 + return 1; + } + + // always operate on both banks. + bool bank2 = (page_num >= 256); + page_num &= 0xff; +10006110: b2c2 uxtb r2, r0 + __attribute__((section(".ramfunc"))) + __attribute__((always_inline)) + static inline uint32_t +_flash_wait_done(void) +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { +10006112: 484d ldr r0, [pc, #308] ; (10006248 ) +10006114: 6901 ldr r1, [r0, #16] +10006116: 4b4c ldr r3, [pc, #304] ; (10006248 ) +10006118: 03c9 lsls r1, r1, #15 +1000611a: d4fb bmi.n 10006114 + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || +1000611c: 6919 ldr r1, [r3, #16] +1000611e: 0788 lsls r0, r1, #30 +10006120: d41e bmi.n 10006160 +10006122: 6919 ldr r1, [r3, #16] +10006124: 0709 lsls r1, r1, #28 +10006126: d41b bmi.n 10006160 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +10006128: 6919 ldr r1, [r3, #16] +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || +1000612a: 06c8 lsls r0, r1, #27 +1000612c: d418 bmi.n 10006160 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +1000612e: 6919 ldr r1, [r3, #16] +10006130: 0689 lsls r1, r1, #26 +10006132: d415 bmi.n 10006160 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +10006134: 6919 ldr r1, [r3, #16] + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +10006136: 0648 lsls r0, r1, #25 +10006138: d412 bmi.n 10006160 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +1000613a: 6919 ldr r1, [r3, #16] +1000613c: 0609 lsls r1, r1, #24 +1000613e: d40f bmi.n 10006160 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +10006140: 6919 ldr r1, [r3, #16] + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +10006142: 05c8 lsls r0, r1, #23 +10006144: d40c bmi.n 10006160 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +10006146: 6919 ldr r1, [r3, #16] +10006148: 0589 lsls r1, r1, #22 +1000614a: d409 bmi.n 10006160 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +1000614c: 691b ldr r3, [r3, #16] + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +1000614e: 045b lsls r3, r3, #17 +10006150: d406 bmi.n 10006160 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +10006152: 4b3d ldr r3, [pc, #244] ; (10006248 ) +10006154: 6919 ldr r1, [r3, #16] +10006156: 0408 lsls r0, r1, #16 +10006158: d402 bmi.n 10006160 +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +1000615a: 6999 ldr r1, [r3, #24] + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +1000615c: 2900 cmp r1, #0 +1000615e: da02 bge.n 10006166 +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +#endif + ) { + // Save an error code; somewhat random + return FLASH->SR; +10006160: 4b39 ldr r3, [pc, #228] ; (10006248 ) +10006162: 691b ldr r3, [r3, #16] +10006164: e004 b.n 10006170 + } + + // Check FLASH End of Operation flag + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) { +10006166: 6919 ldr r1, [r3, #16] +10006168: 07c9 lsls r1, r1, #31 + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); +1000616a: bf44 itt mi +1000616c: 2101 movmi r1, #1 +1000616e: 6119 strmi r1, [r3, #16] + + // just in case? + _flash_wait_done(); + + // clear any and all errors + FLASH->SR = FLASH->SR & 0xffff; +10006170: 4b35 ldr r3, [pc, #212] ; (10006248 ) +10006172: 6919 ldr r1, [r3, #16] +10006174: b289 uxth r1, r1 +10006176: 6119 str r1, [r3, #16] + + // disable data cache + __HAL_FLASH_DATA_CACHE_DISABLE(); +10006178: 6819 ldr r1, [r3, #0] +1000617a: f421 6180 bic.w r1, r1, #1024 ; 0x400 +1000617e: 6019 str r1, [r3, #0] + + // choose appropriate bank to work on. + if(bank2) { + SET_BIT(FLASH->CR, FLASH_CR_BKER); +10006180: 6959 ldr r1, [r3, #20] + + // disable data cache + __HAL_FLASH_DATA_CACHE_DISABLE(); + + // choose appropriate bank to work on. + if(bank2) { +10006182: 2cff cmp r4, #255 ; 0xff + SET_BIT(FLASH->CR, FLASH_CR_BKER); +10006184: bf8c ite hi +10006186: f441 6100 orrhi.w r1, r1, #2048 ; 0x800 + } else { + CLEAR_BIT(FLASH->CR, FLASH_CR_BKER); +1000618a: f421 6100 bicls.w r1, r1, #2048 ; 0x800 +1000618e: 6159 str r1, [r3, #20] + } + + // Proceed to erase the page + MODIFY_REG(FLASH->CR, FLASH_CR_PNB, (page_num << POSITION_VAL(FLASH_CR_PNB))); +10006190: 6959 ldr r1, [r3, #20] +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +10006192: f44f 60ff mov.w r0, #2040 ; 0x7f8 +10006196: fa90 f0a0 rbit r0, r0 +1000619a: fab0 f080 clz r0, r0 +1000619e: f421 61ff bic.w r1, r1, #2040 ; 0x7f8 +100061a2: fa02 f000 lsl.w r0, r2, r0 +100061a6: 4308 orrs r0, r1 +100061a8: 6158 str r0, [r3, #20] + SET_BIT(FLASH->CR, FLASH_CR_PER); +100061aa: 695a ldr r2, [r3, #20] + __attribute__((section(".ramfunc"))) + __attribute__((always_inline)) + static inline uint32_t +_flash_wait_done(void) +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { +100061ac: 4926 ldr r1, [pc, #152] ; (10006248 ) + CLEAR_BIT(FLASH->CR, FLASH_CR_BKER); + } + + // Proceed to erase the page + MODIFY_REG(FLASH->CR, FLASH_CR_PNB, (page_num << POSITION_VAL(FLASH_CR_PNB))); + SET_BIT(FLASH->CR, FLASH_CR_PER); +100061ae: f042 0202 orr.w r2, r2, #2 +100061b2: 615a str r2, [r3, #20] + SET_BIT(FLASH->CR, FLASH_CR_STRT); +100061b4: 695a ldr r2, [r3, #20] +100061b6: f442 3280 orr.w r2, r2, #65536 ; 0x10000 +100061ba: 615a str r2, [r3, #20] + __attribute__((section(".ramfunc"))) + __attribute__((always_inline)) + static inline uint32_t +_flash_wait_done(void) +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { +100061bc: 690a ldr r2, [r1, #16] +100061be: 4b22 ldr r3, [pc, #136] ; (10006248 ) +100061c0: 03d4 lsls r4, r2, #15 +100061c2: d4fb bmi.n 100061bc + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || +100061c4: 691a ldr r2, [r3, #16] +100061c6: 0790 lsls r0, r2, #30 +100061c8: d41e bmi.n 10006208 +100061ca: 691a ldr r2, [r3, #16] +100061cc: 0711 lsls r1, r2, #28 +100061ce: d41b bmi.n 10006208 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +100061d0: 691a ldr r2, [r3, #16] +{ + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || +100061d2: 06d2 lsls r2, r2, #27 +100061d4: d418 bmi.n 10006208 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +100061d6: 691a ldr r2, [r3, #16] +100061d8: 0694 lsls r4, r2, #26 +100061da: d415 bmi.n 10006208 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +100061dc: 691a ldr r2, [r3, #16] + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) { + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || +100061de: 0650 lsls r0, r2, #25 +100061e0: d412 bmi.n 10006208 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +100061e2: 691a ldr r2, [r3, #16] +100061e4: 0611 lsls r1, r2, #24 +100061e6: d40f bmi.n 10006208 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +100061e8: 691a ldr r2, [r3, #16] + // busy wait + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || +100061ea: 05d2 lsls r2, r2, #23 +100061ec: d40c bmi.n 10006208 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +100061ee: 691a ldr r2, [r3, #16] +100061f0: 0594 lsls r4, r2, #22 +100061f2: d409 bmi.n 10006208 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +100061f4: 691b ldr r3, [r3, #16] + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || +100061f6: 0458 lsls r0, r3, #17 +100061f8: d406 bmi.n 10006208 + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +100061fa: 4b13 ldr r3, [pc, #76] ; (10006248 ) +100061fc: 691a ldr r2, [r3, #16] +100061fe: 0411 lsls r1, r2, #16 +10006200: d402 bmi.n 10006208 +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +10006202: 699a ldr r2, [r3, #24] + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +10006204: 2a00 cmp r2, #0 +10006206: da02 bge.n 1000620e +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) +#endif + ) { + // Save an error code; somewhat random + return FLASH->SR; +10006208: 4b0f ldr r3, [pc, #60] ; (10006248 ) +1000620a: 691b ldr r3, [r3, #16] +1000620c: e004 b.n 10006218 + } + + // Check FLASH End of Operation flag + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) { +1000620e: 691a ldr r2, [r3, #16] +10006210: 07d2 lsls r2, r2, #31 + // Clear FLASH End of Operation pending bit + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); +10006212: bf44 itt mi +10006214: 2201 movmi r2, #1 +10006216: 611a strmi r2, [r3, #16] + + // Wait til done + _flash_wait_done(); + + // If the erase operation is completed, disable the PER Bit + CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB)); +10006218: 4b0b ldr r3, [pc, #44] ; (10006248 ) +1000621a: 695a ldr r2, [r3, #20] +1000621c: f422 62ff bic.w r2, r2, #2040 ; 0x7f8 +10006220: f022 0202 bic.w r2, r2, #2 +10006224: 615a str r2, [r3, #20] + + // Flush the caches to be sure of data consistency, and reenable. + __HAL_FLASH_DATA_CACHE_RESET(); +10006226: 681a ldr r2, [r3, #0] +10006228: f442 5280 orr.w r2, r2, #4096 ; 0x1000 +1000622c: 601a str r2, [r3, #0] +1000622e: 681a ldr r2, [r3, #0] +10006230: f422 5280 bic.w r2, r2, #4096 ; 0x1000 +10006234: 601a str r2, [r3, #0] + __HAL_FLASH_DATA_CACHE_ENABLE(); +10006236: 681a ldr r2, [r3, #0] +10006238: f442 6280 orr.w r2, r2, #1024 ; 0x400 +1000623c: 601a str r2, [r3, #0] + + return 0; +1000623e: 2000 movs r0, #0 +10006240: bd10 pop {r4, pc} +{ + uint32_t page_num = (address & 0x7ffffff) / FLASH_PAGE_SIZE; // 2k pages + + // protect ourselves! + if(page_num < ((BL_FLASH_SIZE + BL_NVROM_SIZE) / FLASH_PAGE_SIZE)) { + return 1; +10006242: 2001 movs r0, #1 + // Flush the caches to be sure of data consistency, and reenable. + __HAL_FLASH_DATA_CACHE_RESET(); + __HAL_FLASH_DATA_CACHE_ENABLE(); + + return 0; +} +10006244: bd10 pop {r4, pc} +10006246: bf00 nop +10006248: 40022000 .word 0x40022000 diff --git a/stm32/bootloader/releases/README.md b/stm32/bootloader/releases/README.md index 16f3bad4..31c0b074 100644 --- a/stm32/bootloader/releases/README.md +++ b/stm32/bootloader/releases/README.md @@ -6,3 +6,8 @@ In this directory we will capture public releases of the bootloader. Github is nearly free, so why not capture all the actual bits! +# Change log + +- V1.0.0 - first public version +- V1.0.1 - check signature over firmware before changing main flash +