Home > Linux, Software management, Ubuntu > 12MB Minimal Image for Raspberry Pi using the Yocto Project

12MB Minimal Image for Raspberry Pi using the Yocto Project

Last year, I wrote instructions and provided a download link about a minimal image for Raspberry Pi based on Raspbian. The compressed image is 84MB, and the good thing about it is that you can just use apt-get to install packages. The problem is that it’s not actually that small as once it is uncompressed the rootfs is still a massive 414 MB.

So today, I’ll explain how to create a smaller (and custom) image using the Yocto Project, a platform that let you build an embedded Linux distribution matching exactly your project’s requirements. Other advantages are that the build is configurable with config files, so it’s easily reproducible with a few command lines, and it might turn out to be useful to learn more about the Yocto Project as many boards and SoC are now making use of the framework, including Freescale i.MX6 (Wandboard, Olinuxino-imx233, Sabrelite, etc…), the Beagleboard, and Minnowboard to name a few.

If you just want the image, you can download the compressed image (12MB), extract it, use dd to copy it to your SD card, and gparted to resize the rootfs. This is an image that’s only useful for (headless) embedded systems, but more likely than not, you’d want to customize it with the instructions below.

I got started with instructions from pimpmypi, but these are a little old, and now everything seems much simpler. I’ve performed the steps below in a PC running Ubuntu 12.04 LTS, and with most dependencies required (e.g. build-essentials, git) already installed.

First you need to get poky and the meta layer for Raspberry Pi:

mkdir yocto
cd yocto
git clone -b dylan git://git.yoctoproject.org/poky.git
cd poky
git clone -b dylan git://git.yoctoproject.org/meta-raspberrypi

dylan is the codename of the latest Yocto Project release (Version 1.4).

Then you can run the following command line to initialize some environment variables and the build directory:

. oe-init-build-env build

Now edit conf/local.conf with vim or nano to optimize the build speed depending on your PC processor (generally number of threads/cores +1), set the machine as Raspberry Pi, and possibly adjust the GPU memory, by updating or adding the corresponding lines:

BB_NUMBER_THREADS = "9"
PARALLEL_MAKE = "-j 9"
MACHINE ?= "raspberrypi"
GPU_MEM = "16"

You may want to check the README if you want to overclock your R-Pi board, change the rootfs type, add VC-1 or/and MPEG-2 licenses, or disable overscan. All those extra options, including GPU_MEM, can be added by editing config.txt directly in the SD card, but doing it before the build makes the steps automatically reproducible.

You also need to add the path to meta-raspberrypi in conf/bblayers file, so that it looks like:

BBLAYERS ?= " \
  /home/jaufranc/edev/rpi/yocto/poky/meta \
  /home/jaufranc/edev/rpi/yocto/poky/meta-yocto \
  /home/jaufranc/edev/rpi/yocto/poky/meta-yocto-bsp \
  /home/jaufranc/edev/rpi/yocto/poky/meta-raspberrypi \
  "

Now we’re ready to build the image. There are two images possible: rpi-basic-image and rpi-hwup-image, both of will provide a minimal image, but rpi-basic-image will add ssh-server-dropbear (for ssh server support) and splash (for the splash screen). Let’s go with rpi-basic-image:

bitbake rpi-basic-image

It took just over one hour in my computer, but it may take less or much more time depending on your computer and/or Internet connection.

Once the build is complete you should see a file called tmp/deploy/images/rpi-basic-image-raspberrypi.rpi-sdimg, which is a symlink to the binary image you want to dump on your SD card. The file size is 80MB, but it can be compressed to 12MB if you want to distribute over the Internet:

7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on rpi-basic-image-raspberrypi-20130702123605.rootfs.rpi-sdimg.7z rpi-basic-image-raspberrypi-20130702123605.rootfs.rpi-sdimg

Now insert an SD card in your Linux computer, and check the device name:

lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sr0     11:0    1  1024M  0 rom  
sda      8:0    0 931.5G  0 disk 
├─sda1   8:1    0 915.5G  0 part /
├─sda2   8:2    0     1K  0 part 
└─sda5   8:5    0    16G  0 part [SWAP]
sdc      8:32   0 931.5G  0 disk 
└─sdc1   8:33   0 931.5G  0 part /media/SEAGATE EXTENSION
sdb      8:16   1 241.3M  0 disk 
└─sdb1   8:17   1 240.3M  0 part

Since I have a USB hard drive attached to my computer I do this all the time, because sometimes the SD card is /dev/sdb, and other times /dev/sdc, and if I use the wrong one, all my data will be lost.

Let’s copy the image with dd or dd.sh:

sudo dd.sh if=tmp/deploy/images/rpi-basic-image-raspberrypi.rpi-sdimg of=/dev/sdb bs=1M

Now remove the SD card, and reinsert it. The ext-3 partition in the image is only 55MB, so to make full use of your SD card storage capacity, you need to resize the partition with the command line, or easier, with gparted. Resizing from the Raspberry Pi won’t work with this image, as resize2fs utility is not available.

We’re now ready to try it out. Let’s insert the SD card into the Raspberry Pi, and connect the power. You can access the console via HDMI, the UART port, or if you’ve connected an Ethernet cable via ssh.

Near the end of the boot, or when you access the board with SSH, you should see:

Poky 9.0 (Yocto Project 1.4 Reference Distro) 1.4.1 raspberrypi ttyAMA0

raspberrypi login:

Login with as root without password.

Let’s check some details about the kernel:

uname -a
Linux raspberrypi 3.6.11 #1 PREEMPT Tue Jul 2 18:05:23 ICT 2013 armv6l GNU/Linux

busybox:

BusyBox v1.20.2 (2013-07-02 18:09:51 ICT) multi-call binary.
...
Currently defined functions:                                                    
        [, [[, ar, ash, awk, basename, bunzip2, bzcat, cat, chattr, chgrp,      
        chmod, chown, chroot, chvt, clear, cmp, cp, cpio, cut, date, dc, dd,    
        deallocvt, df, diff, dirname, dmesg, dnsdomainname, du, dumpkmap,       
        dumpleases, echo, egrep, env, expr, false, fbset, fdisk, fgrep, find,   
        flock, free, fsck, fsck.minix, fuser, grep, groups, gunzip, gzip, halt, 
        head, hexdump, hostname, hwclock, id, ifconfig, ifdown, ifup, insmod,   
        ip, kill, killall, klogd, less, ln, loadfont, loadkmap, logger,         
        logname, logread, losetup, ls, lsmod, md5sum, microcom, mkdir, mkfifo,  
        mkfs.minix, mknod, mkswap, mktemp, modprobe, more, mount, mv, nc,       
        netstat, nohup, nslookup, od, openvt, patch, pidof, ping, ping6,        
        pivot_root, poweroff, printf, ps, pwd, rdate, readlink, realpath,       
        reboot, renice, reset, rfkill, rm, rmdir, rmmod, route, run-parts, sed, 
        seq, setconsole, sh, sleep, sort, start-stop-daemon, stat, strings,     
        stty, swapoff, swapon, switch_root, sync, sysctl, syslogd, tail, tar,   
        tee, telnet, test, tftp, time, top, touch, tr, traceroute, true, tty,   
        udhcpc, udhcpd, umount, uname, uniq, unzip, uptime, users, usleep, vi,  
        watch, wc, wget, which, who, whoami, xargs, yes, zcat

available space:

 df -h                                                       
Filesystem                Size      Used Available Use% Mounted on              
/dev/root               212.5M     42.8M    158.9M  21% /                       
devtmpfs                108.0M      4.0K    108.0M   0% /dev                    
tmpfs                   116.0M    188.0K    115.8M   0% /var/volatile           
tmpfs                   116.0M         0    116.0M   0% /dev/shm                
tmpfs                   116.0M         0    116.0M   0% /media/ram              
/dev/mmcblk0p1           19.9M      8.2M     11.7M  41% /media/mmcblk0p1

and available memory:

free -h                                                     
             total         used         free       shared      buffers          
Mem:        237628        19872       217756            0         1456          
-/+ buffers:              18416       219212                                    
Swap:            0            0            0

We’ve got a recent kernel, only 42.8MB of the root file system is used, and 232MB RAM available on a Raspberry Pi Model B with 256 MB RAM.

Let’s check the kernel config on the board:

zcat /proc/config.gz

You can download the kernel config for details.

If you want to save even more memory, or add features, you can change the kernel configuration with:

bitbake virtual/kernel -c menuconfig

and build the kernel with:

bitbake virtual/kernel

Busybox can also be tuned with the commands:

bitbake busybox -c menuconfig
bitbake busybox

The images recipes are located in poky/meta-raspberrypi/recipes-core/images, and you you could copy rpi-basic-image.bb to rpi-myappliance-image.bb, and edit the later to add the recipes/packages you need.

But this may be difficult, if you don’t know exactly what you need, and luckily the Yocto Project also have a graphical interface called “hob” that you can just start from the build directory. Let’s start with rpi-hwup-image for the Raspberry Pi by selecting the corresponding machine and base image:

Raspberry_Pi-Yocto_Hob

You can then either select “Edit Image” to add recipes and/or package groups, or simply click “Build Image” to start the build. Let’s just do that. The build is now much faster since most packages have already been built when we ran “bitbake rpi-basic-image”.

R-Pi_Yocto_Hob_Task

After a few minutes, you should the “Your image is ready” window below with easy access to the binaries and log files:

Yocto_Hob_Raspberry_Pi_Build_Complete

If instead of clicking “Build Image”, you clicked on “Edit image” you’d have access to the list of included recipes, all recipes and package groups. In the screenshot below I searched for recipes with “bcm” and “rpi” names. bcm2835 is used for GPIO support, so you may want to include it in the build.

Yocto_Rpi_Edit_Recipes

Once you’ve selected the required packages, click on “Build Packages”, and after a while, Step 2 window will appear and let you click on “Build Image”. Your custom SD card image will be available in tmp/deploy/images/ directory with the name hob-image-raspberrypi.rpi-sdimg.

That’s just a small overview of what’s possible with the Yocto Project for the Raspberry Pi board. For further details you may want to check the project’s documentation, and you may also read Hob’s manual for specific details about Yocto’s GUI.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter

  1. July 5th, 2013 at 16:59 | #1

    Incredible, congratulations. This summer if I have enough time I try to prepare my own little distro with your instructions.

  2. Vinicius Tinti
    July 7th, 2013 at 18:59 | #2

    Hi,

    Should not it be?

    mkdir yocto
    cd yocto
    git clone -b dylan git://git.yoctoproject.org/poky.git
    cd poky
    git clone -b dylan git://git.yoctoproject.org/meta-raspberrypi

    Regards

  3. July 8th, 2013 at 09:43 | #3

    @Vinicius Tinti
    Correct! Thanks!

  4. Rich
    July 17th, 2013 at 23:06 | #4

    Thanks for pointing me in this direction. I already have a nice custom build for my Pi thanks to this. I do have some issue though – on first boot ethernet is working fine, but on subsequent boots it doesnt. I have to goto a prompt (using a monitor etc) and manually do “ifdown eth0″ then “ifup eth0″ and it is working again.

    Have you seen this happen, and if so how did you fix it?

  5. July 18th, 2013 at 09:07 | #5

    @Rich
    I haven’t experienced this issue.

    You can use dmesg between the boots to find out the issue, or like I do, use the serial console to check the boot log.

  6. July 19th, 2013 at 00:09 | #6

    i tried your commands but bitbake is failing here:

    Pseudo is not present but is required, building this first before the main build
    ERROR: Unable to parse /home/edsiper/coding/yocto/poky/meta-raspberry/conf/layer.conf: [Errno 2] No such file or directory: ‘/home/edsiper/coding/yocto/poky/meta-raspberry/conf/layer.conf’

    i cannot find the missing dependency package…

  7. July 19th, 2013 at 09:44 | #7

    @Eduardo
    If you don’t have “/home/edsiper/coding/yocto/poky/meta-raspberry/conf/layer.conf”, it’s probably because “git clone -b dylan git://git.yoctoproject.org/meta-raspberrypi” command line, or was done in the wrong directory.

  8. danial smith
    September 23rd, 2013 at 14:24 | #8

    please teal me how can i install gui interface (Desktop) and install other application on it ???

  9. kazaar
    November 9th, 2013 at 22:07 | #9

    I tried to follow the steps to the letter, tried under Fedora and Ubuntu distributions.
    Every time bitbake stops at this point:

    0: linux-raspberrypi-3.6.11+git31a951046155b27361127d9cf85a1f58719fe9b3-r6 do_fetch (pid 1705)
    1: linux-libc-headers-raspberrypi-3.2.27-r0 do_fetch (pid 1690)
    2: bcm2835-bootfiles-20130107-r3 do_fetch (pid 1706)

    It seems to be unable to get those files and I don’t know how to get them in other way. Tried to google for the problem without luck.

    Any Ideas?

  10. November 9th, 2013 at 22:35 | #10

    @kazaar
    There should be some logs files, but I can’t quite remember the location.
    The build will take time. If you’re computer is not a fast machine, it may take several hours, so it’s also possible you may just have to wait a bit longer.

  11. Luke
    November 12th, 2013 at 11:17 | #11

    Thank you very much for this. I have reconstructed your described build process and flashed the resulting image. After dding it to the SD, inserting SD, HDMI and uUSB power, the green ACT LED flashes up once, red LED lights up permanently, nothing is visible on the HDMI Monitor. Plugging in USB keyboard, caps lock LED does not react. I tried the same with your prebuilt image with the same result. Using a rasbian as reference from the same SD works well. Any hints would be most appreciated.

  12. Luke
    November 12th, 2013 at 11:53 | #12

    @kazaar
    Just wait until bitbake finished cloning those git repositories. Especially the kernel might take a while, maybe hours. A workaround would be to modify the kernel recipe changing the original SRC_URI to a mirror.

    Unless it encounters an error and notifies you about that, bitbake won’t stop.

  13. November 12th, 2013 at 11:53 | #13

    @Luke
    You could try with another SD card, or preferably use an USB to TTL debug board to access the serial console and see if there’s any output. If there’s no output at all that means the system does not boot (even to the bootloader), so it’s probably because it can’t read the SD card

  14. Luke
    November 12th, 2013 at 19:50 | #14

    @cnxsoft
    Thanks, same symptoms writing your image to an old 2GB SD. Also, with the other SDHC card, rasbian works, yocto images don’t. So I guess I cannot blame the SD. Looks like I will have to recover my old FTDI cable.
    Do you get any output on your HDMI display and usb function by default in the posted image?

  15. November 12th, 2013 at 19:58 | #15

    @Luke
    Yes, HDMI worked, and I used a USB keyboard to login.

  16. Luke
    November 12th, 2013 at 21:13 | #16

    @cnxsoft
    Ok. So I hooked up the FTDI cable.
    16 GB SanDisk Class 100 SDHC

    2013-09-25-wheezy-raspbian.img will give a bunch regular linux boot kernel messages in the terminal. I can connect usb hdmi and everything works instantly.

    rpi-basic-image-raspberrypi-20130702123605.rootfs.rpi-sdimg will give this �<� in terminal and no hdmi or usb interaction.

    Might this be related to different hardware revisions ? A sticker on the back of my RPI says E1613RS2V13B1.0
    Do you have a similar identifier?

  17. November 12th, 2013 at 21:26 | #17

    @Luke
    My raspberry Pi is in a box with lots of connected wires, and I’d have to disconnect all that to look at the back of the board, so I’d rather avoid that right now. But I have one of the earlier versions with 256MB RAM. It could be the reason for the failure. Maybe some of the binary files in the FAT partition need to be changed. You could try to copy the bin files from your working SD card to the one with the Yocto image.

  18. November 12th, 2013 at 21:34 | #18

    @Luke
    Maybe a solution. I remember newer boards have different SDRAM chips that requires an upgraded firmware.
    See http://www.raspberrypi.org/phpBB3/viewtopic.php?f=28&t=52842

    That’s basically the same solution as copying binaries from working SD to non working SD, but it’s neater.

  19. Luke
    November 12th, 2013 at 22:42 | #19

    That’s great! Something similar here http://blog.rogiervandenberg.nl/2013/05/how-to-fix-boot-problems-with-hynix.html

    In fact I do have a newer version with hynix memory. Will update once tested

  20. Luke
    November 12th, 2013 at 22:50 | #20

    @cnxsoft
    Win :)

    So for everybody who encounters the no boot problem:

    Using

    bootcode.bin
    cmdline.txt
    config.txt
    *.elf

    from

    http://downloads.raspberrypi.org/images/raspbian/2013-02-09-wheezy-raspbian/2013-02-09-wheezy-raspbian.zip

    fixes the yocto 1.4 images on my newer 512MB hynix memory raspberry pi.

  21. November 13th, 2013 at 10:31 | #21

    @Luke
    Great!

    By the way, Yocto 1.5 (Dora) has been released last month, so it’s possible replacing “dylan” by “dora” in the instructions above fixes the issue too.

    For example, replacing:
    git clone -b dylan git://git.yoctoproject.org/poky.git
    by
    git clone -b dora git://git.yoctoproject.org/poky.git

  22. phil
    November 16th, 2013 at 08:31 | #22

    @cnxsoft
    Hi,

    I tried with dora for both poky and meta-raspberrypi and I’ve this error when I bitbake basic image:
    ERROR: No recipes available for:
    /home/plegal/svn/rpi/poky/meta-raspberrypi/recipes-graphics/mesa/mesa_9.2.2.bbappend
    ERROR: Command execution failed: Exited with 1

    So I tried dora for poky and dylan for meta-raspberrypi and I still have the no boot problem.

    One solution is to replace the bootcode.bin, start.elf and start_cd.elf from the deploy img with the same files in the last noobs_v1.3.2 image.

    After that it boots.

  23. phil
    November 20th, 2013 at 03:22 | #23

    @phil
    OK, it’s compile and boot fine if we change mesa_9.2.2 to mesa_9.1.6 and if we change the preferred kernel to 3.8.%

  24. January 25th, 2014 at 02:12 | #24

    Hello, I created the minimal rpi-hwup-image image and it boots great. Problem is in eclipse for my c project I am using tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabi-raspbian I have used the normal or hard floating point.
    The hard floating point creates an executable that when I run on this build it just says “not found” like it doesn’t even understand it. So I changed it to soft floating point and I get “segmentation fault”. My only linker entry is for pthread. What compiler works with this build? I would really appreciate your help. Thanks.

  25. January 25th, 2014 at 09:46 | #25

    @Paul
    You should use the compiler built by Yocto.

  26. Filip
    February 7th, 2014 at 04:16 | #26

    Is it possible to configure yocto to be build for raspberrypi with hard-float support set?

  27. February 7th, 2014 at 10:02 | #27

    @Filip
    Is the image armel? There must be a way to change compiler flags (CFLAGS) somewhere, maybe conf/local.conf, or meta-raspberrypi.

  28. Sheeru
    March 9th, 2014 at 00:31 | #28

    I am currently trying to add new packages to rpi-basic-image and build my custom distribution. I started with hello world package. I created a new meta layer and I wanted to add additional packages to the image in that layer.

    I tried testing with the hello world auto tooled package. This hello
    world is the hello world autotooled package downloaded from
    ftp://ftp.gnu.org/gnu/hello/hello-2.7.tar.gz. When trying
    to execute that bb, am getting the error as follows,

    | make: *** No rule to make target `install’. Stop.
    | ERROR: oe_runmake failed

    My bb file is as follows,

    DESCRIPTION = “Dummy”
    SECTION = “package”
    LICENSE = “CLOSED”
    PR = “r0″
    SRC_URI = “file://hello/”
    inherit autotools gettext

    After executing this bb file, i took a look at the logs of configure.
    It says nothing to configure.

    Please help me with what’s wrong with this process am following?

  29. March 9th, 2014 at 09:30 | #29

    @Sheeru
    Sorry, I haven’t done this type of modif. You’d better ask on Yocto mailing list.

  30. Aananth C N
    September 4th, 2014 at 01:18 | #30

    The image generated out of “bitbake rpi-basic-image” works well on Raspberry Pi Rev B model. But it does not work on Rev B+ model hardware. Any one verified this?

  31. September 4th, 2014 at 13:47 | #31
  32. Aananth C N
    September 5th, 2014 at 01:44 | #32

    @cnxsoft
    Thank you. It worked after updating the firmware as per the link above.

  33. Vincent Wang
    October 27th, 2014 at 20:03 | #33

    Hi @cnxsoft , thank you very much for the share. I’m using “bitbake busybox -c menuconfig” and customized the utilities working good. But when I trying to add telnetd utility via busybox, I find that I need to add some configuration in rootfs, for telnetd to auto launch and configure itself. How can I find the way to add my own files to rootfs and let bitbake compile it together with the whole rootfs?

  1. July 6th, 2013 at 01:03 | #1
  2. July 19th, 2013 at 16:15 | #2
  3. July 21st, 2013 at 11:30 | #3
  4. December 9th, 2013 at 00:37 | #4
  5. December 18th, 2013 at 19:38 | #5