<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet href="/feed_style.xsl" type="text/xsl"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="https://www.rssboard.org/media-rss">
  <channel>
    <title>Hardware on Mario Moura</title>
    <link>https://mariomoura.com/tags/hardware/</link>
    <description>Recent content in Hardware on Mario Moura</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <managingEditor>mm@mariomoura.com (Mario Moura)</managingEditor>
    <webMaster>mm@mariomoura.com (Mario Moura)</webMaster>
    <copyright>Mario Moura</copyright>
    <lastBuildDate>Mon, 01 Jun 2026 12:00:00 -0300</lastBuildDate><atom:link href="https://mariomoura.com/tags/hardware/index.xml" rel="self" type="application/rss+xml" /><icon>https://mariomoura.com/img/avatar.jpg</icon>
    
    
    <item>
      <title>Hacking a FiberHome ONU to replace a Vivo HGU</title>
      <link>https://mariomoura.com/post/onu-hacking/</link>
      <pubDate>Mon, 01 Jun 2026 12:00:00 -0300</pubDate>
      <author>mm@mariomoura.com (Mario Moura)</author>
      <guid>https://mariomoura.com/post/onu-hacking/</guid>
      <description><![CDATA[<h1 id="patching-a-proprietary-gpon-onu-one-byte-at-a-time">Patching a proprietary GPON ONU one byte at a time</h1>
<h2 id="why">Why</h2>
<p>I want to replace my ISP&rsquo;s all-in-one router (an Askey RTF8225VW provided by Vivo) with a dedicated setup: a dumb bridge ONU for the fiber, and a Raspberry Pi running Debian as the actual router. Full control over NAT, firewall, DNS, DHCP &ndash; the works.</p>
<p>I had a FiberHome AN5506-01-A lying around. Single fiber port, single Ethernet port, bridge-only. Exactly what I needed. The problem is that Vivo&rsquo;s OLT (the ISP-side equipment that manages fiber subscribers) doesn&rsquo;t just let any ONU onto the network. It expects to see specific identity parameters from the device, and if something doesn&rsquo;t match, it refuses to provision it.</p>
<p>This is the story of extracting credentials from the Askey, dumping a 16MB flash chip, patching a proprietary ARM binary inside a compressed read-only filesystem, and flashing it all back. It didn&rsquo;t fully work, but the journey was educational.</p>
<h2 id="the-plan">The plan</h2>
<p>GPON authentication involves a handful of parameters that the ONU exchanges with the OLT during registration:</p>
<table>
  <thead>
      <tr>
          <th>Parameter</th>
          <th>What it is</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPON Serial Number</td>
          <td>Unique device ID, burned into the ONU</td>
      </tr>
      <tr>
          <td>PLOAM Password</td>
          <td>Shared secret for PLOAM-level auth</td>
      </tr>
      <tr>
          <td>Equipment ID</td>
          <td>Device model string reported via OMCI</td>
      </tr>
      <tr>
          <td>Hardware Version</td>
          <td>Board revision string</td>
      </tr>
      <tr>
          <td>Software Version</td>
          <td>Firmware version string</td>
      </tr>
      <tr>
          <td>OMCC Version</td>
          <td>OMCI protocol version byte</td>
      </tr>
  </tbody>
</table>
<p>The idea was simple: extract these from the working Askey, set them on the FiberHome, and have the OLT think it&rsquo;s still talking to the same device.</p>
<h2 id="extracting-credentials-from-the-askey">Extracting credentials from the Askey</h2>
<p>The Askey RTF8225VW is locked down. Telnet gives you a <code>User&gt;</code> prompt with almost every <code>show</code> command returning &ldquo;reserved for future&rdquo;. No shell, no backup export, no way to pull configuration.</p>
<p>The GPON Serial Number was easy &ndash; it&rsquo;s printed on the device label: <code>TLCMXXXXXXXX</code>.</p>
<p>The PLOAM password was harder. The admin web interface doesn&rsquo;t show it. But Vivo&rsquo;s installer page at <code>/index_instalador.asp</code> (login as <code>instalador</code>) embeds it in the HTML source as a JavaScript variable:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">gponPw</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#39;00000000000000000000&#39;</span>;
</span></span></code></pre></div><p>Twenty hex characters, all zeros. Ten bytes of <code>0x00</code>. Vivo authenticates by Serial Number only, the PLOAM is blank.</p>
<p>PPPoE credentials were visible in the WAN settings: <code>cliente@cliente</code> / <code>cliente</code>. Not exactly Fort Knox.</p>
<h2 id="getting-root-on-the-fiberhome">Getting root on the FiberHome</h2>
<p>The FiberHome AN5506-01-A runs Linux on a HiSilicon SD5116 SoC. The web interface at <code>192.168.1.1</code> is basic and locked down, but the real access is through a hidden telnet service on <strong>port 26</strong>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>telnet 192.168.1.1 <span style="color:#ae81ff">26</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Login: root (no password)</span>
</span></span></code></pre></div><p>Full root shell. From here you can browse the filesystem, edit config files, and poke at the GPON internals.</p>
<p>The first thing to do was set the GPON Serial Number:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo TLCMXXXXXXXX &gt; /fhcfg/fh_pon/physicSN
</span></span><span style="display:flex;"><span>echo &gt; /fhcfg/fh_pon/logicSN
</span></span><span style="display:flex;"><span>echo &gt; /fhcfg/fh_pon/logicPWD
</span></span></code></pre></div><p>Reboot, connect the fiber, and the ONU reaches <strong>O5 state</strong> &ndash; registered with the OLT. The SN spoofing worked. But <code>rx_omci: 0</code>. The OLT accepted the registration at the PLOAM level but refused to start OMCI provisioning. It knew something was off.</p>
<h2 id="understanding-the-flash-layout">Understanding the flash layout</h2>
<p>This is where things get interesting. The ONU runs from a 16MB SPI NOR flash chip (MX25L12833F), and the kernel&rsquo;s boot arguments reveal exactly how it&rsquo;s partitioned:</p>
<pre tabindex="0"><code>mtdparts=hi_sfc:256k(boot),256k(env),1536k(kernel),5888k(rootfs_app),
         1536k(kernel),5888k(rootfs_app),1M(cfg)
</code></pre><p>Laid out visually:</p>
<pre tabindex="0"><code>Offset     Size     Name         Filesystem
0x000000   256KB    boot         U-Boot (bootloader)
0x040000   256KB    env          Raw (U-Boot environment variables)
0x080000   1.5MB    kernel       zImage (bank 0)
0x200000   5.75MB   rootfs_app   cramfs (bank 0)
0x7C0000   1.5MB    kernel       zImage (bank 1)
0x940000   5.75MB   rootfs_app   cramfs (bank 1)
0xF00000   1MB      cfg          jffs2 (/fhcfg)
</code></pre><h3 id="mtd">MTD</h3>
<p><strong>MTD</strong> (Memory Technology Device) is Linux&rsquo;s subsystem for raw flash chips. Unlike an SSD or SD card, SPI NOR flash has no controller. The OS manages erase blocks directly. There&rsquo;s no MBR or GPT partition table &ndash; the kernel receives the partition layout as a boot argument from U-Boot and creates <code>/dev/mtdblock0</code> through <code>/dev/mtdblock6</code> accordingly.</p>
<h3 id="two-filesystems">Two filesystems</h3>
<p>The flash uses two different filesystems for different purposes:</p>
<p><strong>cramfs</strong> (Compressed ROM File System) is a read-only compressed filesystem. The entire OS, applications, and libraries live here. It&rsquo;s efficient for embedded devices: small footprint, no write wear on the flash, and the kernel can mount it directly. The downside is obvious: you can&rsquo;t change anything without rebuilding the whole image.</p>
<p><strong>jffs2</strong> (Journaling Flash File System 2) is a read-write filesystem designed for raw flash. It handles wear leveling and power-loss safety. The ONU uses it for the 1MB <code>/fhcfg</code> partition, which stores mutable config like the GPON SN, Wi-Fi settings, and PPPoE credentials.</p>
<p><strong>zImage</strong> (compressed kernel image) The kernel partitions contain a <strong>zImage</strong> &ndash; a self-extracting compressed Linux kernel. When U-Boot loads it into RAM and calls <code>bootm</code>, the small decompression stub at the head of the image unpacks the real kernel in-place and jumps to it. It&rsquo;s the standard format for ARM Linux on embedded devices where flash space is tight.</p>
<h3 id="dual-banks">Dual banks</h3>
<p>Notice the two copies of kernel + rootfs. This is an <strong>A/B update scheme</strong>. The OLT can push firmware updates to the ONU over OMCI. One bank is active, the other receives the update. If the update fails, the bootloader falls back to the working bank. The U-Boot env stores <code>kernel_flag</code> and <code>rootfs_app_flag</code> to track which bank is active.</p>
<h2 id="the-boot-process">The boot process</h2>
<p>When the ONU powers on:</p>
<ol>
<li><strong>U-Boot</strong> starts from offset 0x0, initializes RAM and SPI flash, reads its environment from the <code>env</code> partition.</li>
<li>It executes <code>bootcmd</code>: copies the kernel from flash to RAM (<code>sf read 0x80300000 0x80000 0x180000</code>) and boots it (<code>bootm</code>).</li>
<li>The <strong>Linux kernel</strong> receives <code>bootargs</code> including <code>root=/dev/mtdblock3 rootfstype=cramfs</code>, mounts the cramfs root filesystem.</li>
<li>Init runs, mounts <code>/fhcfg</code> as jffs2, then executes <code>/fh/extend/initialize.sh</code>.</li>
<li><code>initialize.sh</code> loads GPON drivers, creates network interfaces (eth0, wan0, tel0, br0), and starts the main application binary <code>/fh/extend/AN5506-01-A</code>.</li>
<li>The main app loads <code>libnomci.so</code> for OMCI handling, connects to the GPON MAC hardware, and begins PLOAM registration with the OLT.</li>
</ol>
<pre tabindex="0"><code>Flash → U-Boot → Kernel → mount cramfs → initialize.sh → AN5506-01-A
                                ↓
                          mount jffs2 → /fhcfg/
</code></pre><h2 id="the-omci-identity-problem">The OMCI identity problem</h2>
<p>OMCI (ONU Management and Control Interface) is the protocol the OLT uses to configure the ONU after registration. It queries <strong>Management Entities</strong> (MEs) to learn about the device. The key ones:</p>
<ul>
<li><strong>ONT-G (ME 256)</strong>: Vendor ID, hardware version</li>
<li><strong>ONT2-G (ME 257)</strong>: Equipment ID, OMCC version</li>
<li><strong>Software Image (ME 7)</strong>: Firmware version</li>
</ul>
<p>The FiberHome reports its own identity &ndash; <code>AN5506-01-A</code>, software <code>R8.21.01.01</code>, etc. The OLT expects to see the Askey&rsquo;s identity: <code>RTF8225VW</code>, software <code>R8225VWXXXXXX</code>. Some of these values live in writable config files, but the critical ones are hardcoded in <code>libnomci.so</code>, a proprietary ARM shared library sitting on the read-only cramfs.</p>
<table>
  <thead>
      <tr>
          <th>Parameter</th>
          <th>Location</th>
          <th>Writable?</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Hardware Version</td>
          <td><code>/fhcfg/hw_version.ini</code></td>
          <td>Yes (jffs2)</td>
      </tr>
      <tr>
          <td>GPON SN</td>
          <td><code>/fhcfg/fh_pon/physicSN</code></td>
          <td>Yes (jffs2)</td>
      </tr>
      <tr>
          <td>Equipment ID</td>
          <td><code>libnomci.so</code> offset 975768</td>
          <td>No (cramfs)</td>
      </tr>
      <tr>
          <td>Software Version</td>
          <td><code>/fh/extend/info.ini</code></td>
          <td>No (cramfs)</td>
      </tr>
      <tr>
          <td>OMCC Version</td>
          <td>Hardcoded in <code>libnomci.so</code></td>
          <td>No (cramfs)</td>
      </tr>
  </tbody>
</table>
<p>The writable ones were easy:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;hardware_001=RTF8225VW&#39;</span> &gt; /fhcfg/hw_version.ini
</span></span></code></pre></div><p>But to change the Equipment ID and Software Version, I needed to modify files inside the cramfs. That means dumping the flash, extracting the filesystem, patching files, rebuilding it, and flashing it back.</p>
<h2 id="dumping-the-flash-with-ch341a">Dumping the flash with CH341A</h2>
<p>The MX25L12833F is an 8-pin SOIC SPI NOR chip. To read and write it, I used a <strong>CH341A USB programmer</strong> with an SOIC8 test clip:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Detect the chip (ONU powered off, clip attached):</span>
</span></span><span style="display:flex;"><span>sudo flashrom -p ch341a_spi
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Read the full 16MB twice and compare:</span>
</span></span><span style="display:flex;"><span>sudo flashrom -p ch341a_spi -c <span style="color:#e6db74">&#34;MX25L12833F&#34;</span> -r ~/onu/onu_backup.bin
</span></span><span style="display:flex;"><span>sudo flashrom -p ch341a_spi -c <span style="color:#e6db74">&#34;MX25L12833F&#34;</span> -r ~/onu/onu_backup2.bin
</span></span><span style="display:flex;"><span>diff ~/onu/onu_backup.bin ~/onu/onu_backup2.bin
</span></span><span style="display:flex;"><span><span style="color:#75715e"># No output = reads match, good dump</span>
</span></span></code></pre></div><p>One gotcha: the CH341A has two headers labeled <strong>25XX</strong> and <strong>24XX</strong>. The 25XX header is for SPI flash (what we need). The 24XX is for I2C EEPROMs. Another: the Linux <code>ch341</code> serial driver grabs the device before flashrom can use it. If <code>lsusb</code> shows <code>1a86:5523</code> instead of <code>5512</code>, run <code>sudo rmmod ch341</code> and replug.</p>
<h2 id="extracting-and-patching-cramfs">Extracting and patching cramfs</h2>
<p>With the ROM dump in hand, I carved out the bank 0 rootfs (mtd3) and extracted it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Carve mtd3 from the ROM (offset 0x200000 = 2097152):</span>
</span></span><span style="display:flex;"><span>dd <span style="color:#66d9ef">if</span><span style="color:#f92672">=</span>~/onu/onu_backup.bin of<span style="color:#f92672">=</span>~/onu/mtd3_cramfs.bin <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>   bs<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> skip<span style="color:#f92672">=</span><span style="color:#ae81ff">2097152</span> count<span style="color:#f92672">=</span><span style="color:#ae81ff">5324800</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Extract the cramfs contents:</span>
</span></span><span style="display:flex;"><span>sudo fsck.cramfs --extract<span style="color:#f92672">=</span>~/onu/rootfs_extracted ~/onu/mtd3_cramfs.bin
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Make everything writable:</span>
</span></span><span style="display:flex;"><span>sudo chmod -R u+w ~/onu/rootfs_extracted/
</span></span></code></pre></div><p>Now I had the full filesystem on disk. Time to patch.</p>
<h3 id="equipment-id-in-libnomciso">Equipment ID in libnomci.so</h3>
<p>The string <code>AN5506-01-A</code> (the Equipment ID reported to the OLT) lives at offset 975768 in the 1.1MB ARM ELF binary <code>libnomci.so</code>. The replacement <code>RTF8225VW</code> is 9 bytes vs the original 11, so I padded with null bytes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>printf <span style="color:#e6db74">&#39;RTF8225VW\x00\x00&#39;</span> | dd of<span style="color:#f92672">=</span>~/onu/rootfs_extracted/fh/extend/libnomci.so <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>   bs<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> seek<span style="color:#f92672">=</span><span style="color:#ae81ff">975768</span> conv<span style="color:#f92672">=</span>notrunc
</span></span></code></pre></div><h3 id="software-version-in-infoini">Software version in info.ini</h3>
<p>Straightforward text edit in <code>/fh/extend/info.ini</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="color:#66d9ef">[software version]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">software_version</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">R8225VWXXXXXX</span>
</span></span></code></pre></div><h3 id="rebuilding-and-flashing">Rebuilding and flashing</h3>
<p>Rebuild the cramfs, splice it back into the ROM, and write it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Rebuild cramfs:</span>
</span></span><span style="display:flex;"><span>sudo mkfs.cramfs ~/onu/rootfs_extracted ~/onu/mtd3_patched.bin
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Splice into ROM at mtd3 offset:</span>
</span></span><span style="display:flex;"><span>cp ~/onu/onu_backup.bin ~/onu/onu_patched.bin
</span></span><span style="display:flex;"><span>dd <span style="color:#66d9ef">if</span><span style="color:#f92672">=</span>~/onu/mtd3_patched.bin of<span style="color:#f92672">=</span>~/onu/onu_patched.bin <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>   bs<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> seek<span style="color:#f92672">=</span><span style="color:#ae81ff">2097152</span> conv<span style="color:#f92672">=</span>notrunc
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Flash it:</span>
</span></span><span style="display:flex;"><span>sudo flashrom -p ch341a_spi -c <span style="color:#e6db74">&#34;MX25L12833F&#34;</span> -w ~/onu/onu_patched.bin
</span></span></code></pre></div><p>Verification after flashing:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>strings /fh/extend/libnomci.so | grep RTF8225
</span></span><span style="display:flex;"><span><span style="color:#75715e"># RTF8225VW</span>
</span></span></code></pre></div><p>The patch took. The binary now reports <code>RTF8225VW</code> as the Equipment ID.</p>
<h2 id="the-result-still-stuck">The result: still stuck</h2>
<p>After flashing, the ONU registers (O5), but <code>rx_omci</code> stays at zero. The OLT still won&rsquo;t provision it.</p>
<p>I caught something interesting in <code>dmesg</code>:</p>
<pre tabindex="0"><code>[PLOAM]ONUID(112): O4 =&gt; O5
[PLOAM]ONUID(112): O5 =&gt; O6
[PLOAM]ONUID(255): O6 =&gt; O1
</code></pre><p><strong>O6 is POPUP</strong> &ndash; deactivation. The OLT actively kicks the ONU after registration, before any OMCI exchange even starts. This turned out to be caused by a leftover <code>logicPWD</code> field that was set to <code>fiberhome</code> (the FiberHome default). After clearing it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo &gt; /fhcfg/fh_pon/logicPWD
</span></span></code></pre></div><p>The O5-&gt;O6 loop stopped. The ONU stays registered. But still <code>rx_omci: 0</code>. The OLT simply won&rsquo;t talk OMCI to it.</p>
<p>There are more parameters to spoof &ndash; the <strong>OMCC version</strong> byte is still hardcoded somewhere in the ARM binary, and I haven&rsquo;t confirmed the correct VLAN for my region (Vivo 2 might use VLAN 600 instead of 10). But at this point I&rsquo;m patching a proprietary binary one byte at a time without documentation, and each iteration means a cramfs rebuild + CH341A reflash cycle.</p>
<h2 id="what-i-learned">What I learned</h2>
<p><strong>The flash layout matters.</strong> Understanding how the 16MB chip is partitioned into MTD blocks, which ones are cramfs (read-only) vs jffs2 (writable), and how U-Boot selects the active bank &ndash; this is foundational for any embedded hacking. The dual-bank A/B scheme is elegant: safe firmware updates with automatic fallback.</p>
<p><strong>cramfs is a pain.</strong> Any change requires: dump flash, carve partition, extract filesystem, modify files, rebuild image, splice back, flash. A potential improvement is converting the rootfs to jffs2 (the kernel already has the driver for <code>/fhcfg</code>), making everything writable over telnet. One final flash, then never touch the CH341A again.</p>
<p><strong>Proprietary GPON stacks are a wall.</strong> The SD5116 SoC has no public datasheet. The OMCI library is a closed ARM binary that talks to undocumented hardware registers. There&rsquo;s no open-source GPON stack for this chip, and the hacking community (hack-gpon.org) works by modifying proprietary firmware, not replacing it. If you&rsquo;re choosing an ONU for this kind of project, pick one with a <strong>Realtek RTL9601CI</strong> chipset &ndash; those have full community support and let you set every OMCI parameter from a shell command.</p>
<p><strong>The right hardware makes all the difference.</strong> I spent days on cramfs extraction, binary patching, and flash programming. On a V-SOL V2801F (RTL9601CI), the same changes are:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>flash set OMCI_EQ_ID RTF8225VW
</span></span><span style="display:flex;"><span>flash set OMCI_SW_VER1 R8225VWXXXXXX
</span></span><span style="display:flex;"><span>flash set OMCI_FAKE_OK <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>reboot
</span></span></code></pre></div><p>A few commands vs a multi-day reverse engineering project. The FiberHome adventure was a great learning experience about embedded Linux, flash memory, and GPON internals. But for actually getting internet working, the right tool matters more than the right hack.</p>
<p>But this is not over yet.</p>
]]></description>
      
        <media:thumbnail url="https://mariomoura.com/img/posts/onu-hacking.jpeg" />
      
    </item>
    
    
  </channel>
</rss>
