Skip to content

Commit 3f285dc

Browse files
committed
feat(epon): F-MDCONU3A — add CLI permission bypass, full command tree, firmware flash protocol
Adds extensive reverse-engineering findings for the Free/Iliad F-MDCONU3A (BCM55030 10G-EPON ONU) from static analysis of the v3.2.9 firmware binary: - CLI permission system: pl built-in command bypasses all permission checks, pl omega gives full manufacturing access (level 2) from default UART shell - Complete CLI command tree at all 3 permission levels (level 0: ~60 cmds, level 1: +20, level 2: +25) - Firmware flash protocol (load/rx): raw binary transfer over UART at 57600 baud, TKF container format with trailing CRC32 - Hardware architecture details: Harvard ARC (ICCM/DCCM), firmware structure, FDS personality records - Expanded flash memory map with all 5 regions including FDS/Config - Filled in missing hardware specs (bootloader, system, load addr, RAM, chipset rev) All findings from Ghidra static analysis (2697 functions named). No proprietary documentation was used.
1 parent d2728dc commit 3f285dc

1 file changed

Lines changed: 187 additions & 63 deletions

File tree

_ont_epon/free_iliad_F-MDCONU3A.md

Lines changed: 187 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ parent: Free/Iliad
1313
| Model | F-MDCONU3A |
1414
| ODM ||
1515
| ODM Product Code | |
16-
| Chipset | BCM55030 |
17-
| Flash | W25Q32J (4MB SPI) |
18-
| RAM | embedded |
16+
| Chipset | BCM55030B2FBG rev B2 |
17+
| Flash | W25Q32J (4 MB SPI) |
18+
| RAM | embedded SRAM (DCCM) |
1919
| CPU | ARCompact[^arc-isa], big endian |
2020
| CPU Clock | |
21-
| Bootloader | |
22-
| System | |
23-
| Load addr | |
21+
| Bootloader | TK2000 Boot v3.27 |
22+
| System | bare-metal (no OS) |
23+
| Load addr | 0x20000000 (ICCM) |
2424
| HSGMII | No |
2525
| Optics | SFP w/o MAC |
2626
| IP address | |
@@ -32,73 +32,93 @@ parent: Free/Iliad
3232
| Serial encoding | 8-N-1 |
3333
| Form Factor | ONT |
3434

35-
The BCM55030 is a 10G-EPON ONU/ONT.
36-
The BCM55030's UNI (User Network Interface) side should be capable of 4xSGMII (1 GbE) or 1xXAUI (10 GbE) or 1xXFI (10 GbE SFP) or 1xRGMII, but only one SGMII lane is actually routed.
37-
UNI link won't go up when connected to a media converter or directly to a NIC.
35+
The BCM55030 is a 10G-EPON DPoE (DOCSIS Provisioning over EPON) ONU/ONT used by Free/Iliad (France) on their FTTH network. The PON side operates in asymmetric 10G/1G mode: downstream at 1577 nm / 10.3125 Gb/s, upstream at 1310 nm / 1.25 Gb/s burst (IEEE 802.3av).
36+
37+
The BCM55030's UNI (User Network Interface) side should be capable of 4xSGMII (1 GbE) or 1xXAUI (10 GbE) or 1xXFI (10 GbE SFP) or 1xRGMII, but only one SGMII lane is actually routed (1000BASE-X via soldered SFP+ male connector).
38+
39+
UNI link won't go up when connected to a media converter or directly to a NIC. The firmware waits for a valid 1000BASE-X partner before activating the PON side (circular dependency).
40+
41+
The CPU uses a Harvard architecture: ICCM (Instruction Closely-Coupled Memory) for code execution and DCCM/SRAM for data. Code in ICCM is not readable via the data bus — the `mem/rf` command can only read data memory, not firmware code.
3842

3943
## Serial
4044

4145
The serial port is easily accessible at TP5 and TP6. A prompt is available without authentication, it is structured as a tree of directories. To navigate type the subdirectory name. To go back type `/` and hit enter. To list available commands type `help`.
4246

43-
Available commands:
47+
### CLI Permission Levels
48+
49+
The CLI has a 3-level permission system. By default, UART connects at level 0 (restricted). The **`pl`** (Print Level) built-in command switches between levels without any authentication:
50+
51+
| Command | Level | Effect |
52+
| ------------ | ----- | ----------------------------------------- |
53+
| `pl reset` | 0 | Default restricted access |
54+
| `pl alpha` | 1 | Debug mode — unlocks ~20 additional commands |
55+
| **`pl omega`** | **2** | **Full manufacturing access — unlocks ALL commands** |
56+
57+
The `pl` command is a framework built-in keyword (like `help` and `..`) that is processed *before* the permission-checked command tree walk. It never passes through the permission gate, so it works from any level — including the default level 0.
58+
59+
The permission byte is stored at a single RAM address and persists for the duration of the session. It resets to 0 on reboot. To persist a higher level across reboots, use `fds/write` (available at level 1+) to write to FDS group 4, record 7.
60+
61+
### Available commands
62+
63+
Level 0 (default — 22 root entries, ~60 total commands):
4464

4565
```
4666
- mac/
47-
- epon
48-
- user
67+
- epon
68+
- user
4969
- alm/
50-
- info
51-
- gpio
70+
- info
71+
- gpio
5272
- debug/
53-
- mcast
54-
- mpcp
55-
- nco
56-
- rstp
57-
- sysd
73+
- mcast
74+
- mpcp
75+
- nco
76+
- rstp
77+
- sysd
5878
- epon/
59-
- eponmac
60-
- usermac
61-
- dom
62-
- ponspeed
79+
- eponmac
80+
- usermac
81+
- dom
82+
- ponspeed
6383
- fds/
64-
- erase
84+
- erase
6585
- load/
66-
- info
67-
- commit
68-
- setRecoveryPoint
69-
- runRecoveryPoint
70-
- rx
86+
- info
87+
- commit
88+
- setRecoveryPoint
89+
- runRecoveryPoint
90+
- rx
7191
- mcast/
72-
- domains
73-
- groups
74-
- sources
75-
- reporters
76-
- igmpinfo
77-
- igmpsources
92+
- domains
93+
- groups
94+
- sources
95+
- reporters
96+
- igmpinfo
97+
- igmpsources
7898
- mem/
79-
- rf
99+
- rf
80100
- mpcp/
81-
- info
82-
- failsafe
83-
- oltmac
101+
- info
102+
- failsafe
103+
- oltmac
84104
- pers/
85-
- read
105+
- read
86106
- serdes/
87-
- sdextlptest
107+
- sdextlptest
88108
- stats/
89-
- clear
90-
- gather
91-
- epon
92-
- fifo
93-
- lif
94-
- uni
95-
- xif
96-
- statsmode
109+
- clear
110+
- gather
111+
- epon
112+
- fifo
113+
- lif
114+
- uni
115+
- xif
116+
- statsmode
97117
- log/
98-
- show
99-
- level
118+
- show
119+
- level
100120
- sysd/
101-
- frmdmp
121+
- frmdmp
102122
- clionly
103123
- clr
104124
- ints
@@ -109,6 +129,89 @@ Available commands:
109129
- sftver
110130
```
111131

132+
Level 1 (`pl alpha` — adds these commands):
133+
134+
```
135+
- access/
136+
- read (hardware peripheral bus read — I2C/SPI)
137+
- write (hardware peripheral bus write)
138+
- mdio/
139+
- read
140+
- readlst
141+
- write
142+
- lue/
143+
- lin/
144+
- inst
145+
- bin/
146+
- inst
147+
- cust/
148+
- e (examine custom data)
149+
- r (read custom data)
150+
- w (write custom data)
151+
- fds/
152+
- write (write FDS record)
153+
- mem/
154+
- wm (write memory)
155+
- wf (write flash)
156+
- ef (erase flash)
157+
```
158+
159+
Level 2 (`pl omega` — adds these commands):
160+
161+
```
162+
- efuse (read eFuse OTP memory)
163+
- efusebits (read eFuse bit-level detail)
164+
- learn/
165+
- inst
166+
- tbl
167+
- age
168+
- limit
169+
- gmc/
170+
- le
171+
- ld
172+
- serdes/
173+
- dump
174+
- debug/
175+
- fc
176+
- epon
177+
- learn
178+
- eap
179+
- fifo/
180+
- queue
181+
- eae/
182+
- eap
183+
- mka
184+
- mtime
185+
- klen
186+
- xau/
187+
- xcap
188+
- fec/
189+
- auto
190+
- reglist
191+
- regbits
192+
```
193+
194+
### Useful commands
195+
196+
| Command | Description |
197+
| ------- | ----------- |
198+
| `sftver` | Print firmware version and chip ID |
199+
| `load/info` | Show all firmware slots with versions and CRCs |
200+
| `epon/eponmac` | Show EPON MAC address |
201+
| `epon/ponspeed` | Show current PON link speed |
202+
| `mpcp/info` | Show MPCP registration state |
203+
| `mpcp/oltmac` | Show OLT MAC address |
204+
| `pers/read` | Dump personality data (raw hex) |
205+
| `mem/rf <addr> <len>` | Read `len` bytes of data memory starting at `addr` |
206+
| `stats/epon` | Show EPON statistics counters |
207+
| `reg <index>` | Read a software register by index |
208+
| `set <index> <value>` | Write a software register |
209+
| `pl omega` | Unlock full manufacturing access |
210+
| `mem/wm <addr> <value>` | Write to memory (level 1+) |
211+
| `efuse` | Dump eFuse OTP contents (level 2) |
212+
| `load/rx` | Receive firmware image over UART |
213+
| `load/commit` | Commit received firmware to active slot |
214+
112215
`load/info` output:
113216
```
114217
TK2000 APP 3.27 May 13 2016 02:48:05 Chip: 4701 B2110816
@@ -158,24 +261,45 @@ Stream: 112 Revision: 131152
158261
Time: 2016-05-18 01:28:44Z
159262
```
160263

161-
`mem/rf [start address] [lenght]` reads bytes from the flash memory, wraps every 512 kB.
264+
`mem/rf [start address] [length]` reads bytes from data memory (DCCM/SRAM). Due to the Harvard architecture, this command cannot read firmware code (which resides in ICCM). The address space wraps every 512 kB.
265+
266+
## Firmware Flash Protocol
267+
268+
The `load/rx` command accepts a firmware image over UART using a raw binary transfer (no XMODEM, no handshake):
269+
270+
1. Wait for the `2000/>` prompt
271+
2. Send `load/rx\r`
272+
3. ONU responds: `Begin binary transfer...`
273+
4. Send the TKF image as raw binary at 57600 baud (~55 seconds for 319 KB)
274+
5. ONU responds: `Transfer complete: N bytes received`
275+
6. Send `load/commit\r` to activate the new slot
276+
7. Send `reset\r` to reboot
277+
278+
The firmware image must be wrapped in a TKF (Teknovus) container:
279+
280+
```
281+
[header 39 bytes] [payload N bytes] [CRC32 4 bytes]
282+
```
283+
284+
The trailing CRC32 covers the entire header+payload (standard IEEE 802.3 CRC). The ONU writes to App 0 and App 1 slots in rotation.
162285

163286
## List of partitions
164287

165-
The flash memory is not actually partitioned, upon reset the CPU loads from address 0 (reset vector) and jumps to another address ([page 74](http://me.bios.io/images/d/dd/ARCompactISA_ProgrammersReference.pdf#%5B%7B%22num%22%3A177%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C72%2C157%2C0%5D)). Each section ends with its CRC.
288+
The flash memory (W25Q32J, 4 MB SPI) has 5 regions. Each application section starts with a 39-byte TKF header and ends with its CRC.
166289

167-
| Section | Start address | End address | Size |
168-
| --------------------- | ---------------- | ---------------- | -------------- |
169-
| Bootloader | 0 | 42896/0xA790 | 42896/0xA790 |
170-
| App 0 | ? | ? | ? |
171-
| App 1 | 1179687/0x120027 | 1498731/0x16DE6B | 319044/0x4DE44 |
172-
| App 2 | 1703975/0x1A0027 | 2023215/0x1EDF2F | 319240/0x4DF08 |
173-
| Diag (copy of App 1?) | 2555943/0x270027 | 2874987/0x2BDE6B | 319044/0x4DE44 |
290+
| Section | Start address | End address | Size | Version |
291+
| ---------- | ---------------- | ---------------- | -------------- | ------- |
292+
| Bootloader | 0x000000 | 0x00A790 | 42 KB | v3.27 |
293+
| FDS/Config | 0x00A790 | 0x120000 | ~460 KB | |
294+
| App 1 | 0x120027 | 0x16DE6B | 319 KB | v3.2.7 |
295+
| App 2 | 0x1A0027 | 0x1EDF2F | 319 KB | v3.2.9 |
296+
| Diag | 0x270027 | 0x2BDE6B | 319 KB | v3.2.7 |
174297

175298
(End address is non-inclusive)
176-
App 1 and App 2 sections are located at a distance of 512 kB (0x80000) from each other. This probably means that the CPU is capable of addressing only 512 kB of flash. It can be verified also by running the `mem/rf` command, which wraps every 512 kB.
177299

178-
# Userful files and binaries
300+
App slots are located at 512 KB (0x80000) intervals. The CPU can address only 512 KB of flash at a time (verified by `mem/rf` wrapping behavior). The FDS (Flash Data Storage) region between the bootloader and App 1 contains personality records, MAC addresses, SerDes configuration, and CLI config data (34 known FDS record types).
301+
302+
# Useful files and binaries
179303

180304
# EEPROM
181305

0 commit comments

Comments
 (0)