Skip to content

Instantly share code, notes, and snippets.

@cellularmitosis
Last active April 9, 2025 18:44
Show Gist options
  • Save cellularmitosis/a79c663f2e8430bc58bab61d459c9c1b to your computer and use it in GitHub Desktop.
Save cellularmitosis/a79c663f2e8430bc58bab61d459c9c1b to your computer and use it in GitHub Desktop.
Running the MIPS Creator CI20 from an SD card rootfs

Blog 2025/4/8

<- previous | index | next ->

Running the MIPS Creator CI20 from an SD card rootfs

IMG_5109

In a previous post, I described setting up Debian on the MIPS Creator CI20 SBC.

However, there were a couple of outstanding issues:

  • All of the SD card images available for the CI20 copy their contents to the onboard NAND flash, and the CI20 runs from a NAND flash rootfs, not an SD card rootfs
    • Eventually, NAND flash wears out (and cannot be replaced), so I'd instead like to run from the SD card as rootfs.
  • A number of people have experienced crashes with the CI20, which appear to be due to bad RAM timings.

In this post, I'll describe how I got my CI20 to run from SD card rootfs by making a few modifications to a script and using Gabriele's u-boot fork.

Dependencies

This process uses this script:

and this Debian rootfs tarball:

However, I had to make a couple of modifications to the script, and I've attached the modified version to this gist.

On a Debian box:

  • install a MIPS cross-compiler and mtd-utils
  • download the modified script
  • download the Debian rootfs tarball
  • extract the uImage from the tarball
sudo apt-get --yes install gcc-mipsel-linux-gnu mtd-utils
wget http://mipscreator.mips.com/CI20/images/default_NAND/Debian8_20160602/rootfs_2016_06_02.tar
wget https://gist.githubusercontent.com/cellularmitosis/a79c663f2e8430bc58bab61d459c9c1b/raw/08da3bdf1580d6e9eaab55900766d694edad5ae4/make-flash-card-ci20-sd.sh
chmod +x make-flash-card-ci20-sd.sh
tar -xaf rootfs_2016_06_02.tar boot/uImage-3.18.3-ci20-1

Run the script

First, figure out the device node of your SD card (try sudo dmesg after inserting it). Set that as a variable (here, I'm using /dev/sdz so folks don't clobber a hard drive by copy/pasting).

SDDEV=/dev/sdz

Here is how I invoked the script:

CROSS_COMPILE=mipsel-linux-gnu- \
UBOOT_REPO=https://github.com/gabrielesvelto/CI20_u-boot \
UBOOT_BRANCH=fixed-timings \
./make-flash-card-ci20-sd.sh \
    $SDDEV \
    boot/uImage-3.18.3-ci20-1 \
    rootfs_2016_06_02.tar

Wait for the script to finish, then insert the SD card into your CI20, set the boot jumper on pins 2-3, and boot it up.

You can log in as user ci20, password ci20, and the root user's password is also ci20.

If using ssh, you can find the CI20's IP address by listing all of the machines on your network which are running ssh on port 22:

sudo nmap -p 22 --open 192.168.1.0/24

Script changes

For the record, here are the changes I made to the script:

$ diff -urN make-flash-card-ci20-sd.sh.orig make-flash-card-ci20-sd.sh
--- make-flash-card-ci20-sd.sh.orig	2025-04-08 14:32:18.681202719 -0500
+++ make-flash-card-ci20-sd.sh	2025-04-08 14:33:27.100526152 -0500
@@ -12,7 +12,8 @@
 #   instead of just kernel or ../../kernel. Even if in the same directory
 
 
-set -e
+set -e -o pipefail
+set -x
 tmpDir=`mktemp -d`
 
 cleanup()
@@ -74,10 +75,10 @@
 # Deleting old uboot environment
 sudo dd if=/dev/zero of=${device} bs=1K seek=526 count=32
 
-# create ext4 partition
-sudo mkfs.ext4 ${device}1
+# create ext2 partition
+sudo mkfs.ext2 ${device}1
 
-# mount ext4 partition
+# mount the partition
 sdMount=${tmpDir}/sd_mount
 mkdir ${sdMount}
 sudo mount ${device}1 ${sdMount}
@@ -122,10 +123,15 @@
 fi
 
 echo "Deleting /etc/fstab"
-rm -f ${sdMount}/etc/fstab
+sudo rm -f ${sdMount}/etc/fstab
 
 echo "SD contents:"
 ls -hl ${sdMount}/
 
+echo "Converting from ext2 to ext4"
+sudo umount ${sdMount}
+unset sdMount
+sudo tune2fs -O extents,uninit_bg,dir_index,has_journal ${device}1
+
 echo "Finished, wait for clean up before removing your card!"
 sync

The ext4 issue

You'll notice in above script changes that I first used ext2, then converted to ext4.

This is a workaround for a strange bug (which others have also experienced), where u-boot can't see some of the files on an ext4 filesystem.

My CI20 wasn't booting from SD card, and after hooking up a serial console, I saw this from u-boot:

Hit any key to stop autoboot:  0 
** File not found /boot/uImage **
Wrong Image Format for bootm command
ERROR: can't get kernel image!
ci20# 

I was able to list the files:

ci20# ext4ls mmc 0:1 /
<DIR>       4096 .
<DIR>       4096 ..
<DIR>      16384 lost+found
<DIR>       4096 bin
<DIR>          0 boot
<DIR>       4096 dev
<DIR>          0 etc
<DIR>       4096 home
<DIR>          0 lib
<DIR>       2492 media
<DIR>          0 mnt
<DIR>    5270623 opt
<DIR>       4096 proc
<DIR>        894 root
<DIR>          0 run
<DIR>       4096 sbin
<DIR>          0 srv
<DIR>       4096 sys
<DIR>          0 tmp
<DIR>       4096 usr
<DIR>       4096 var
ci20# 

but noticed that many of those directories had a zero size, and the confirmed that /boot appeared to be empty:

ci20# ext4ls mmc 0:1 /boot
ci20#

I mounted the SD card in a linux box, and sure enough, the files are actually there:

$ ls -1 /boot
config-3.18.3-ci20-1
System.map-3.18.3-ci20-1
uImage
uImage-3.18.3-ci20-1
vmlinux.img

a quick sanity check was to make a copy of uImage at the root level and then manually boot that, which worked:

ci20# ext4load mmc 0:1 0x00800000 /uImage
5270623 bytes read in 647 ms (7.8 MiB/s)
ci20# bootm 0x800000
## Booting kernel from Legacy Image at 00800000 ...
   Image Name:   Linux-3.18.3-ci20-1
   Image Type:   MIPS Linux Kernel Image (gzip compressed)
   Data Size:    5270559 Bytes = 5 MiB
   Load Address: 80010000
   Entry Point:  80782930
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK

Starting kernel ...

I then experimented and found the ext2/ext4 workaround.

Serial console connection

I used a cheap USB-to-serial dongle from ebay.

Wiring connections: (see 1 and 2

dongle GND  ->  CI20 GND (pin 6)
dongle RX   ->  CI20 TX (pin 8)
dongle TX   ->  CI20 RX (pin 10)

I then ran tio /dev/ttyUSB0, which defaults to 115200 baud.

TL;DR

Set your SD card device as an env var:

SDDEV=/dev/sdz

then run this:

sudo apt-get --yes install gcc-mipsel-linux-gnu mtd-utils
wget http://mipscreator.mips.com/CI20/images/default_NAND/Debian8_20160602/rootfs_2016_06_02.tar
wget https://gist.githubusercontent.com/cellularmitosis/a79c663f2e8430bc58bab61d459c9c1b/raw/08da3bdf1580d6e9eaab55900766d694edad5ae4/make-flash-card-ci20-sd.sh
chmod +x make-flash-card-ci20-sd.sh
tar -xaf rootfs_2016_06_02.tar boot/uImage-3.18.3-ci20-1
CROSS_COMPILE=mipsel-linux-gnu- \
UBOOT_REPO=https://github.com/gabrielesvelto/CI20_u-boot \
UBOOT_BRANCH=fixed-timings \
./make-flash-card-ci20-sd.sh \
    $SDDEV \
    boot/uImage-3.18.3-ci20-1 \
    rootfs_2016_06_02.tar
#!/bin/bash
#
# Copyright (c) 2013 Imagination Technologies
# Author: Paul Burton <[email protected]>
#
# Creates a bootable SD card for the CI20 using a kernel and rootfs tarball.
#
# Usage:
# ./make-flash-card.sh /dev/sdX /path/to/vmlinux /path/to/rootfs.tar.xz
# the path to vmlinux can be uImage as well.
# Please use full paths while passing arguments. i.e. /home/user/ci20/linux/kernel
# instead of just kernel or ../../kernel. Even if in the same directory
set -e -o pipefail
set -x
tmpDir=`mktemp -d`
cleanup()
{
echo "Cleaning up..."
[ -z "${sdMount}" ] || sudo umount ${sdMount}
sync; sync; sync
rm -rf ${tmpDir}
trap - EXIT INT TERM
}
trap cleanup EXIT INT TERM
die()
{
echo "$@" >&2
exit 1
}
# check device
device="$1"
[ -e "${device}" ] || die "Device '${device}' not found"
grep ${device} /etc/mtab >/dev/null && \
die "Device '${device}' contains mounted partitions"
# check kernel
vmlinux="$2"
[ -e "${vmlinux}" ] || die "Kernel (vmlinux) '${vmlinux}' not found"
# check root filesystem
rootTar="$3"
[ -e "${rootTar}" ] || die "Root filesystem tarball '${rootTar}' not found"
# default environment
[ ! -z "${CROSS_COMPILE}" ] || export CROSS_COMPILE=mips-linux-gnu-
[ ! -z "${UBOOT_REPO}" ] || UBOOT_REPO="https://github.com/MIPS/CI20_u-boot"
[ ! -z "${UBOOT_BRANCH}" ] || UBOOT_BRANCH="ci20-v2013.10"
if [ -z "${JOBS}" ]; then
cpuCount=`grep -Ec '^processor' /proc/cpuinfo`
JOBS=`echo "${cpuCount} * 2" | bc`
fi
# check for tools
which bc >/dev/null || die "No bc in \$PATH"
which fakeroot >/dev/null || die "No fakeroot in \$PATH"
which sfdisk >/dev/null || die "No sfdisk in \$PATH"
which mkfs.ext4 >/dev/null || die "No mkfs.ext4 in \$PATH"
which mkfs.ubifs >/dev/null || die "No mkfs.ubifs in \$PATH"
${CROSS_COMPILE}gcc --version >/dev/null 2>&1 || \
die "No ${CROSS_COMPILE}gcc, set \$CROSS_COMPILE"
${CROSS_COMPILE}objcopy --version >/dev/null 2>&1 || \
die "No ${CROSS_COMPILE}objcopy, set \$CROSS_COMPILE"
# partition SD/MMC card
sudo sfdisk ${device} -L << EOF
2M,,L
EOF
# Deleting old uboot environment
sudo dd if=/dev/zero of=${device} bs=1K seek=526 count=32
# create ext2 partition
sudo mkfs.ext2 ${device}1
# mount the partition
sdMount=${tmpDir}/sd_mount
mkdir ${sdMount}
sudo mount ${device}1 ${sdMount}
# clone u-boot
ubootDir=$tmpDir/u-boot
git clone ${UBOOT_REPO} -b ${UBOOT_BRANCH} --depth 1 $ubootDir
# build & install MMC u-boot
pushd $ubootDir
make distclean
make ARCH=mips ci20_mmc
# make -j${JOBS}
maxsize=14336
cursize=$(wc -c < spl/u-boot-spl.bin)
# JZ4780 internal boot ROM reads 14KB (14336 bytes) of data from the boot device
if [ $cursize -ge $maxsize ]; then
die "Size '${cursize}' is over '${maxsize}' bytes"
fi
sudo dd if=spl/u-boot-spl.bin of=${device} obs=512 seek=1
sudo dd if=u-boot.img of=${device} obs=1K seek=14
popd
echo "Untarring rootfs into sd card"
sudo tar -xaf ${rootTar} -C ${sdMount}
if file "${vmlinux}" | grep uImage >/dev/null; then
# already a uImage
if [ ! -d "${sdMount}/boot" ]; then
mkdir -p "${sdMount}/boot";
fi;
sudo cp -v "${vmlinux}" ${sdMount}/boot/vmlinux.img
else
# generate kernel uImage
vmlinuxBin=${tmpDir}/vmlinux.bin
${CROSS_COMPILE}objcopy -O binary ${vmlinux} ${vmlinuxBin}
${ubootDir}/tools/mkimage \
-A mips -O linux -T kernel -C none -a 0x80010000 \
-e `readelf -h ${vmlinux} | grep 'Entry point' | awk '{print $4}'` \
-n "CI20 Linux" -d ${vmlinuxBin} ${sdMount}/boot/vmlinux.img
fi
echo "Deleting /etc/fstab"
sudo rm -f ${sdMount}/etc/fstab
echo "SD contents:"
ls -hl ${sdMount}/
echo "Converting from ext2 to ext4"
sudo umount ${sdMount}
unset sdMount
sudo tune2fs -O extents,uninit_bg,dir_index,has_journal ${device}1
echo "Finished, wait for clean up before removing your card!"
sync
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment