# Flash_Info Protocol Analysis

## Conclusion

`Flash_Info` is the mailbox structure used by the CVD/CodeViser host and the SRAM-resident STM32F103 flash loader. The host does not communicate with the loader through UART, USB, CAN, or another MCU peripheral. It writes this structure directly through JTAG/SWD memory access, starts the CPU at the loader entry point, then reads `Flash_Info.Result`.

The symbol is exported by the AXF:

```text
Flash_Info  0x20000ce4  size 8252
```

The CVD installation also contains the original generic flash-loader framework. In `D:\JnDTech\CVI\CVD\FlashLoader\ST\common.h`, `FLASH_INFO` has the same field layout. The Korean comment in `ST16.c` says the structure is used to exchange host-program data and command values.

## Evidence

### CVD Script

`D:\project\CVD_ALG\stm32F103\STM32F103.csf` configures a custom user loader:

```text
CFlash.DownLoad      ON
CFLash.Base          0x08000000
CFlash.Size          0x00020000
CFlash.RamBase       0x20000000
CFlash.RamSize       0x00005000
CFlash.UserOption    ON
CFlash.UserFilePath ".\STM32_FlashLoader.axf"
DEBUG.DownLoadBuffer 0x800
```

This means CVD downloads the AXF into target RAM at `0x20000000`, then uses it as the flash algorithm for the internal flash range `0x08000000..0x0801ffff`.

### AXF Symbol Table

The ARM toolchain confirms the relevant addresses:

```text
ER_RO                0x20000000  size 0x0cd8
ER_RW                0x20000cd8  size 0x000c
ER_ZI                0x20000ce4  size 0x269c
EraseCounter         0x20000cd8
NbrOfPage            0x20000cdc
FLASHStatus          0x20000ce0
MemoryProgramStatus  0x20000ce1
HSEStartUpStatus     0x20000ce2
Flash_Info           0x20000ce4  size 0x203c
SvsStack             0x20002d20  size 0x0200
__libspace_start     0x20002f20  size 0x0060
__heap_base          0x20002f80
__heap_limit         0x20003180
__initial_sp         0x20003380
```

### CVD FlashLoader Source Match

CVD has generic flash-loader source templates under:

```text
D:\JnDTech\CVI\CVD\FlashLoader\
```

The important files are:

```text
D:\JnDTech\CVI\CVD\FlashLoader\ST\common.h
D:\JnDTech\CVI\CVD\FlashLoader\ST\Buff.c
D:\JnDTech\CVI\CVD\FlashLoader\ST\ST16.c
D:\JnDTech\CVI\CVD\FlashLoader\ST\Init.s
```

`Buff.c` contains:

```c
volatile FLASH_INFO Flash_Info;
```

The generic ST external NOR version uses `BUFFER_SIZE 0x100000`. The STM32F103 loader recovered from this AXF uses `Buf[8192]`, matching `D:\project\Trace32_Alg\trace32_flash\flash\common.h`.

## Structure Layout

For this STM32F103 AXF:

```c
typedef struct {
    uint32_t Command;       // +0x00
    uint32_t Result;        // +0x04
    uint32_t Reserved1[4];  // +0x08
    uint32_t Reserved2;     // +0x18
    uint32_t TargetAddr;    // +0x1c
    uint32_t Length;        // +0x20
    uint32_t Reserved3;     // +0x24
    uint32_t Reserved4;     // +0x28
    uint32_t Reserved5;     // +0x2c
    uint32_t Reserved6;     // +0x30
    uint32_t Reserved7;     // +0x34
    uint32_t Reserved8;     // +0x38
    uint8_t  Buf[8192];     // +0x3c
} FLASH_INFO;
```

Runtime address map:

```text
Flash_Info.Command     0x20000ce4
Flash_Info.Result      0x20000ce8
Flash_Info.TargetAddr  0x20000d00
Flash_Info.Length      0x20000d04
Flash_Info.Buf         0x20000d20
```

Total size:

```text
0x3c + 0x2000 = 0x203c = 8252 bytes
```

## Command Values

The CVD generic header defines:

```c
#define FPROGRAM  0
#define FERASEALL 1
#define FERASESEC 2
#define FREADID   3
```

The recovered `Main()` from this AXF does exactly this:

```c
switch (Flash_Info.Command) {
case 0:
    Program();
    break;
case 1:
    EraseAll();
    break;
case 2:
    EraseSector();
    break;
case 3:
    ReadChipID();
    break;
default:
    Flash_Info.Result = 0;
    break;
}
```

## Host-Side Sequence

### Program

Expected host writes before running `Main()`:

```text
Command    = 0
Result     = usually 0 before run
TargetAddr = flash destination, e.g. 0x08000000
Length     = byte count, normally even
Buf        = payload bytes, up to 8192 bytes
```

Loader behavior:

```c
targetP = Flash_Info.TargetAddr;
srcP = (uint16_t *)Flash_Info.Buf;

for (i = 0; i < Flash_Info.Length; i += 2) {
    FLASHStatus = FLASH_ProgramHalfWord(targetP, srcP);
    targetP += 2;
    srcP++;
}

Flash_Info.Result = 1;
```

Important detail: this AXF's `FLASH_ProgramHalfWord()` takes a pointer to a halfword source buffer, not the usual STM32 SPL signature that takes the halfword value. It reads `*srcP` internally.

This specific AXF does not call `Verification()` after `Program()`. Some related source variants in `trace32_flash\flash\main.c` do call verification, but the binary in `STM32_FlashLoader.axf` does not.

### Erase All

Expected host write:

```text
Command = 1
```

Loader behavior:

```c
NbrOfPage = 128;
for (EraseCounter = 0;
     EraseCounter < NbrOfPage && FLASHStatus == FLASH_COMPLETE;
     EraseCounter++) {
    FLASHStatus = FLASH_ErasePage(0x08000000 + EraseCounter * 0x400);
}
Flash_Info.Result = 1;
```

This is 128 pages * 1024 bytes = 128 KiB, matching STM32F103 medium-density flash size configured by the script:

```text
CFlash.Size 0x00020000
```

### Erase Sector/Page Range

Expected host writes:

```text
Command    = 2
TargetAddr = start address in flash
Length     = byte count
```

Loader behavior:

```c
Flash_Info.Result = 0;

for (i = 0; i < NbrOfPage - 1; i++) {
    if (0x08000000 + (i + 1) * 0x400 > Flash_Info.TargetAddr) {
        break;
    }
}

while (i < NbrOfPage - 1 &&
       FLASHStatus == FLASH_COMPLETE &&
       Flash_Info.TargetAddr + Flash_Info.Length > 0x08000000 + i * 0x400) {
    FLASHStatus = FLASH_ErasePage(0x08000000 + i * 0x400);
    if (FLASHStatus == 0) {
        return;
    }
    i++;
}

Flash_Info.Result = 1;
```

There is no blank-check after erase in this AXF. Again, some related source variants do blank-check, but this binary does not.

### Read ID

Expected host write:

```text
Command = 3
```

Loader behavior:

```c
Flash_Info.Result = 1;
```

Despite the symbol name `ReadChipID`, this STM32F103 internal-flash loader does not read `DBGMCU_IDCODE` or flash size registers. It only returns success.

## How CVD Finds Flash_Info

The robust path is symbol lookup:

1. CVD loads `STM32_FlashLoader.axf`.
2. It parses the ELF symbol table.
3. It finds global object symbol `Flash_Info`.
4. It writes to the symbol address through JTAG/SWD.

This avoids hardcoding `0x20000ce4`. The address is still stable for this exact AXF because there are no relocations and the load address is fixed.

The less robust path would be a hardcoded offset:

```text
Flash_Info = CFlash.RamBase + 0x0ce4
           = 0x20000000 + 0x0ce4
           = 0x20000ce4
```

Given the CVD generic loader source exports the same global variable name, symbol lookup is the likely design.

## Relationship Of trace32_flash

`D:\project\Trace32_Alg\trace32_flash` is useful, but it is not the STM32 peripheral driver library. It is another flash-loader/algorithm workspace and contains a close reconstruction or related source:

```text
D:\project\Trace32_Alg\trace32_flash\flash\common.h
D:\project\Trace32_Alg\trace32_flash\flash\Buff.c
D:\project\Trace32_Alg\trace32_flash\flash\main.c
D:\project\Trace32_Alg\trace32_flash\flash\cvd.c
D:\project\Trace32_Alg\trace32_flash\flash\STM32_FlashLoader.map
```

The map file directly matches this AXF:

```text
Flash_Info 0x20000ce4 size 8252
```

`cvd.c` is especially close to a decompiled version of the current AXF. `main.c` looks like a cleaned-up or modified source variant. One difference is that `main.c` adds verification after programming and erase-sector blank-check, while the actual AXF does not.

## Ghidra Output

Ghidra headless was run successfully with:

```text
D:\Programs\ghidra\support\analyzeHeadless.bat
```

Exported decompiler output:

```text
D:\project\CVD_ALG\stm32F103\recovered\ghidra_decompiled.c
```

Ghidra detected:

```text
Language/Compiler: ARM:LE:32:v8:default
DWARF producers:
  ARM/Thumb C/C++ Compiler, RVCT3.0 [Build 441]
  ARM/Thumb Macro Assembler, RVCT3.0 [Build 441]
```

There were DWARF warnings because this is old RVCT DWARF, but function names, types, and symbol addresses imported well enough for this analysis.

## Practical Host Implementation Model

A minimal host using a JTAG/SWD API would do this:

```text
download AXF load segment to 0x20000000
lookup symbol Flash_Info -> 0x20000ce4
lookup symbol Reset_Handler -> 0x20000001

for each flash operation:
    halt CPU
    write Flash_Info fields
    write Flash_Info.Buf if programming
    set PC = Reset_Handler
    run CPU
    wait for halt/breakpoint or poll Result
    read Flash_Info.Result
```

This loader contains `BKPT 0` words after `Main()` and in the exception handler area, so a debugger host can also detect completion by breakpoint/halt rather than only polling `Result`.

## Files Produced

- `recovered_main.c`: cleaned reconstructed C
- `recovered_startup.s`: recovered ARMASM startup
- `ghidra_decompiled.c`: raw Ghidra decompiler output
- `STM32_FlashLoader.disasm.txt`: full disassembly
- `STM32_FlashLoader.symbols.txt`: symbol table
- `STM32_FlashLoader.dwarf.txt`: DWARF dump
- `STM32_FlashLoader.readobj.txt`: ELF sections and symbols
