From 3c8366de2d0535392225ac753c9997b68efc8560 Mon Sep 17 00:00:00 2001 From: kuwoyuki Date: Mon, 2 Dec 2024 19:03:20 +0600 Subject: [PATCH] first commit --- flash_map.png | Bin 0 -> 61896 bytes rom-boot-seq.md | 1048 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1048 insertions(+) create mode 100644 flash_map.png create mode 100644 rom-boot-seq.md diff --git a/flash_map.png b/flash_map.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a3bfd1ea587214da6dda8f6bd95fcd57f5e3b4 GIT binary patch literal 61896 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 z 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 OQ&IjEvP|~PhyMr2f`bqM literal 0 HcmV?d00001 diff --git a/rom-boot-seq.md b/rom-boot-seq.md new file mode 100644 index 0000000..5a8b1d8 --- /dev/null +++ b/rom-boot-seq.md @@ -0,0 +1,1048 @@ +# Ameba-Z (RTL8710BX) + + + +- [Ameba-Z RTL8710BX](#ameba-z-rtl8710bx) + - [Memory Map](#memory-map) + - [RAM Regions 256KB Total at 0x10000000](#ram-regions-256kb-total-at-0x10000000) + - [Flash Regions 1MB Total at 0x08000000](#flash-regions-1mb-total-at-0x08000000) + - [ROM Region](#rom-region) + - [Boot Process](#boot-process) + - [Reset_Handler](#reset_handler) + - [HalResetVsr](#halresetvsr) + - [HW states](#hw-states) + - [Setup](#setup) + - [Boot source select](#boot-source-select) + - [Early Boot Paths pre-populated SRAM](#early-boot-paths-pre-populated-sram) + - [Normal Boot Path](#normal-boot-path) + - [BOOT_ROM_Process](#boot_rom_process) + - [BOOT_ROM_FromFlash](#boot_rom_fromflash) + - [XIP bootloader flash layout](#xip-bootloader-flash-layout) + - [Image Location Calculation](#image-location-calculation) + - [Image Header @ 0x8000C88](#image-header--0x8000c88) + - [Function](#function) + - [TL;DR](#tldr) + - [XIPBOOT structure](#xipboot-structure) + - [Decompiled function](#decompiled-function) + - [FLASH_LoadAndBootImage](#flash_loadandbootimage) + - [control flow graph](#control-flow-graph) + - [check flash encryption in eFuse](#check-flash-encryption-in-efuse) + - [set up pointers to BD_RAM in BOOTLOADER_RAM](#set-up-pointers-to-bd_ram-in-bootloader_ram) + - [flash configuration](#flash-configuration) + - [OTA slot selection](#ota-slot-selection) + - [OTA_SelectBootImage decompiled](#ota_selectbootimage-decompiled) + - [check if OTA1 is forced by GPIO:](#check-if-ota1-is-forced-by-gpio) + - [final image selection and address set](#final-image-selection-and-address-set) + - [OTA1-TEXT header](#ota1-text-header) + - [OTA1-DATA](#ota1-data) + - [jump](#jump) + - [Decompiled function](#decompiled-function) + + + +## Memory Map + +### RAM Regions (256KB Total at 0x10000000) + +| Region | Start Address | End Address | Size | Flags | Description | +| --------- | ------------- | ----------- | ------- | ----- | ------------------ | +| ROM BSS | 0x10000000 | 0x10001FFF | 8KB | RW | ROM BSS Storage | +| IMG1 RAM | 0x10002000 | 0x10004FFF | 12KB | RWX | Boot Loader Code | +| IMG2 RAM | 0x10005000 | 0x1003DFFF | 172KB | RWX | Main Program RAM | +| MSP Stack | 0x1003E000 | 0x1003EFFF | 4KB | WX | Main Stack Pointer | +| RDP | 0x1003F000 | 0x1003FFEF | 4KB-16B | WX | RDP Operations | + +### Flash Regions (1MB Total at 0x08000000) + +| Region | Start Address | End Address | Size | Flags | Description | +| ----------- | ------------- | ----------- | ----- | ----- | --------------- | +| Boot | 0x08000020 | 0x08003FFF | ~16KB | RX | Boot Code | +| System Data | 0x08009000 | 0x08009FFF | 4KB | R | System Data | +| Reserved | 0x0800A000 | 0x0800AFFF | 4KB | R | Reserved Region | +| OTA1 | 0x0800B020 | 0x0807FFFF | 468KB | RX | OTA Region 1 | +| OTA2 | 0x08080020 | 0x080F4FFF | 468KB | RX | OTA Region 2 | + +### ROM Region + +| Region | Start Address | End Address | Size | Flags | Description | +| ------ | ------------- | ----------- | ----- | ----- | ----------- | +| ROM | 0x00000000 | 0x0007FFFF | 512KB | RX | Main ROM | + +Notes: + +- RDP region reserves 16 bytes at the end (0x1003FFF0-0x1003FFFF) +- Flash regions marked with 0x20 offset indicate header reservation +- Image2 RAM combines DATA, BSS, and HEAP sections + +![Flash map](./flash_map.png) + +## Boot Process + +```mermaid +sequenceDiagram + participant CPU as CPU + participant ROM as ROM + participant FLASH as Flash + participant RAM as RAM + participant eFuse as eFuse + + Note over CPU,RAM: Reset Sequence + CPU->>CPU: Reset_Handler + CPU->>CPU: Enable FPU + CPU->>CPU: Set Stack @ 0x1003EFFC + CPU->>ROM: Jump to HalResetVsr + + Note over ROM,RAM: Early Boot Check + ROM->>ROM: Check SOC_FUNC_EN Register + alt Boot from JTAG + ROM->>RAM: IMG2_JTAGPreloadBoot + else Unlock from JTAG + ROM->>RAM: IMG2_QuickValidateAndBoot + else Direct Patch + ROM->>RAM: IMG2_DirectPatchBoot + else Normal Boot + ROM->>ROM: Continue Boot Process + end + + Note over ROM,RAM: Normal Boot Init + ROM->>RAM: Clear Vector Table + ROM->>ROM: CPU_ClkSet + ROM->>ROM: Vector_TableInit + ROM->>ROM: OSC32K_Cmd + ROM->>ROM: Init UART/Debug + + Note over ROM,eFuse: Boot Source Selection + ROM->>eFuse: Read Boot Type + + alt Boot from Flash + ROM->>ROM: BOOT_ROM_FromFlash + ROM->>eFuse: Check Flash Encryption + + Note over ROM,FLASH: Load XIP Bootloader + ROM->>FLASH: Read IMG1_HEADER @ 0x8000C88 + ROM->>RAM: Copy to 0x10002000 (12KB) + ROM->>RAM: Verify Signature + ROM->>RAM: Jump to FLASH_LoadAndBootImage + + Note over RAM,FLASH: Image Selection + RAM->>FLASH: Configure Flash Speed/Mode + RAM->>RAM: IMG2_SetupAddresses + RAM->>FLASH: OTA_SelectBootImage + + alt Valid OTA2 & No GPIO Force + RAM->>FLASH: Load OTA2 + else Otherwise + RAM->>FLASH: Load OTA1 + end + + RAM->>RAM: Decrypt if needed + RAM->>RAM: Jump to Entry @ 0x10005000 + else Other Boot Sources + ROM->>ROM: Handle SDIO/USB/UART/SPI boot + end + + Note over RAM: Final Execution + RAM->>RAM: Start Application +``` + +### `Reset_Handler` + +```nasm +Reset_Handler: + LDR.W R0, =0xE000ED88 ; Enable FPU (CP10/11) + LDR R1, [R0] + ORR.W R1, R1, #0xF00000 + STR R1, [R0] + LDR.W SP, =0x1003EFFC ; Set stack pointer + B.W HalResetVsr ; Jump to init +``` + +### `HalResetVsr` + +#### HW states + +```c +// REG_SOC_FUNC_EN @ 0x40000210 +#define BIT_SOC_BOOT_FROM_JTAG (1 << 31) +#define BIT_SOC_UNLOCK_FROM_JTAG (1 << 30) +#define BIT_SOC_WAKE_FROM_PS (1 << 29) +#define BIT_SOC_PATCH_FUNC0 (1 << 28) +#define BIT_SOC_PATCH_FUNC1 (1 << 27) +#define BIT_SOC_PATCH_FUNC2 (1 << 26) + +// REG_SYS_EFUSE_SYSCFG6 @ 0x40000038 +#define BIT_MASK_SYS_BOOT_TYPE_SEL (3 << 28) +#define BIT_SYS_ICFG2_TEST (1 << 31) + +// Debug configuration +#define BIT_DBG_MSG_EN (1 << 30) // ConfigDebugErr bit 30 +``` + +#### 1. Setup + +```nasm +PUSH {R4-R6,LR} +LDR R3, =__rom_bss_end__ +LDR R5, =NewVectorTable +LDR R2, =(SYSCFG2_ROMINFO_Set+1) +LDR R4, =off_10002000 ; SRAM boot table ptr (may be empty) +SUB SP, SP, #8 +SUBS R5, R3, R5 ; Calculate vector table size +``` + +#### 2. Boot source select + +```c +// hw init first +SYSCFG2_ROMINFO_Set(); +RCC_PeriphClockCmd(0, 0x40u, 1); + +// early boot paths - SRAM must be pre-populated +if (REG_SOC_FUNC_EN & BIT_SOC_BOOT_FROM_JTAG) { // bit 31 + IMG2_JTAGPreloadBoot(); // off_10002004 +} else if (REG_SOC_FUNC_EN & BIT_SOC_UNLOCK_FROM_JTAG) { // bit 30 + IMG2_QuickValidateAndBoot(); // off_10002000 +} else if (REG_SOC_FUNC_EN & BIT_SOC_PATCH_FUNC0) { // bit 28 + IMG2_DirectPatchBoot(); // off_1000200C +} else { + // normal boot path - init everything + + // debug flags setup + ConfigDebugWarn = 0; + ConfigDebugErr = 0xFFFFFFFF; + ConfigDebugInfo = 0; + if (REG_SYS_EFUSE_SYSCFG6 & BIT_SYS_ICFG2_TEST) { + ConfigDebugErr = 0; + } + + // clear vector table + memset(&NewVectorTable, 0, &_rom_bss_end__ - (_UNKNOWN *)&NewVectorTable); + + // core system initialization + CPU_ClkSet(0); + VECTOR_TableInit(&unk_1003EFFC); + OSC32K_Cmd(1); + xtal_freq = XTAL_ClkGet(); + NCO32K_Init(0x8000, xtal_freq, 9, 2); + DIAG_UartInit(1); + BOOT_ROM_ShowBuildInfo(0); + SYSTIMER_Init(); + BOOT_ROM_InitFlash(); + BOOT_ROM_Simulation(); + + if (REG_SOC_FUNC_EN & BIT_SOC_PATCH_FUNC1) { // bit 27 + IMG2_QuickValidateAndBoot(); // off_10002010 + } + + // UART/Debug console handling + if (SYSCFG1_TRP_ICFG() == 2) { + if (SYSCFG1_AutoLoadDone() && (REG_SYS_EFUSE_SYSCFG6 & 0x80000000)) { + if (ConfigDebugErr & 0x40000000) { + DiagPrintf("\rROM BOOT: DEBUG mode \n"); + } + RtlConsolRom(100000); + } + } else { + RtlConsolRom(20); + } + + // check for UART image download + if (SYSCFG1_TRP_UARTImage() || (BKUP_Read() & 8)) { + BKUP_Clear(0, 8); + UARTIMG_Download(2); + + if (!(REG_SOC_FUNC_EN & BIT_SOC_PATCH_FUNC2)) { // bit 26 + goto NORMAL_BOOT; + } + } else if (!(REG_SOC_FUNC_EN & BIT_SOC_PATCH_FUNC2)) { + goto NORMAL_BOOT; + } + + IMG2_QuickValidateAndBoot(); // off_10002008 + +NORMAL_BOOT: + // turn off SWD based on eFuse + uint8_t efuse_val; + EFUSE_OneByteReadROM(REG_SYS_EFUSE_SYSCFG6, 211, &efuse_val, 7); + if (!(efuse_val & 1)) { + PINMUX_SWD_OFF(); + } + + // enable mac and init USB + REG_SOC_HCI_COM_FUNC_EN |= BIT_SOC_HCI_WL_MACON_EN; + BOOT_ROM_InitUsb(); + + // process normal boot + BOOT_ROM_Process(); +} + +while (1); +``` + +#### Early Boot Paths (pre-populated SRAM) + +1. **JTAG Boot** (BIT_SOC_BOOT_FROM_JTAG) + - boot via `IMG2_JTAGPreloadBoot` @ `0x10002004` +2. **JTAG Unlock** (BIT_SOC_UNLOCK_FROM_JTAG) + - boot via `IMG2_QuickValidateAndBoot` @ `0x10002000` +3. **Direct Patch** (BIT_SOC_PATCH_FUNC0) + - boot via `IMG2_DirectPatchBoot` @ `0x1000200C` + +#### Normal Boot Path + +- clear vector table +- **Patch Check** (`BIT_SOC_PATCH_FUNC1`): if set, boot via `IMG2_QuickValidateAndBoot` @ `0x10002000` +- **UART Image Handler** + - check for UART image or backup flag + - if found: + - clear backup flag + - download UART image + - if `BIT_SOC_PATCH_FUNC2` set: boot via`IMG2_QuickValidateAndBoot` @ `0x10002000` + - otherwise: goto normal boot +- disable SWD based if set in eFuse +- enable MAC +- init USB +- `BL BOOT_ROM_Process` + +### `BOOT_ROM_Process` + +Boot types: + +```c +enum _BOOT_TYPE_ { + BOOT_FROM_FLASH = 0, + BOOT_FROM_SDIO = 1, + BOOT_FROM_USB = 2, + BOOT_FROM_UART0 = 3, + BOOT_FROM_UART1 = 4, + BOOT_FROM_SPI = 5, + BOOT_FROM_RSVD = 6, +}; +``` + +```c +int __fastcall BOOT_ROM_Process(uint8_t *config, int param) { + // setup registers and read eFuse + uint32_t *efuse = (uint32_t *)0x40000038; // REG_SYS_EFUSE_SYSCFG6 + uint32_t debug = ConfigDebugErr; + _BOOT_TYPE_ boot_type = (*efuse >> 28) & 7; // BIT_MASK_SYS_BOOT_TYPE_SEL + + // If debug not enabled, direct jump to handler + if (!(debug & 0x80000000)) { // BMI check in asm + // TBB jump table implementation + switch (boot_type) { + case 0: + return BOOT_ROM_FromFlash((int)config, param); + case 1: + return SDIO_Boot_Up(config, param, debug << 1); + case 2: + return USB_Boot_ROM(config, param, debug << 1); + case 3: + return UARTIMG_Download(0, param, debug << 1); + case 4: + return UARTIMG_Download(1, param, debug << 1); + case 5: + return SPI_Boot_ROM(config, param, debug << 1); + default: + return RtlConsolRom(0x186A0, param, debug << 1); + } + } + + // Debug path - print info first + int xtal = XTAL_ClkGet(config, param, debug << 1); + DiagPrintf("\rBOOT TYPE:%x XTAL:%d\n", boot_type, xtal); + + switch (boot_type) { + case 0: + return BOOT_ROM_FromFlash((int)config, param); + case 1: + return SDIO_Boot_Up(config, param, debug << 1); + case 2: + return USB_Boot_ROM(config, param, debug << 1); + case 3: + return UARTIMG_Download(0, param, debug << 1); + case 4: + return UARTIMG_Download(1, param, debug << 1); + case 5: + return SPI_Boot_ROM(config, param, debug << 1); + default: + DiagPrintf("\rNo support boot type !!!!!!!\n"); + return RtlConsolRom(0x186A0, param, debug << 1); + } +} +``` + +### `BOOT_ROM_FromFlash` + +Loads the XIP bootloader RAM section from flash into SRAM + +#### XIP bootloader flash layout + +``` +0x8000000 - Flash Base + 0x8000008: IMG1_HEADER_OFFSET = 0xC68 +``` + +#### Image Location Calculation + +``` +1. Base (0x8000000) + IMG1_HEADER_OFFSET (0xC68) = 0x8000C68 +2. 0x8000C68 + 0x20 = 0x8000C88 (Final image location) +``` + +#### Image Header (@ 0x8000C88) + +``` +0x8000C88-0x8000C8F: Signature (99 99 96 96 3F CC 66 FC) +0x8000C90: Size (0x468) +0x8000C94: Destination (0x10002000) +``` + +#### Function + +1. check encryption in eFuse + +```nasm +LDR R3, =0x40000038 ; Check flash encryption status +LDR R3, [R3] +LSLS R4, R3, #0x12 ; Test bit 13 +BMI init_flash_encryption +``` + +2. calc image location + +```nasm +MOV.W R3, #0x8000000 ; Load flash base +LDR R5, [R3,#(IMG1_HEADER_OFFSET - 0x8000000)] ; Get 0xC68 +ADD.W R5, R5, #0x8000000 ; R5 = 0x8000C68 +ADDS R5, #0x20 ; R5 = 0x8000C88 (Image start) +``` + +3. load image params + +```nasm +LDR.W R8, [R5,#(dword_8000C90 - 0x8000C88)] ; Load size (0x468) +LDR R7, [R5,#(dword_8000C94 - 0x8000C88)] ; Load dest (0x10002000) +``` + +4. `memcpy` + +```c +memcpy(destination_addr, source_addr + 32, size); +// Copies from 0x8000C88 to 0x10002000 +``` + +5. entrypoint selection + +```nasm +LDR R3, [R4,#(off_10002014 - 0x10002000)] ; load FLASH_LoadAndBootImage +LDR R2, =off_10002000 ; base address for fallback +CBNZ R3, loc_5476 ; if primary entry valid, go to exit +LDR R3, [R2] ; load IMG2_QuickValidateAndBoot +loc_5476: ; exit sequence + POP.W {R4-R8,LR} + BX R3 ; jump to entry point + +``` + +#### TL;DR + +1. check flash encryption +2. calculate image location: + - start @ `0x8000000` + - add `IMG1_HEADER_OFFSET` (`0xC68` in factory boot_all.bin) + - add `0x20` to reach image +3. read image metadata from `0x8000C88` +4. copy `0x468` bytes to RAM @ `0x10002000` +5. validate copied data +6. jump to entry point (should be `FLASH_LoadAndBootImage`) + +#### XIPBOOT structure + +``` +Flash: +0x8000000 [Base] + └── +0xC68 [IMG1_HEADER_OFFSET] + └── +0x20 [Header Skip] + └── 0x8000C88 [Image Start] + ├── +0x00: Signature + ├── +0x08: Size (0x468) + └── +0x0C: Destination (0x10002000) +``` + +#### Decompiled function + +```c +__int64 __fastcall BOOT_ROM_FromFlash(int a1, int a2) { + int img_source; // r5 + int img_size; // r8 + int img_dest; // r7 + _BYTE *v5; // r0 + int v6; // r1 + char *pattern_dest; // r3 + void *pattern_src; // r2 + _BYTE *v9; // t1 + int pattern_byte; // t1 + __int64(__fastcall * v11)(int, int, int, int); // r3 + int v13; // r2 + int v14; // r3 + + if ((MEMORY[0x40000038] & 0x2000) != 0) init_flash_encryption(); + img_source = IMG1_HEADER_OFFSET + 0x8000020; + img_size = *(int *)((char *)&dword_8 + IMG1_HEADER_OFFSET + 0x8000020); + img_dest = *(int *)((char *)&dword_C + IMG1_HEADER_OFFSET + 0x8000020); + if ((ConfigDebugErr & 0x40000000) != 0) + DiagPrintf("\rIMG1 DATA[%d:%x]\n", + *(int *)((char *)&dword_8 + IMG1_HEADER_OFFSET + 0x8000020), + *(int *)((char *)&dword_C + IMG1_HEADER_OFFSET + 0x8000020)); + if (img_size == -1 || (a2 = img_dest + 1, img_dest == -1)) { + while (1) { + v13 = 2 * ConfigDebugErr; + if ((ConfigDebugErr & 0x40000000) != 0) + DiagPrintf("\rFlash not Program \n", a2, v13); + RtlConsolRom(100000, a2, v13); + } + } + v5 = (_BYTE *)memcpy(img_dest, img_source + 32, img_size); + pattern_dest = &byte_10002018; + pattern_src = (void *)(unsigned __int8)byte_10002018; + if (byte_10002018 != 35) { + validation_failed: + v14 = ConfigDebugErr & 0x40000000; + if ((ConfigDebugErr & 0x40000000) != 0) { + DiagPrintf("\rImage1 Validation Incorrect !!!\n"); + v14 = ConfigDebugErr & 0x40000000; + } + if (v14) goto LABEL_24; + while (1) { + do RtlConsolRom(100000, v6, pattern_src); + while ((ConfigDebugErr & 0x40000000) == 0); + LABEL_24: + DiagPrintf( + "\rPlease Re-boot and try again, or re-burn the flash image\n"); + } + } + pattern_src = &ROM_IMG1_VALID_PATTEN; + while (1) { + pattern_byte = *((unsigned __int8 *)pattern_src + 1); + pattern_src = (char *)pattern_src + 1; + v6 = pattern_byte; + if (pattern_byte == 255) break; + v9 = (_BYTE *)(unsigned __int8)*++pattern_dest; + v5 = v9; + if (v9 != (_BYTE *)v6) goto validation_failed; + } + if ((ConfigDebugErr & 0x40000000) != 0) + v5 = DiagPrintf("\rIMG1 ENTRY[%x:%x]\n", off_10002014, off_10002000); + v11 = (__int64(__fastcall *)(int, int, int, int))off_10002014; + if (!off_10002014) + v11 = (__int64(__fastcall *)(int, int, int, int))off_10002000; + return v11((int)v5, v6, (int)&off_10002000, (int)v11); +} +``` + +### `FLASH_LoadAndBootImage` + +#### control flow graph + +```mermaid +graph TD + A[Start] --> B[GPIO Setup] + B --> C[Security Config] + C --> D[Memory Setup] + D --> E[Flash Init] + E --> F[OTA Select] + F --> G{Valid OTA2?} + G -->|Yes| H[Load OTA2] + G -->|No| I[Load OTA1] + H --> J[Verify Image] + I --> J + J -->|Valid| K[Boot Image] + J -->|Invalid| L[Error Loop] +``` + +inits gpio: + +```nasm +; Configure SPI Flash pins +MOVS R1, #2 ; Pull control value +MOVS R0, #6 ; Pin 6 +BL j_PAD_PullCtrl ; Set pin pull control +MOVS R1, #2 +MOVS R0, #7 ; Pin 7 +BL j_PAD_PullCtrl +; ... repeats for pins 8,9,10,11,29,30 +``` + +#### check flash encryption in eFuse + +```c +if ((*efuseReg & 0x2000) != 0) { + j_OTF_Mask(0, 0x8000, 2, 1); + set_flash_crypt_masks(); +} +``` + +#### set up pointers to `BD_RAM` in `BOOTLOADER_RAM` + +done by `IMG2_SetupAddresses()` + +```nasm +; setup addresses for IMG2 +LDR R0, =IMG2_VECTOR_TABLE +LDR R1, =0x10005000 ; Vector table address +STR R1, [R0] ; Store vector table addr +ADDS R1, #8 ; Entry point = vector table + 8 +STR R1, [R0,#IMG2_ENTRY] +``` + +-> + +```c +// struct for ota load @ 0x10002430 +typedef struct { + uint32_t *vector_table; // where IMG2 will be loaded in RAM + uint32_t *signature_loc; // points to IMG2 signature location (+8 offset) + uint32_t *ram_start; // working RAM area start + uint32_t *ram_end; // working RAM area end + // a lot of other stuff +} IMG2_Config; + +void IMG2_SetupAddresses(void) { + IMG2_Config *config = (IMG2_Config *)0x10002430; + + config->vector_table = (uint32_t *)0x10005000; // Base RAM address + config->signature_loc = + (uint32_t *)(0x10005000 + 8); // where signature check will be + config->ram_start = (uint32_t *)0x10002464; // Working RAM space + config->ram_end = (uint32_t *)0x10002464; // Working RAM end + + // after fw is copied to RAM, we'd expect to find at 0x10005000: + // - entry_point (sub_8084DDA + 1) // +1 - Thumb + // - 0x803A95D // at 0x04 unrelated but some magic + // number? or address? + // - "RTKWin\0" // signature string +} +``` + +#### flash configuration + +```c +// Configure flash speed and mode +BYTE4(v33[0]) = count_leading_zeros(XIP_SYSTEM_DATA.Spic_Mode); +v14 = count_leading_zeros(XIP_SYSTEM_DATA.Spic_Speed); +if (v14 >= 7) v14 = 6; // Cap max speed + +FLASH_ConfigureClock((char *)v33 + 4); +FLASH_DetectAndInitType(BYTE4(v33[0])); +j_FLASH_ClockDiv(v14); +``` + +#### OTA slot selection + +```mermaid +graph TD + A[Start OTA Selection] --> B{Check Valid_Image2 bitmap} + B -->|OTA2 bit set| C{Check OTA2_FlashAddr} + B -->|OTA1 bit set| D[Select OTA1] + C -->|Valid Address| E{Verify OTA2 Signature} + C -->|Invalid/-1| D + E -->|Valid| F{Check Force GPIO} + E -->|Invalid| D + F -->|GPIO Set| G{Check GPIO State} + F -->|No GPIO/255| H[Select OTA2] + G -->|Force Active| D + G -->|Not Forced| H +``` + +```c +OTA2_FlashAddr = + (_DWORD *)XIP_SYSTEM_DATA.OTA2_FlashAddr; // address of OTA2 in flash +otaSelect = XIP_SYSTEM_DATA.Valid_Image2; // bitmap of valid images +selectedSlot = 0; + +// Find first valid slot +do { + if ((otaSelect >> selectedSlot) & 1) break; + ++selectedSlot; +} while (selectedSlot < 0x20); +``` + +then verify signature: + +```c +v9 = *(_DWORD *)OTA_SIGNATURE_1; +v10 = *OTA2_FlashAddr == *(_DWORD *)OTA_SIGNATURE_1; +if (*OTA2_FlashAddr == *(_DWORD *)OTA_SIGNATURE_1) { + v9 = OTA_SIGNATURE_2; + v10 = *(int *)((char *)&dword_4 + (_DWORD)OTA2_FlashAddr) == OTA_SIGNATURE_2; +} +``` + +#### `OTA_SelectBootImage` decompiled + +```c +void __fastcall OTA_SelectBootImage(_DWORD *destAddr) { + int *v1; // r7 + _DWORD *OTA2_FlashAddr; // r5 + unsigned int otaSelect; // r10 + unsigned int selectedSlot; // r4 + int v6; // r0 + unsigned int v7; // r1 + int v8; // r0 + int v9; // r1 + bool v10; // zf + int v11; // r4 + int v12; // r9 + int v13; // r1 + int v14; // [sp+0h] [bp-38h] BYREF + int v15; // [sp+4h] [bp-34h] + int v16; // [sp+14h] [bp-24h] + + v1 = ConfigDebugErr_ptr; + OTA2_FlashAddr = (_DWORD *)XIP_SYSTEM_DATA.OTA2_FlashAddr; + otaSelect = XIP_SYSTEM_DATA.Valid_Image2; + selectedSlot = 0; + if ((*ConfigDebugErr_ptr & 0x40000000) != 0) { + j_DiagPrintf("\rOTA2 ADDR[%x]\n", XIP_SYSTEM_DATA.OTA2_FlashAddr); + if ((*v1 & 0x40000000) != 0) j_DiagPrintf("\rOTAx SELE[%x]\n", otaSelect); + } + do { + if (((otaSelect >> selectedSlot) & 1) != 0) break; + ++selectedSlot; + } while (selectedSlot < 0x20); + v6 = *v1; + v7 = selectedSlot << 31; + if ((selectedSlot & 1) != 0) { + if ((v6 & 0x40000000) != 0) j_DiagPrintf(aOta2Use, v7); + v8 = *v1; + if (OTA2_FlashAddr == (_DWORD *)-1) { + if ((v8 & 0x40000000) != 0) j_DiagPrintf(aOta2NotInFlash, v7); + } else { + if ((v8 & 0x40000000) != 0) + j_DiagPrintf("\rOTA2 SIGN[%x:%x]\n", *OTA2_FlashAddr, + *(int *)((char *)&dword_4 + (_DWORD)OTA2_FlashAddr)); + v9 = *(_DWORD *)OTA_SIGNATURE_1; + v10 = *OTA2_FlashAddr == *(_DWORD *)OTA_SIGNATURE_1; + if (*OTA2_FlashAddr == *(_DWORD *)OTA_SIGNATURE_1) { + v9 = OTA_SIGNATURE_2; + v10 = *(int *)((char *)&dword_4 + (_DWORD)OTA2_FlashAddr) == + OTA_SIGNATURE_2; + } + if (v10) { + v11 = 0; + if (LOBYTE(XIP_SYSTEM_DATA.OTA1_ForceGpio) == 255) goto LABEL_31; + v16 = XIP_SYSTEM_DATA.OTA1_ForceGpio & 0x3F; + v14 = 0; + if ((XIP_SYSTEM_DATA.OTA1_ForceGpio & 0x80) != 0) { + v15 = 1; + v12 = 1; + } else { + v15 = 2; + v12 = 0; + } + j_GPIO_Init(&v14); + if (j_GPIO_ReadDataBit(v16) == v12) v11 = 1; + j_GPIO_DeInit(v16); + if (!v11) { + LABEL_31: + *destAddr = (char *)OTA2_FlashAddr + + *(int *)((char *)&dword_8 + (_DWORD)OTA2_FlashAddr) + 32; + } else if ((*v1 & 0x40000000) != 0) { + j_DiagPrintf("\rGPIO force OTA1 \n", v13); + } + } else if ((*v1 & 0x40000000) != 0) { + j_DiagPrintf(aOta2SignatureW, v9); + } + } + } else if ((v6 & 0x40000000) != 0) { + j_DiagPrintf(aOta1Use, v7); + } + JUMPOUT(0x8000236); +} +``` + +#### check if OTA1 is forced by GPIO: + +```c +if (LOBYTE(XIP_SYSTEM_DATA.OTA1_ForceGpio) != 255) { // if GPIO force enabled + gpioPin = XIP_SYSTEM_DATA.OTA1_ForceGpio & 0x3F; // get pin number + activeLevel = (XIP_SYSTEM_DATA.OTA1_ForceGpio & 0x80) ? 1 : 0; + + GPIO_Init(&gpioConfig); + if (GPIO_ReadDataBit(gpioPin) == activeLevel) { + forceOTA1 = 1; // force boot OTA1 + } + GPIO_DeInit(gpioPin); +} +``` + +#### final image selection and address set + +```c +if (!forceOTA1 && validOTA2) { + // calculate source address for OTA2 header + *headerAddr = (char *)OTA2_FlashAddr + + *(int *)((char *)&dword_8 + (_DWORD)OTA2_FlashAddr); +} else { + // calculate source address for OTA1 header + *headerAddr = (char *)&IMG2_OTA1_SIGNATURE_STR + + *(int *)((char *)&IMG2_OTA1_SIGNATURE_STR - 24); +} + +// read from header: +destAddr = *(int *)(*headerAddr + 12); // destination from header+12 +size = *(int *)(*headerAddr + 8); // size from header+8 + +// validation (1MB) +if (destAddr == -1 || size > 0x100000) { + // ... + return; +} + +// copy image data that follows the header +memcpy(destAddr, // destination from header + *headerAddr + 32, // source = header + 32 byte header size + size); // size from header +``` + +Example: + +1. Start at `IMG2_OTA1_SIGNATURE_STR` (`0x0800B020`) +2. Get offset at -24 bytes (`0x0800B008`): `0x823AC` + +3. Calculate header location: + `0x0800B020` + `0x823AC` = `0x808D3CC` + +4. From header at `0x808D3CC`: + + - At offset 8 (`0x808D3D4`): Size info (`0x746C`) + - At offset 12 (`0x808D3D8`): Destination = 0x10005000 (RAM address) + +5. Final memcpy: + +```c +memcpy(0x10005000, // destination (from header+12 at 0x808D3D8) + 0x808D3EC, // source (header + 32) + 0x746C) // size 0x746C (from header+8) +``` + +#### OTA1-TEXT header + +``` +seg001:0800B000 OTA1_HEADER DCD 0x35393138, 0x31313738; signature +seg001:0800B000 ; DATA XREF: FLASH_LoadAndBootImage+1AA↑r +seg001:0800B000 ; sub_8076A94+48↓o ... +seg001:0800B008 DCD 0x823AC ; image_size +seg001:0800B00C DCD 0x800B020 ; image_addr +seg001:0800B010 DCD 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF; reserved +seg001:0800B020 IMG2_OTA1_SIGNATURE_STR DCB "Customer Signature-modelxxx",0 +``` + +#### OTA1-DATA + +``` +seg001:0808D3CC DCD 0x35393138, 0x31313738 +seg001:0808D3D4 dword_808D3D4 DCD 0x746C ; DATA XREF: sub_8076A94+54↑r +seg001:0808D3D4 ; sub_80B0534+50↓r +seg001:0808D3D8 DCD unk_10005000 ; RAM destination address!!! +seg001:0808D3DC DCB 0xFF +seg001:0808D3DD DCB 0xFF +seg001:0808D3DE DCB 0xFF +seg001:0808D3DF DCB 0xFF +seg001:0808D3E0 DCB 0xFF +seg001:0808D3E1 DCB 0xFF +seg001:0808D3E2 DCB 0xFF +seg001:0808D3E3 DCB 0xFF +seg001:0808D3E4 DCB 0xFF +seg001:0808D3E5 DCB 0xFF +seg001:0808D3E6 DCB 0xFF +seg001:0808D3E7 DCB 0xFF +seg001:0808D3E8 DCB 0xFF +seg001:0808D3E9 DCB 0xFF +seg001:0808D3EA DCB 0xFF +seg001:0808D3EB DCB 0xFF +seg001:0808D3EC DCD sub_8084DDA+1 +seg001:0808D3F0 DCD 0x803A95D +seg001:0808D3F4 aRtkwin_2 DCB "RTKWin",0 +seg001:0808D3FB DCB 0xFF +``` + +#### jump + +```nasm +LDR.W R0, [R8] ; load address +BLX R0 ; jump to entry point +BL j_BOOT_RunInitializerArray ; this is dead code, since FreeRTOS will never return from the entry point +``` + +#### Decompiled function + +```c +__int64 __fastcall FLASH_LoadAndBootImage(int a1, int a2, int a3, int a4) { + int v4; // r0 + _DWORD *efuseReg; // r5 + int v6; // r4 + _DWORD *ramDest; // r7 + unsigned int *vectorTable; // r8 + int *debugErr; // r5 + int ramSize; // r4 + int v11; // r1 + int v12; // r2 + int v13; // r3 + int v14; // r7 + int v15; // r1 + __int64 v16; // r2 + int *v17; // r4 + int v18; // r0 + int v19; // r6 + int v20; // r11 + bool v21; // zf + bool v22; // zf + int v23; // r0 + int v24; // r7 + int v25; // r1 + unsigned int v26; // r2 + int v27; // r0 + int v28; // r0 + int *v29; // r4 + unsigned int v30; // r1 + int v31; // r0 + _QWORD v33[5]; // [sp+0h] [bp-28h] BYREF + + HIDWORD(v33[0]) = a4; + LODWORD(v33[0]) = 0; + j_PAD_PullCtrl(6, 2); + j_PAD_PullCtrl(7, 2); + j_PAD_PullCtrl(8, 2); + j_PAD_PullCtrl(9, 2); + j_PAD_PullCtrl(10, 2); + j_PAD_PullCtrl(11, 2); + j_PAD_PullCtrl(29, 2); + v4 = j_PAD_PullCtrl(30, 2); + efuseReg = REG_SYS_EFUSE_SYSCFG6; + v6 = *((_DWORD *)REG_SYS_EFUSE_SYSCFG6 + 27); + if (!j_SYSCFG1_TRP_LDOMode(v4)) efuseReg[27] = v6 & 0xFFFFFFFD; + efuseReg[27] &= ~4u; + if ((*efuseReg & 0x2000) != 0) { + j_OTF_Mask(0, 0x8000, 2, 1); + set_flash_crypt_masks(); + } + BYTE4(v33[0]) = 0; + thunk_IMG2_SetupAddresses(); + ramDest = (_DWORD *)IMG2_RAM_START_ptr[0]; + vectorTable = (unsigned int *)*VECTOR_TABLE_ptr; + debugErr = ConfigDebugErr_ptr; + ramSize = *(_DWORD *)IMG2_RAM_END_ptr[0] - *(_DWORD *)IMG2_RAM_START_ptr[0]; + *(_DWORD *)ConfigDebugWarn_ptr[0] = 0; + *(_DWORD *)ConfigDebugInfo_ptr = 0; + *debugErr = -1; + if (!XIP_SYSTEM_DATA.UlogDbgEn) *debugErr = 0; + if ((*debugErr & 0x40000000) != 0) j_DiagPrintf(aImg1Enter); + j__memset(*ramDest, 0, ramSize); + BYTE4(v33[0]) = count_leading_zeros(XIP_SYSTEM_DATA.Spic_Mode); + v14 = count_leading_zeros(XIP_SYSTEM_DATA.Spic_Speed); + if (v14 >= 7) v14 = 6; + FLASH_ConfigureClock((char *)v33 + 4, v11, v12, v13); + if ((*debugErr & 0x40000000) != 0) + j_DiagPrintf("\rread_mode idx:%d, flash_speed idx:%d\n", BYTE4(v33[0]), + v14); + FLASH_DetectAndInitType(BYTE4(v33[0]), v15, v16); + j_FLASH_ClockDiv(v14); + FLASH_SetExtendedConfig(XIP_SYSTEM_DATA.Flash_Status); + v17 = off_80007DC; + v18 = *(int *)((char *)&dword_4 + (_DWORD)(off_80007DC + 2)); + if (v18) j_FLASH_SetStatusBits(v18, 1); + v19 = BYTE4(v33[0]); + byte_25[(_DWORD)v17 + 46] = 0; + v20 = 0; + v21 = v19 == 0; + if (v19) v21 = v19 == 1; + if (v21) { + v20 = 2; + } else { + v22 = v19 == 2; + if (v19 != 2) v22 = v19 == 3; + if (v22) v20 = 1; + } + if (FLASH_CalibrateTimings(v20, v14) == 1) { + if ((*debugErr & 0x40000000) != 0) j_DiagPrintf("\rFLASH CALIB[NEW OK]\n"); + j_FLASH_CalibrationNewCmd(1); + j_FLASH_CalibrationPhaseIdx((unsigned __int8)byte_25[(_DWORD)v17 + 47]); + if (v19) { + switch (v19) { + case 1: + v23 = 107; + break; + case 2: + v23 = 187; + break; + case 3: + v23 = 59; + break; + default: + LABEL_36: + j_FLASH_Init(v20); + goto LABEL_37; + } + } else { + v23 = 235; + } + *(int *)((char *)&dword_8 + (_DWORD)v17) = v23; + goto LABEL_36; + } +LABEL_37: + j_Cache_Enable(1); + v24 = 1; + OTA_SelectBootImage(v33); + if (v27 != 1) { + v25 = *(_DWORD *)&IMG2_OTA1_SIGNATURE_STR_ptr[-24]; + LODWORD(v33[0]) = &IMG2_OTA1_SIGNATURE_STR_ptr[v25]; + v24 = 0; + } + if ((*debugErr & 0x40000000) != 0) + j_DiagPrintf("\rIMG2 DATA[0x%x:%d:0x%x]\n", LODWORD(v33[0]) + 32, + *(_DWORD *)(LODWORD(v33[0]) + 8), + *(_DWORD *)(LODWORD(v33[0]) + 12)); + v28 = *(_DWORD *)(LODWORD(v33[0]) + 12); + if (v28 == -1 || + (v25 = v33[0], v26 = *(_DWORD *)(LODWORD(v33[0]) + 8), v26 > 0x100000)) { + if ((*debugErr & 0x40000000) != 0) j_DiagPrintf("\rIMG2 ADDR Invalid\n"); + goto LABEL_45; + } + j__memcpy(v28, LODWORD(v33[0]) + 32, v26); + v29 = off_8000808; + if ((*debugErr & 0x40000000) != 0) { + j_DiagPrintf("\rIMG2 SIGN[%s(%x)]\n", (const char *)*off_8000808, + *off_8000808); + if ((*debugErr & 0x40000000) != 0) + j_DiagPrintf("\rIMG2 ENTRY[0x%x:0x%x]\n", *VECTOR_TABLE_ptr, + *vectorTable); + } + if (j__strcmp(*v29, aRtkwin_0)) { + if ((*debugErr & 0x40000000) != 0) j_DiagPrintf(aImg2SignInvali); + while (1) + LABEL_45: + j_RtlConsolRom(1000, v25, v26); + } + if (v24) { + v30 = *vectorTable; + if (XIP_SYSTEM_DATA.OTA2_FlashAddr >= *vectorTable) { + while (1) { + if ((*debugErr & 0x40000000) != 0) { + j_DiagPrintf(aOta2ImageError); + if ((*debugErr & 0x40000000) != 0) + j_DiagPrintf( + "\rplease try to rebuild your project to generate OTA2 image " + "again...\n\n\n\n"); + } + j_RtlConsolRom(50000, v30, v26); + } + } + } + FLASH_CheckAndDecryptRDP(); + v31 = ((int (*)(void)) * vectorTable)(); + j_BOOT_RunInitializerArray(v31); + return v33[0]; +} +```