raspberrypi-2-b

Raspberry Pi. Boot from 128Mb microSD card and USB flash drive

Spread the love

Overview

So I have a Raspberry Pi 2 B (the latest model at the moment of writing this article – Dec 2015), 128Mb size SD card and some USB flash drive. The goal is to make the Raspberry Pi boot from 128Mb microSD card and continue loading everything else from the USB flash drive.

The problem is in that that the official raspbian distributives does not allow you to use microSD card smaller than a 1Gb to boot the system from (minimum recommended is 4Gb), and that’s what we will be dealing with here.

This article is updated – Jan 2024.

Please read this article for more solutions.

Context

Raspberry Pi can not be booted directly from USB flash drive (actually can, read this), but only from the microSD card, and more interesting, most available Raspbian OS (or Raspberry Pi OS now) images are bigger than 1Gb of size, so it is impossible to boot the Raspberry Pi from the 128Mb microSD card w/o customization.

The described below method will allow you to boot Raspberry Pi OS using the 128Mb microSD card, however you still need some additional storage to complete the OS loading – the USB flash drive, since it still needs more space for everything else needed for the system to be successfully loaded and running.

Bear in mind that the read/write speed of your SD card might be significantly slower/faster than your USB flash drive, which may affect your OS system loading speed.

Prerequisites

Usually the original Raspbian (or Raspberry Pi) OS image contains two partitions, one is /boot, and another one is /. In this article I will show you how to derive the /boot partition only and write it onto the microSD card, so the system will be able to start booting from the microSD card, and then, by editing cmdline.txt file of the /boot partition, we will tell the system to continue loading from the other source (USB flash drive or even network storage, i.e. NFS). Before the system will switch to the other source the system will load all required drivers, so the other source will be accessible for the system when it switches to it. /etc/fstab also needs to be changed so all drives are mounted correctly on each system start.

Usually the /boot partition of the image is not bigger than 50-70Mb, even if the partition itself is bigger (in the latest Raspberry Pi OS it is usually 256Mb), the total files size is less than 128Mb, that’s exactly what we need for this project.

We would need the laptop with any Ubuntu or Debian system installed, or if you use Windows – install Debian or Ubuntu on VirtualBox, or if your Windows is 11 – use WSL (Windows Subsystem for Linux).

We also need 128Mb microSD card and at least 4Gb USB flash drive.

I will be using Windows 11 with WSL in all my code samples below.

Just reminding you that the standard/default login/pass for the Raspberry Pi OS are:

  • login: pi
  • password: raspberry

Don’t forget to change the password once all is done and you finally see the Raspberry Pi OS welcome or configuration screen 🙂 .

Let’s get started

Prepare your WSL

By default WSL is not able to see (as well as read from or write to) your USB (including microSD card) devices attached physically to your PC/laptop. However there is a solution for that, build your custom linux kernel for WSL which will support USB devices, so then the USB drive can be attached from Windows to WSL and seen by WSL distro in the same way as on original linux OS, as a /dev/sd* device. The whole process is described here.

Download and analyze the Raspbian OS image

  1. Log in to your WSL distro (I’m using Ubuntu):
    wsl -d Ubuntu
  2. Download the Raspberry Pi OS image (Bullseye, 32bit legacy) from Raspberry Download source. Basically you can use any prior Raspbian OS, or Raspberry Pi OS except the latest (starting from bookworm) Raspberry Pi OS images, since they have a different options of booting from USB and other devices, read this:
    cd /tmp && wget https://downloads.raspberrypi.com/raspios_oldstable_armhf/images/raspios_oldstable_armhf-2023-12-06/2023-12-05-raspios-bullseye-armhf.img.xz
  3. Extract the image file:
    xz -dv 2023-12-05-raspios-bullseye-armhf.img.xz
  4. Analyze the downloaded image:
    sudo apt update && sudo apt install fdisk && \
    fdisk -l 2023-12-05-raspios-bullseye-armhf.img

    There should be the result like this:

    Disk 2023-12-05-raspios-bullseye-armhf.img: 3.99 GiB, 4286578688 bytes, 8372224 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0x54aa0fc0
    
    Device                                 Boot  Start     End Sectors  Size Id Type
    2023-12-05-raspios-bullseye-armhf.img1        8192  532479  524288  256M  c W95 FAT32 (LBA)
    2023-12-05-raspios-bullseye-armhf.img2      532480 8372223 7839744  3.7G 83 Linux

    From the listing above we can clearly see that each sector is 512 bytes of size, the first 2023-12-05-raspios-bullseye-armhf.img1 image partition starts from sector 8192 and ends by sector 532479, total 524288 sectors, which is 256Mb of size (partition size, not the real files size). The second image partition 2023-12-05-raspios-bullseye-armhf.img2 starts from sector 532480 and ends by sector 8372223, total 7839744 sectors, which is 3.7Gb of size which we would not be able to write to our microSD card but we can easily write it to any 4Gb USB flash drive. We need the data of the first partition (2023-12-05-raspios-bullseye-armhf.img1) which we will extract from the original image and write onto the microSD card. On the USB flash drive we will write the second partition – 2023-12-05-raspios-bullseye-armhf.img2

Mount first partition

Create a respective mount folders in /mnt:

cd /mnt && \
sudo mkdir image_boot image_data sdcard usbdrive

Mount first image partition to /mnt/image_boot folder. Offset is calculated by Sector size multiplied on sector Start:

sudo mount -t vfat -o loop,offset=$((8192*512)) /tmp/2023-12-05-raspios-bullseye-armhf.img /mnt/image_boot/

Check the real size of the partition, used by files:

df -h

You should see something like:

Filesystem      Size  Used Avail Use% Mounted on
none            3.9G  4.0K  3.9G   1% /mnt/wsl
none            3.8T  300G  3.5T   8% /usr/lib/wsl/drivers
/dev/sdc       1007G   19G  938G   2% /
none            3.9G   92K  3.9G   1% /mnt/wslg
none            3.9G     0  3.9G   0% /usr/lib/wsl/lib
rootfs          3.9G  2.1M  3.9G   1% /init
none            3.9G  860K  3.9G   1% /run
none            3.9G     0  3.9G   0% /run/lock
none            3.9G     0  3.9G   0% /run/shm
tmpfs           4.0M     0  4.0M   0% /sys/fs/cgroup
none            3.9G   76K  3.9G   1% /mnt/wslg/versions.txt
none            3.9G   76K  3.9G   1% /mnt/wslg/doc
C:\             3.8T  300G  3.5T   8% /mnt/c
G:\              15G  6.5G  8.6G  44% /mnt/g
snapfuse         75M   75M     0 100% /snap/core22/1033
snapfuse        128K  128K     0 100% /snap/bare/5
snapfuse         74M   74M     0 100% /snap/core22/864
snapfuse         92M   92M     0 100% /snap/gtk-common-themes/1535
snapfuse         41M   41M     0 100% /snap/snapd/20290
snapfuse         41M   41M     0 100% /snap/snapd/20671
snapfuse        132M  132M     0 100% /snap/ubuntu-desktop-installer/1276
snapfuse        131M  131M     0 100% /snap/ubuntu-desktop-installer/1280
/dev/loop0      255M   51M  205M  20% /mnt/image_boot

Look at /dev/loop0, which is mounted to /mnt/image_boot, as you can see, the used space is only 51M from 255M of partition size (205M is available), so our 128Mb (even 64Mb) microSD card should perfectly fit.

Attach microSD card

Insert the microSD card in one of the physical port of your PC/laptop (Windows) and attach it to WSL (as described here), and check whether it is appeared in WSL properly:

lsusb

There should be something like:

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 011: ID 14cd:1212 Super Top microSD card reader (SY-T18)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Then run the following:

ls -al /dev/sd*

You should see new records in this list, which were not there before the microSD card attached to WSL, something like:

brw-rw---- 1 root disk 8,  0 Jan 16 12:38 /dev/sda
brw-rw---- 1 root disk 8, 16 Jan 16 12:38 /dev/sdb
brw-rw---- 1 root disk 8, 32 Jan 16 12:38 /dev/sdc
brw-rw---- 1 root disk 8, 48 Jan 16 20:08 /dev/sdd

The /dev/sdd – new record (new USB device).
Now check the new USB device by running this command:

sudo lsblk -f

You should see your /dev/sdd at bottom of the list:

NAME  FSTYPE FSVER LABEL  UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
loop0 vfat   FAT32 bootfs 9C6E-1858                             204.6M    20% /mnt/image_boot
sda   ext4   1.0
sdb   swap   1            200c5d9b-37a9-40e4-8978-29ce5d555db6                [SWAP]
sdc   ext4   1.0          193d5217-6469-4205-8067-2e4fe4f76658  935.3G     2% /snap
                                                                              /mnt/wslg/distro
                                                                              /
sdd   vfat   FAT16        7C3E-ED07

Format microSD card

To be able to boot Raspberry Pi from your microSD card, it needs to be properly formatted with the right partition tables and filesystem. The partition table should be W95 FAT32 (LBA) with id 0c (or just c), for this we will use fdisk utility:

sudo fdisk /dev/sdd

and then type m (to display all possible commands), d (if you have already some partitions it needs to be deleted), F (to show all free unpartitioned size, it should show all space of your disk), o (to change the disklabel type to dos), n (to create a new partition, leave all parameters by default, just press enter for all prompts), t (to change the partition type to the 0c W95 FAT32 (LBA)) and finally w (to write it all to the disk), and then check what you did by typing sudo fdisk -l /dev/sdd, you should see something like:

Disk /dev/sdd: 121.25 MiB, 127139840 bytes, 248320 sectors
Disk model: Storage Device
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xf749f5de

Device     Boot Start    End Sectors   Size Id Type
/dev/sdd1        2048 248319  246272 120.3M  c W95 FAT32 (LBA)

Format just created microSD card partition (/dev/sdd1) to vfat (FAT32) filesystem:

sudo mkfs -t vfat /dev/sdd1

We need PARTUUID of just created partition for later use (in /etc/fstab), run sudo blkid /dev/sdd1 and write it down somewhere:

/dev/sdd1: SEC_TYPE="msdos" UUID="888A-9013" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="f749f5de-01"

Mount microSD card

Mount microSD card to /mnt/sdcard folder:

sudo mount /dev/sdd1 /mnt/sdcard

Check that the mounting was successful by typing df -h, you should see /dev/sdd1 mounted to /mnt/sdcard in the bottom of the list:

Filesystem      Size  Used Avail Use% Mounted on
none            3.9G  4.0K  3.9G   1% /mnt/wsl
none            3.8T  300G  3.5T   8% /usr/lib/wsl/drivers
/dev/sdc       1007G   19G  938G   2% /
none            3.9G   92K  3.9G   1% /mnt/wslg
none            3.9G     0  3.9G   0% /usr/lib/wsl/lib
rootfs          3.9G  2.1M  3.9G   1% /init
none            3.9G  864K  3.9G   1% /run
none            3.9G     0  3.9G   0% /run/lock
none            3.9G     0  3.9G   0% /run/shm
tmpfs           4.0M     0  4.0M   0% /sys/fs/cgroup
none            3.9G   76K  3.9G   1% /mnt/wslg/versions.txt
none            3.9G   76K  3.9G   1% /mnt/wslg/doc
C:\             3.8T  300G  3.5T   8% /mnt/c
G:\              15G  6.5G  8.6G  44% /mnt/g
snapfuse         75M   75M     0 100% /snap/core22/1033
snapfuse        128K  128K     0 100% /snap/bare/5
snapfuse         74M   74M     0 100% /snap/core22/864
snapfuse         92M   92M     0 100% /snap/gtk-common-themes/1535
snapfuse         41M   41M     0 100% /snap/snapd/20290
snapfuse         41M   41M     0 100% /snap/snapd/20671
snapfuse        132M  132M     0 100% /snap/ubuntu-desktop-installer/1276
snapfuse        131M  131M     0 100% /snap/ubuntu-desktop-installer/1280
/dev/loop0      255M   51M  205M  20% /mnt/image_boot
/dev/sdd1       120M     0  120M   0% /mnt/sdcard

Copy first image partition files onto microSD card

Now we should be able to copy the files from first partition of the image onto the microSD card:

sudo rsync -a --info=progress2 /mnt/image_boot/ /mnt/sdcard/

In the end you should see the 100% progress, like this:

     52,531,459 100%  131.10MB/s    0:00:00 (xfr#328, to-chk=0/330)

Mount second partition

To be able to mount the second partition, the first one (mounted earlier) shall be unmounted:

sudo umount /dev/loop1

Now we can mount second image partition to /mnt/image_data folder (pretty much the same way as we mounted the first partition):

sudo mount -t ext4 -o loop,offset=$((532480*512)) /tmp/2023-12-05-raspios-bullseye-armhf.img /mnt/image_data/

Check the real size of the partition, used by files:

df -h

You should see something like:

Filesystem      Size  Used Avail Use% Mounted on
none            3.9G  4.0K  3.9G   1% /mnt/wsl
none            3.8T  300G  3.5T   8% /usr/lib/wsl/drivers
/dev/sdc       1007G   19G  938G   2% /
none            3.9G   92K  3.9G   1% /mnt/wslg
none            3.9G     0  3.9G   0% /usr/lib/wsl/lib
rootfs          3.9G  2.1M  3.9G   1% /init
none            3.9G  864K  3.9G   1% /run
none            3.9G     0  3.9G   0% /run/lock
none            3.9G     0  3.9G   0% /run/shm
tmpfs           4.0M     0  4.0M   0% /sys/fs/cgroup
none            3.9G   76K  3.9G   1% /mnt/wslg/versions.txt
none            3.9G   76K  3.9G   1% /mnt/wslg/doc
C:\             3.8T  300G  3.5T   8% /mnt/c
G:\              15G  6.5G  8.6G  44% /mnt/g
snapfuse         75M   75M     0 100% /snap/core22/1033
snapfuse        128K  128K     0 100% /snap/bare/5
snapfuse         74M   74M     0 100% /snap/core22/864
snapfuse         92M   92M     0 100% /snap/gtk-common-themes/1535
snapfuse         41M   41M     0 100% /snap/snapd/20290
snapfuse         41M   41M     0 100% /snap/snapd/20671
snapfuse        132M  132M     0 100% /snap/ubuntu-desktop-installer/1276
snapfuse        131M  131M     0 100% /snap/ubuntu-desktop-installer/1280
/dev/sdd1       120M   51M   70M  43% /mnt/sdcard
/dev/loop0      3.7G  3.1G  384M  90% /mnt/image_data

Look at /dev/loop0, which is mounted to /mnt/image_data, as you can see, the used space is 3.1G from 3.7G of partition size, so we need at least 4Gb USB flash drive.

Attach USB flash drive

I will detach the microSD card since I have only one available USB port in my laptop, so first I have to unmount it in WSL:

sudo umount /dev/sdd1

Then detach it in Windows:

usbipd detach -b 1-1

So it should disappear from the list of lsusb and ls -al /dev/sd*.

Now insert USB flash drive in one of the physical port of your PC/laptop (Windows) and attach it to WSL (as described here), and check whether it is appeared in WSL similarly as for microSD card.

Format USB flash drive

USB flash drive needs to be properly formatted with the right partition tables and filesystem. The partition table should be 83 Linux, for this we will use fdisk utility (my USB flash drive recognized as /dev/sdd, same as microSD card was):

sudo fdisk /dev/sdd

Do the same steps as for microSD card formatting, except the step with changing the partition type, you don’t have to change it, since by default it will be already 83 Linux.

If for some reason you were not able to delete some partition in fdisk, you can do the following trick: exit from fdisk (type q), format the disk typing sudo mkfs -t ext4 /dev/sdd (without the partition number), it will kill all partitions on the disk and format it to ext4, and after that you should be able to run fdisk again and be able to do anything you need with it.

Check that formatting went well by typing sudo fdisk -l /dev/sdd, you should see something like:

Disk /dev/sdd: 14.44 GiB, 15502147584 bytes, 30277632 sectors
Disk model: Storage Device
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xbd589f0b

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdd1        2048 30277631 30275584 14.4G 83 Linux

We need PARTUUID of just created partition for later use (in /etc/fstab and cmdline.txt), run sudo blkid /dev/sdd1 and write it down somewhere:

/dev/sdd1: UUID="fbb4fa1c-ac4a-47ad-8618-8be797981605" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="bd589f0b-01"

Format just created USB flash drive partition (/dev/sdd1) to ext4 filesystem:

sudo mkfs -t ext4 /dev/sdd1

Mount USB flash drive

Mount USB flash drive to /mnt/usbdrive folder:

sudo mount /dev/sdd1 /mnt/usbdrive

Copy second partition files onto USB flash drive

Now we should be able to copy the files from second partition of the image onto the USB flash drive:

sudo rsync -a --info=progress2 /mnt/image_data/ /mnt/usbdrive/

Be patient, this may take up to 1 hour, depends on your USB flash drive write speed and Raspberry Pi OS image size you’ve chosen. Not days though 🙂 .

Edit /etc/fstab on USB flash drive

Since we changed a bit a boot process and its device list, /etc/fstab needs to be changed as well. Once all the files are copied onto USB flash drive, edit the /etc/fstab file.

sudo nano /mnt/usbdrive/etc/fstab

As the device source (left part, the proc column) you should use PARTUUID=*. For PARTUUID value use the value identified by the blkid command (see above), the first one from the microSD card and the second one for the USB flash drive. So your /etc/fstab should look like:

proc            /proc           proc    defaults          0       0
PARTUUID=f749f5de-01  /boot           vfat    defaults          0       2
PARTUUID=bd589f0b-01  /               ext4    defaults,noatime  0       1

and then press Ctrl+X, Shift+Y and Enter to save the changes to the file.

In earlier versions of the linux distros you could use /dev/mmcblk0p1 and /dev/sda1, so your /etc/fstab will look like:

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       2
/dev/sda1       /               ext4    defaults,noatime  0       1

Edit cmdline.txt on microSD card

The system will start booting from microSD card, boot partition of which is recognized as /dev/mmcblk0p1 device (or PARTUUID=f749f5de-01) in Raspberry Pi, then the system will read the instructions from cmdline.txt file and continue loading the system files from the device indicated in the root parameter.

Since the second image partition files are written onto the USB flash drive (so it won’t be a microSD card anymore), we need to change the root parameter in cmdline.txt on microSD card accordingly.

Unmount USB flash drive, detach it in Windows, insert microSD card in one of the physical PC/laptop port (if not inserted yet), attach it in Windows, mount it to /mnt/sdcard in WSL and change the value of the root parameter to PARTUUID=bd589f0b-01 (in earlier linux distros you could also use /dev/sda1 format if you like, however it is considered less reliable in the latest versions of linux distros), so it will look like (it should still be one line):

console=serial0,115200 console=tty1 root=PARTUUID=bd589f0b-01 rootfstype=ext4 fsck.repair=yes rootwait quiet init=/usr/lib/raspberrypi-sys-mods/firstboot splash plymouth.ignore-serial-consoles

or (for earlier linux distros):

console=serial0,115200 console=tty1 root=/dev/sda1 rootfstype=ext4 fsck.repair=yes rootwait quiet init=/usr/lib/raspberrypi-sys-mods/firstboot splash plymouth.ignore-serial-consoles

and then press Ctrl+X, Shift+Y and Enter to save the changes to the file.

Now you can unmount the SD card:

sudo umount /dev/sdd1

Conclusion

This is basically it. Now you should be able to insert the SD card into the micro SD slot of Raspberry Pi, USB flash drive into the USB port and start your Raspberry Pi.

Don’t forget to connect the display and at least keyboard to your Raspberry Pi on the first start.

Once you set the network settings (and enabled SSH) you should be able to connect to your Raspberry Pi via SSH, make sure that the Raspberry Pi is connected to your network.