<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>39 Labs</title>
    <link>https://39labs.org/</link>
    <description>Recent content on 39 Labs</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>hello@39labs.org (Anthony DeStefano)</managingEditor>
    <webMaster>hello@39labs.org (Anthony DeStefano)</webMaster>
    <copyright>All rights reserved</copyright>
    <lastBuildDate>Sun, 15 Sep 2024 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://39labs.org/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Colophon</title>
      <link>https://39labs.org/colophon/</link>
      <pubDate>Sun, 15 Sep 2024 00:00:00 +0000</pubDate><author>hello@39labs.org (Anthony DeStefano)</author>
      <guid>https://39labs.org/colophon/</guid>
      <description>This site is built with Hugo using a customized version of the Bear Cub theme. Theme changes include custom colors and fonts, small layout changes, and the addition of post summaries on the home page.&#xA;All pages and posts are written using GNU Emacs and the awesome org-mode package and markup.</description>
      <content:encoded><![CDATA[<p>This site is built with <a href="https://gohugo.io">Hugo</a> using a customized version of the <a href="https://github.com/clente/hugo-bearcub/tree/main">Bear Cub</a> theme. Theme changes include custom colors and fonts, small layout changes, and the addition of post summaries on the home page.</p>
<p>All pages and posts are written using <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> and the awesome <a href="https://orgmode.org/">org-mode</a> package and markup. Export to Markdown and Hugo supported layout is done with the <a href="https://ox-hugo.scripter.co/">ox-hugo</a> Org exporter backend.</p>
<h2 id="design">Design</h2>
<p>The hope for the design was to be as light as possible. I found inspiration from <a href="https://ploum.net/">Ploum</a> and Harman Martinus&rsquo; <a href="https://bearblog.dev/">Bear Blog</a>.</p>
<p>Colors are derived from Prot&rsquo;s <a href="https://protesilaos.com/emacs/ef-themes">ef-themes</a> Emacs themes, mainly the maris-light and maris-dark versions. My own Emacs setup using the ef-day and ef-night themes from the same package.</p>
<p>The primary text font is <a href="https://www.ibm.com/plex/">IBM Plex</a> hosted by Google Fonts. Headings render with the <a href="https://github.com/system-fonts/modern-font-stacks?tab=readme-ov-file#geometric-humanist">Geometric Humanist</a> font list. At some point this may change to remove the Google Fonts depdency, but the IBM Plex family and Avenir are two of my personal favorite fonts.</p>
<h2 id="hosting">Hosting</h2>
<p>Hosting is provided by the included the <a href="https://fastmail.com">Fastmail</a> file storage and web hosting support. Fastmail has been my e-mail provider for close to 15 years and they have been excellent. Maybe one day this site will outgrow the static hosting, but for now it works.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Reviving a Dead Kobo Libra 2</title>
      <link>https://39labs.org/blog/reviving-a-dead-kobo-libra-2/</link>
      <pubDate>Thu, 15 Aug 2024 00:00:00 +0000</pubDate><author>hello@39labs.org (Anthony DeStefano)</author>
      <guid>https://39labs.org/blog/reviving-a-dead-kobo-libra-2/</guid>
      <description>On the second day of my annual beach trip my Kobo Libra 2 eReader greeted me with a screen that flashed twice, turned white and the status LED continuously blinked. I did some quick searching on the web and found these are the symptoms of a bad SD card.</description>
      <content:encoded><![CDATA[<p>On the second day of my annual beach trip my Kobo Libra 2 eReader greeted me with a
screen that flashed twice, turned white and the status LED continuously blinked. I did
some quick searching on the web and found these are the symptoms of a bad SD card.</p>
<p>Luckily, I always bring one or two physical books on this vacation and tucked the Kobo
back into my bag to deal with when I got home.</p>
<h2 id="removing-the-microsd-card">Removing the microSD card</h2>
<p>After returning home, I got out the Kobo and proceeded to remove the back cover. This
is an easy job with a small plastic spudger. iFixit has a <a href="https://www.ifixit.com/Guide/Kobo+Libra+Colour+Back+Cover+Replacement/170299">guide</a> to removing the back
cover of the new Libra Colour which is the same case as the Libra 2. On the main board
is microSD card that in a standard connector. Unfortunately, removing the microSD card
is not as straightforward as popping off the back.</p>
<p>The Libra 2 is IPX 7 rated as waterproof. How do they get an IPX 7 rating with a
plastic cover that can pop on and off so easily?</p>
<p>They cover the entire board, connectors and all, with a waterproof coating.</p>
<p>Removing the coating is not difficult. You can scrape the coating off parts with a
small metal screwdriver. Once started it&rsquo;s easy to pick away the rest with a pair of
tweezers. <a href="https://www.ifixit.com/Guide/Kobo+Libra+Colour+Motherboard+Replacement/170420#s361567">iFixit recommends</a> some heat could also help.</p>
<p>Getting the card out was a bit more difficult. First, there&rsquo;s no easy way to get a
good grip on the card. Usually, it&rsquo;s easy to slide out with your fingertips, but not
when covered in the waterproof coating. Second, the coating seeps <strong>everywhere</strong> and
can really lock in the card. I had to scrape away the coating inside the small opening
of the canister with the tip of the tweezers and gently lift the metal canister away
from the top of the card.</p>
<p>After some light swearing and not gentle pulling on the card with tweezers it finally
came free.</p>
<h2 id="examining-the-microsd-card">Examining the microSD card</h2>
<p>I inserted the microSD card into my trusty ThinkPad running Linux to see what was on
the card. The system found 3 partitions, 2 small Linux partitions and 1 large FAT
partition:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ sudo fdisk -l /dev/sda
</span></span><span class="line"><span class="cl">Disk /dev/sda: 29.72 GiB, 31914983424 bytes, 62333952 sectors
</span></span><span class="line"><span class="cl">Disk model: SD/MMC
</span></span><span class="line"><span class="cl">Units: sectors of 1 * 512 = 512 bytes
</span></span><span class="line"><span class="cl">Sector size (logical/physical): 512 bytes / 512 bytes
</span></span><span class="line"><span class="cl">I/O size (minimum/optimal): 512 bytes / 512 bytes
</span></span><span class="line"><span class="cl">Disklabel type: dos
</span></span><span class="line"><span class="cl">Disk identifier: 0x0d2cc842
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Device     Boot   Start      End  Sectors  Size Id Type
</span></span><span class="line"><span class="cl">/dev/sda1         49152   573440   524289  256M 83 Linux
</span></span><span class="line"><span class="cl">/dev/sda2        573441  1359873   786433  384M 83 Linux
</span></span><span class="line"><span class="cl">/dev/sda3       1359874 62301182 60941309 29.1G  b W95 FAT32</span></span></code></pre></div><p>And it would mount and read the partitions:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ sudo mount /dev/sda1 /mnt
</span></span><span class="line"><span class="cl">$ ls /mnt
</span></span><span class="line"><span class="cl">bin/  drivers/  fs.md5sum  libexec/  lost+found/  proc/  sbin/  tmp/  var/
</span></span><span class="line"><span class="cl">dev/  etc/      lib/       linuxrc@  mnt/         root/  sys/   usr/</span></span></code></pre></div><p>At this point, I wasn&rsquo;t sure what was going on. So I re-installed the microSD card. Pushed the power button. And nothing.</p>
<p>No screen flash. No LED. <strong>Nothing</strong></p>
<h2 id="a-detour-into-dealing-with-more-f-ing-coating">A detour into dealing with more f#!*@ing coating</h2>
<p>The next morning I brought out the big guns. By big guns I mean the soldering iron. On the main board there is are four points helpfully labeled as <code>V</code>, <code>TX</code>, <code>RX</code>, and ground. That certainly looks like a serial port. I did a quick test with a multi-meter and there was a bit of 3.3v flickering on the <code>TX</code> point. That certainly is a serial port.</p>
<p>I soldering three temporary wires to the <code>TX</code>, <code>RX</code>, and ground points, connected a TTL to USB serial cable rated for 3.3v, fired up <code>minicom</code>, and pushed the power button. Quickly a  U-Boot banner scrolled by and just as quickly a U-Boot prompt. That&rsquo;s cool, but not really what I wanted to see.</p>
<p>Scrolling back through the output I found this:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">*** Warning - MMC init failed, using default environment</span></span></code></pre></div><p>That seems bad.</p>
<p>Above I mentioned how the waterproof coating gets everywhere. By, everywhere I mean <strong>everywhere</strong>. After some thrashing around I realized the bottom of the microSD card had flakes of coating on in. I thought that maybe some of that was still inside the microSD card case on the board and may be causing issues with contact. I reached in with a fine, flat screwdriver and scraped off each contact, and tried booting again.</p>
<p>The screen flashed twice and the LED was blinking. I was back to where I started.</p>
<p>The serial output showed U-Boot find the card and started to boot a Linux kernel. Now I saw the real error.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">mmcblk0: card_busy_detect: error sending status cmd, status 0x80900
</span></span><span class="line"><span class="cl">mmcblk0: card_busy_detect: error sending status cmd, status 0x80900
</span></span><span class="line"><span class="cl">mmcblk0: card_busy_detect: error sending status cmd, status 0x80900
</span></span><span class="line"><span class="cl">mmcblk0: card_busy_detect: error sending status cmd, status 0x80900
</span></span><span class="line"><span class="cl">mmcblk0: card_busy_detect: error sending status cmd, status 0x80900
</span></span><span class="line"><span class="cl">mmcblk0: card_busy_detect: error sending status cmd, status 0x80900
</span></span><span class="line"><span class="cl">mmcblk0: card_busy_detect: error sending status cmd, status 0x80900
</span></span><span class="line"><span class="cl">blk_update_request: I/O error, dev mmcblk0, sector 311302
</span></span><span class="line"><span class="cl">Buffer I/O error on dev mmcblk0p1, logical block 131075, lost async page write</span></span></code></pre></div><p>and finally</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">EXT4-fs (mmcblk0p1): error loading journal
</span></span><span class="line"><span class="cl">Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,1)
</span></span><span class="line"><span class="cl">---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on
</span></span><span class="line"><span class="cl">unknown-block(179,1)
</span></span><span class="line"><span class="cl">random: nonblocking pool is initialized</span></span></code></pre></div><p>## What&rsquo;s really going on The two side effects, the screen blinking and LED flashing,
are part of the Linux boot process. When the kernel initializes the display device it
causes the two flashes. It also starts the LED flashing before it tries to mount the
root file system. Since that file system is never mounted the LED never stops
flashing.</p>
<p>But why does the card work fine in my laptop? I pull it out of the Kobo and load it
back in my laptop to make sure I didn&rsquo;t somehow damage the card. It still shows up and
mounts fine. I copied a random file to the card and that works, too.</p>
<p>Put it back in the Kobo. Boot up and it still can&rsquo;t mount the root file system.</p>
<p>Pull out the card, put back it in the laptop, and mount again. This time I notice the
file I wrote wasn&rsquo;t there.</p>
<p>At this point I knew I needed a new microSD card. I&rsquo;m still not sure why it seemed to
work fine on my laptop with no errors. A mystery for another day.</p>
<h2 id="re-imaging-a-new-microsd-card">Re-imaging a new microSD card</h2>
<p>In my stash I had a 16GB microSD card. Smaller than the 32GB that comes with the
device, but I never needed that much space on my Kobo. If I had a good card I could
<code>dd</code> and image off of that, but I wasn&rsquo;t sure of the state of my current card. It
would read on my laptop, but I didn&rsquo;t trust the state of that card anymore.</p>
<p>It is left as an exercise to the reader to find a backup image somewhere on the
web. It&rsquo;s not too bad.</p>
<p>Wrote a backup image to the microSD card with <code>dd</code>, put in the Kobo, and booted
up. Screen blinked, LED flashed, LED went out, and then the &ldquo;Do not power down&rdquo; image
showed up. After rebooting a few times it went to the select a language page.</p>
<p><strong>Success!</strong></p>
<h2 id="updating-the-serial-number">Updating the serial number</h2>
<p>But something still didn&rsquo;t seem right. All of your Kobo data is stored on the FAT
partition including a special directory <code>.kobo</code>. In there includes your settings,
version, and serial number information. But where does that come from?</p>
<p>I dug around in the U-Boot output and saw that when the card was not found even U-Boot
didn&rsquo;t get far because it was looking for configuration data on the microSD
card. Doing a bit more digging I found that even the device serial number is stored in
that space on the card at logical address 0x200 starting with &ldquo;SN-N&rdquo;. The backup that
I got kindly zeroed out the serial number.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ hexdump -C -s 512 -n 16 backup_Libra2_RevE_nosn.img
</span></span><span class="line"><span class="cl">00000200  53 4e 2d 4e 30 30 30 30  30 30 30 30 30 30 30 30  |SN-N000000000000|</span></span></code></pre></div><p>To add the correct serial number, load the backup file in any hex editor and put in
your serial number starting at 0x204. On the Libra 2 it&rsquo;s on a sticker stuck to the
battery. Write the updated version of the file onto the card with <code>dd</code> like before.</p>
<p>After a couple more reboots the language selection screen shows up. After a couple
more screen you need to re-register the device with kobo. If you have purchased books
via the Kobo online store they should even be automatically downloaded.</p>
<h2 id="restoring-books-and-reading-stats">Restoring books and reading stats</h2>
<p>I don&rsquo;t use the Kobo store and instead sideline books using <a href="https://calibre-ebook.com/">Calibre</a>. To get my books
back, I took a chance and did a copy from the old, maybe working microSD card, to the
new one. Once the Kobo disconnected from my computer it did the normal import of files
and everything was there. Even Calibre thought everything was back to working order,
but&hellip;</p>
<p>Every book showed as unread.</p>
<p>Kobo stores reading stats in the <code>.kobo/KoboReader.sqlite</code> database on the FAT
partition. If you search online you&rsquo;ll find directions on moving that file to a new
device. It includes updating the database to match the new device. However, since
you&rsquo;re not moving to a new device and you&rsquo;ve updated the serial number correctly there
is no need to change anything in the database. Copy it over and the reading stats will
come back.</p>
<p>Now I was happy.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
