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 (WREN0x06, Sector Erase0x20, Page Program0x02, Read Status0x05, Read JEDEC ID0x9F) 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_GPRAMhardware 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_IDLEBit 9: SFI_BOOT_REMAPBit 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
- Open serial port with
rtscts=Trueanddsrdtr=Trueat 115200 baud. - Send single sync byte
0xA0repeatedly until0x5Fis received. - Send 3-byte command packet
b'\x0A\x50\x05'. - Verify receive 3-byte ACK packet
b'\xF5\xAF\xFA'.
Step 2: Chip Identification & Watchdog Disabling
- 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).
- Send
- 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
- 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.
- Send
Step 4: SPI NOR Status Register Inspection & Unlock
- Read SPI NOR Status Register (
0x05) viasfi_mac_cmd_read(0x05, 1). - Inspect Block Protect bits (
BP0,BP1,BP2,BP3). - If protected, issue status register unlock:
- Send Volatile Write Enable
0x50viasfi_mac_cmd_write(0x50). - Send Write Status Register
0x01with data0x00viasfi_mac_cmd_write(0x01, data=b'\x00').
- Send Volatile Write Enable
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_CTLenable) MUST occur BEFORE Step 4 (SFI_MAC_OUTLset). Writing toSFI_MAC_OUTLwhile 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):
- Send Write Enable (
0x06) viasfi_mac_cmd_write(0x06). - Issue Sector Erase (
0x20) with target address:sfi_mac_cmd_write(0x20, addr=sector_address)
- 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:
- Divide target page payload into 64-byte chunks.
- 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.
- Send Write Enable (
Step 8: Memory-Mapped Verification & Readback
Read back the written memory region directly using BROM 32-bit read command 0xD1:
- Issue
0xD1command for 1024-byte blocks (25632-bit words):- Send
b'\xD1' + struct.pack('>II', curr_addr, 256) - Receive echo header + 1028 bytes response.
- Send
- Skip 2-byte header and 2-byte status footer.
- Convert little-endian words to big-endian binary stream.
- Perform byte-for-byte MD5 comparison against reference binary image.
Step 9: Software Reset
- Issue system reset command via RGU register:
write_reg16(0xA003001C, 0x1209)
- 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 |