Rescuing N900

The problem

The battery was completely depleted and device couldn't boot. It was dying before it could start charging the battery.

Also for some reason, flashing didn't work. I was plugging the device to my laptop, holding 'u' key, but it didn't show up as an USB device.

The opportunitiy

I had U-Boot installed earlier. I was playing with running postmarketOS, so I had an SD card properly formatted. I could choose menu entries and even enter U-Boot console, but I had very short time before it was dying and rebooting.

The solution

This method allows to boot rescueOS with default U-Boot "External SD card" menu entry.

  • Download rescueOS kernel and initrd image
  • Convert kernel zImage to uImage using

    mkimage \
        -A arm \
        -O linux \
        -T kernel \
        -C none \
        -a 80008000 \
        -e 80008000 \
        -n kernel \
        -d rescueOS_n900_kernel_1.3.zImage \
  • Convert initrd image using

    mkimage \
        -A arm \
        -O linux \
        -T ramdisk \
        -C none \
        -a 0 \
        -e 0 \
        -n initrd \
        -d rescueOS-1.3.img \
  • Create boot.cmd file

    setenv bootargs rootdelay root=/dev/ram0;
    setenv setup_omap_atag 1;
    setenv mmckernfile rescueOS_n900_kernel_1.3.uImage;
    setenv mmcinitrdfile rescueOS-1.3.uimg;
    setenv mmcscriptfile;
    run trymmckerninitrdboot;
  • Convert boot.cmd to boot.scr

    mkimage \
        -c none \
        -A arm \
        -T script \
        -d boot.cmd \
  • Use SD card with partition type ext2/3/4 or FAT. If you have multiple partitions, use first one.

  • Put boot.scr rescueOS_n900_kernel_1.3.uImage and rescueOS-1.3.uimg on SD card

  • Put SD card into N900, power it on and use "External SD card" in U-Boot.

  • Once the system is booted type "chargebat" command.

How I figured this out

First I tried easy methods. The "u-boot charging?" thread on suggested that letting it charge on bootloader could help, but it wasn't working for me. Then I tried running rescueOS, but I found that, for unknown reason, flasing doesn't work either. What I was left with, was trying to run rescueOS from SD card with U-Boot.

I tried to figure out how adding entries to U-Boot works under the hood. In rescueOS sources there is an example U-Boot menu entry in file (uboot_item_by_kerio), but it seems to be a bit outdated. Anyway, I looked at u-boot-update-bootmenu script from pali's u-boot-maemo and concluded that it would create this U-Boot script:

setenv mmcnum 0;
setenv mmcpart 1;
setenv mmctype ext2;
setenv bootargs rootdelay root=/dev/ram0;
setenv setup_omap_atag 1;
setenv mmckernfile rescueOS_n900_kernel_1.3.zImage;
setenv mmcinitrdfile rescueOS-1.3.img;
setenv mmcscriptfile;
run trymmckerninitrdboot;

I tried to type those commands in "U-Boot console", but the device was dying before I could finish.

Next I tried to understand how default U-Boot menu entries work. I found the implementation in the include/configs/nokia_rx51.h file in U-Boot source. It's surprisingly readable. For example this part:

"trymmcpartboot=setenv mmcscriptfile boot.scr;
        run trymmcscriptboot;" \
    "setenv mmckernfile uImage; run trymmckernboot\0" \

says that it'll try to run commands from boot.scr file. Also at this point variables "mmcnum", "mmcpart" and "mmctype" are already defined, so they can be removed from my boot script.

So I uploaded the script, kernel and initrd image on SD card, booted the phone and it didn't work. It went past my script and continued to boot postmarketOS I still had on this card.

By grepping for "boot.scr" in U-Boot sources I found the command required to convert text boot script into binary format accepted by U-Boot.

So I uploaded the converted boot script, booted the phone and it still didn't work.

I poked at the "uImage" file of postmarketOS with "file" command and found that it's an "u-boot legacy uImage". Kernel image of rescueOS is a "zImage". On U-Boot "homepage" I found a command to do required conversion.

So I uploaded the converted kernel image, updated the boot script, booted the phone and it still didn't work. This time the correct kernel was booting, but it stopped at:

Kernel panic - not syncing: VFS:
    Unable to mount root fs on unknown-block(1,0)

Despite many web searches I was clueless. I decided I need to take a step back and, instead of looking for what went wrong, look for how to do it right. I started reading README from U-Boot sources. Fortunately I quickly found that the initrd image needs to be converted as well.

So I uploaded the converted initrd image, updated the boot script, booted the phone and SUCCESS!!! It worked! Now I just needed to quickly type "chargebat" command and my phone was rescued.

After this long adventure I looked again at the "u-boot-update-bootmenu" script and found that it already contains commands to convert kernel and initrd, but somehow I skipped them (facepalm). At this point I could only verify that the conversion command are correct.

2020-12-05 Update: I added this instruction to rescueOS documentation in PR#2.