Files
mtboss/research/FLASHING_ALGORITHM.md
T
2026-08-03 19:57:38 +03:00

9.6 KiB

MTBoss: MT6261 Direct BootROM SPI NOR Flashing Algorithm

Thorough technical documentation of the BROM-direct SPI NOR flash programming algorithm for MediaTek MT6261 series feature phones (such as the Maxcom MM817).

This approach bypasses Download Agent (DA) binaries entirely by manipulating the hardware Serial Flash Interface (SFI) controller directly via BootROM register access commands.


1. Overview & Architecture

Standard MediaTek flashing workflows load a two-stage Download Agent (DA) into SRAM (0x70007000) and DRAM (0x10020000) via BootROM commands 0xD7 and 0xD5. However, on many legacy feature phone platforms, standard DA binaries silently crash or fail to execute due to uninitialized DRAM or memory map mismatches.

This algorithm implements Direct BootROM SFI Hardware Flashing:

  • Handshake & Register Initialization: Connects via native BootROM serial protocol, disables system/battery watchdogs, and enables USB download mode.
  • Direct Hardware SFI Controller Manipulation: Uses BROM 32-bit memory access commands (0xD1 / 0xD4) to control the Serial Flash Interface (0xA0140000).
  • Hardware MAC Controller Switching: Enables SFI MAC Mode (SFI_MAC_SEL) to send raw SPI NOR commands (WREN 0x06, Sector Erase 0x20, Page Program 0x02, Read Status 0x05, Read JEDEC ID 0x9F) directly to the physical NOR flash chip.
  • Buffer Management: Chunks page program payloads to 64 bytes to strictly fit within the 160-byte (0x00A0) SFI_GPRAM hardware buffer limit.
  • Memory-Mapped Verification: Uses BROM 32-bit read commands (0xD1) at Memory Map Mode 2 (0xA0510000 = 2) to perform byte-for-byte readback verification.

2. Hardware Memory & Register Map

2.1 Base Addresses

Peripheral Base Address Description
SFI_BASE 0xA0140000 Serial Flash Interface Registers
CONFIG_BASE 0xA0010000 Clock & System Configuration Registers
RGU_BASE 0xA0030000 Reset Generation Unit (Watchdog)
BOOT_ENG_BASE 0xA0510000 Boot Engine Configuration
PMU_BASE 0xA0700000 Power Management Unit

2.2 SFI Registers (0xA0140000)

Offset Name Bitfield / Description
+0x0000 SFI_MAC_CTL Bit 0: SFI_WIP (Write In Progress)
Bit 1: SFI_WIP_READY (Trigger Completed)
Bit 2: SFI_TRIG (Trigger MAC Operation)
Bit 3: SFI_MAC_EN (Enable MAC Controller)
Bit 4: SFI_MAC_SIO_SEL (Serial I/O Select)
Bit 16: SFI_RELEASE_MAC (Release MAC Mode)
Bit 28: SFI_MAC_SEL (Route SPI Bus to MAC Controller)
+0x0004 SFI_DIRECT_CTL Direct Read Controller Configuration
+0x0008 SFI_MISC_CTL Bit 8: SFI_REQ_IDLE
Bit 9: SFI_BOOT_REMAP
Bit 23: SFI_NO_RELOAD
+0x0010 SFI_MAC_OUTL Outgoing Command/Data Length (in bytes)
+0x0014 SFI_MAC_INL Incoming Data Length to read (in bytes)
+0x0044 SFI_MISC_CTL3 Bit 9: SFI_CH2_TRANS_MASK (AHB Channel Mask)
Bit 13: SFI_CH2_TRANS_IDLE
+0x0800 SFI_GPRAM General Purpose RAM Buffer (160 bytes total, 0x0800 - 0x08A0)

3. Step-by-Step Flashing Algorithm

flowchart TD
    A["Start: Connect Port (rtscts=True)"] --> B["BROM Sync: Send 0xA0 (wait 0x5F)<br>Send 0x0A5005 (wait 0xF5AFFA)"]
    B --> C["Read Chip ID (0xA2 to 0x80000008)"]
    C --> D["Disable Watchdogs & Set Boot Map Mode 2"]
    D --> E["Unlock SPI Flash Write Protection"]
    E --> F["Erase 4KB Sectors via SFI MAC (0x20)"]
    F --> G["Program Pages via SFI MAC (0x02)<br>(64-byte chunks to fit GPRAM)"]
    G --> H["Read Back & Verify via BROM 0xD1"]
    H --> I["Reset Device (0xA003001C = 0x1209)"]

Step 1: BootROM Serial Connection & Handshake

  1. Open serial port with rtscts=True and dsrdtr=True at 115200 baud.
  2. Send single sync byte 0xA0 repeatedly until 0x5F is received.
  3. Send 3-byte command packet b'\x0A\x50\x05'.
  4. Verify receive 3-byte ACK packet b'\xF5\xAF\xFA'.

Step 2: Chip Identification & Watchdog Disabling

  1. Read Chip ID via 16-bit BROM read command 0xA2:
    • Send b'\xA2' + struct.pack('>II', 0x80000008, 1)
    • Receive echo and 2-byte response (0x6261 = MT6261).
  2. Disable watchdogs and configure power registers via 16-bit BROM write command 0xD2:
    • 0xA0030000 = 0x2200 (Disable system watchdog)
    • 0xA0700A28 = 0x8000 (Enable USB download mode)
    • 0xA0700A24 = 0x0002 (Disable battery watchdog)

Step 3: Configure Memory Mapping Mode 2

  1. Set boot engine memory map mode to Mode 2 via 32-bit BROM write command 0xD4:
    • Send b'\xD4' + struct.pack('>II', 0xA0510000, 1) + struct.pack('>I', 2)
    • Maps physical SPI NOR flash starting at CPU address 0x00000000.

Step 4: SPI NOR Status Register Inspection & Unlock

  1. Read SPI NOR Status Register (0x05) via sfi_mac_cmd_read(0x05, 1).
  2. Inspect Block Protect bits (BP0, BP1, BP2, BP3).
  3. If protected, issue status register unlock:
    • Send Volatile Write Enable 0x50 via sfi_mac_cmd_write(0x50).
    • Send Write Status Register 0x01 with data 0x00 via sfi_mac_cmd_write(0x01, data=b'\x00').

Step 5: SFI Hardware MAC Mode Register Sequencing

All SPI NOR operations (Erase, Program, Status Read) must follow this exact register sequence:

# 1. Format payload: [cmd_byte] + [3-byte big-endian address] + [optional payload data]
payload = bytes([cmd_byte])
if addr is not None:
  payload += addr.to_bytes(3, 'big')
payload += data
total_len = len(payload)

# 2. Write payload into SFI GPRAM (0xA0140800) in 32-bit little-endian words
for i in range(0, total_len, 4):
  chunk = payload[i : i + 4]
  val = int.from_bytes(chunk.ljust(4, b'\x00'), 'little')
  write_reg32(0xA0140800 + i, val)

# 3. Mask AHB Channel 2 in MISC_CTL3 (0xA0140044)
write_reg32(0xA0140044, read_reg32(0xA0140044) | (1 << 9))

# 4. Enable MAC mode FIRST (SFI_MAC_SEL bit 28 | SFI_MAC_EN bit 3)
mac_val = (1 << 28) | (1 << 3)
write_reg32(0xA0140000, mac_val)

# 5. Set OUTL and INL lengths WHILE MAC mode is active
write_reg32(0xA0140010, total_len)  # SFI_MAC_OUTL
write_reg32(0xA0140014, 0)  # SFI_MAC_INL

# 6. Trigger transaction by adding SFI_TRIG (bit 2)
write_reg32(0xA0140000, mac_val | (1 << 2))

# 7. Poll SFI_MAC_CTL until SFI_WIP_READY (bit 1) is 1 and SFI_WIP (bit 0) is 0
while True:
  v = read_reg32(0xA0140000)
  if (v & 0x02) and not (v & 0x01):
    break

# 8. Clean up MAC mode and unmask AHB channel 2
write_reg32(0xA0140000, 0)
write_reg32(0xA0140044, read_reg32(0xA0140044) & ~(1 << 9))

[!CRITICAL] Register Order Dependency: Step 3 (SFI_MAC_CTL enable) MUST occur BEFORE Step 4 (SFI_MAC_OUTL set). Writing to SFI_MAC_OUTL while MAC mode is disabled will cause the controller to ignore the transfer length and transmit 0 payload bytes.

Step 6: Sector Erasing (4KB Sectors)

For each 4KB boundary (0x0000, 0x1000, 0x2000, 0x3000):

  1. Send Write Enable (0x06) via sfi_mac_cmd_write(0x06).
  2. Issue Sector Erase (0x20) with target address:
    • sfi_mac_cmd_write(0x20, addr=sector_address)
  3. Wait until flash WIP bit clears in status register (0x05).

Step 7: Chunked Page Programming

SPI NOR page programming uses command 0x02. Because SFI_GPRAM is limited to 160 bytes (0x0800 - 0x08A0), page data MUST be chunked into maximum 64 bytes per command:

  1. Divide target page payload into 64-byte chunks.
  2. For each 64-byte chunk:
    • Send Write Enable (0x06).
    • Issue Page Program (0x02) with current chunk address and 64-byte payload: sfi_mac_cmd_write(0x02, addr=curr_addr, data=64_byte_chunk)
    • Wait until flash WIP bit clears in status register (0x05).
    • Advance address by 64 bytes.

Step 8: Memory-Mapped Verification & Readback

Read back the written memory region directly using BROM 32-bit read command 0xD1:

  1. Issue 0xD1 command for 1024-byte blocks (256 32-bit words):
    • Send b'\xD1' + struct.pack('>II', curr_addr, 256)
    • Receive echo header + 1028 bytes response.
  2. Skip 2-byte header and 2-byte status footer.
  3. Convert little-endian words to big-endian binary stream.
  4. Perform byte-for-byte MD5 comparison against reference binary image.

Step 9: Software Reset

  1. Issue system reset command via RGU register:
    • write_reg16(0xA003001C, 0x1209)
  2. Device reboots cleanly into updated firmware.

4. Flash Layout Reference (Maxcom MM817 4MB SPI NOR)

0x00000000 +-----------------------------------+
           | ARM Bootloader (ARM_BL)           | 10,240 bytes (0x2800)
0x00002800 +-----------------------------------+
           | Extended Bootloader (EXT_BL)      | 3,072 bytes (0x0C00)
0x00003400 +-----------------------------------+
           | Boot Padding / Header             | 3,072 bytes (0x0C00)
0x00004000 +-----------------------------------+
           | Boot Region 2 Backup              | 16,384 bytes (0x4000)
0x00008000 +-----------------------------------+
           | Boot Region 3 Backup              | 16,384 bytes (0x4000)
0x0000C000 +-----------------------------------+
           | Main Firmware & File System       | ~3.93 MB
0x00400000 +-----------------------------------+

5. Verification Checklist

Test Phase Expected Result Verified Status
BootROM Handshake Sync ACK b'\xF5\xAF\xFA', Chip ID 0x6261 PASS
Watchdog Disable Reg 0xA0030000 = 0x2200 PASS
SPI Flash JEDEC ID Read 0x9F returns manufacturer & device ID PASS
Sector Erase (4KB) Memory reads as 0xFF across sector PASS
64-Byte Page Program Memory reads match programmed payload PASS
Full 16KB Verification 100% exact MD5 match against reference image PASS