Headless Raspberry Pi configuration

Settings up a Raspberry Pi it’s easy when you have an HDMI display, a USB keyboard and mouse in oder to access the terminal or you favourite Desktop, but can be quite a challenge when you don’t have any of these or at least no keyboard.

Everything in this blog post should be done from you host computer, with you microSD card connected and mounted, assuming the microSD is mounted at /Volumes/boot.

cd /Volumes/boot
Raspberry Pi 4 with Hyperpixel 4.0 display

Enable SSH over LAN / WiFi

The SSH server is not enable by default as a user it’s expected that you access your Raspberry using a KVM. Not a Linux Kernel but a Keyboard, (VGA) Display and Mouse. This can be easily done by creating an empty file named ssh.

touch ssh

Preconfigured a WiFi network

If you are going to connect to Raspberry to your network using an Ethernet cable, you can skip this part. But if a WiFi network (even your mobile phone as a hotspot) it’s you only option, you can set your default WiFi network config in a file called wpa_supplicant.conf

sudo vi wpa_supplicant.conf
    ssid="<< your WiFi's SSID >>"
    psk="<< your WiFi's password >>"

Take into consideration that this configuration uses your password in plain-text! If you want to encrypt your password in this configuration file do the following:

wpa_passphrase "<< your WiFi's SSID >>" "<< your WiFi's password >>"

On a Linux distribution wpa_passphrase is installed, but on macOS or Windows not. the following Ruby script will use OpenSSL in order to create the content of the configuration file.

vi /tmp/raspi_wifi.rb
require 'openssl'
ssid = '<< your WiFi SSID >>'
psk  = 'ID >>" "<< your WiFi password >>'
puts 'country=AR'
puts 'ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev'
puts 'update_config=1'
puts ''
puts 'network={'
puts '  ssid="' + ssid + '"'
puts '  psk=' + OpenSSL::PKCS5.pbkdf2_hmac_sha1(psk, ssid, 4096, 32).unpack("H*").first
puts '  key_mgmt=WPA-PSK'
puts '}'

Then run the script and copy the output to /Volumes/boot/etc/wpa_supplicant/wpa_supplicant.conf

ruby /tmp/raspi_wifi.rb > /Volumes/boot/wpa_supplicant.conf

Accessing your Pi using SSH

Now when your Raspberry completes its boot process, you will be able to access your device using SSH even without knowing its IP address.

Raspberry exposes a host in your local domain, so the following command with let you know it IP address.

ping raspberrypi.local

The default Raspberry user and password are pi and raspberry, so the following command will establish a SSH connection

ssh pi@raspberry.local 
ESP32 File System

ESP32: Using the Internal Flash File System

The ESP32 contains a lightweight filesystem specially design for microcontrollers called Serial Peripheral Interface Flash File System. This File System, also known as SPIFFS for its initials, is implemented on top of a Flash chip connected directly to the SPI bus.

SPIFFS supports basic operations on files, like opening, close, read and write, and a very rudimentary implementation of directories. You will find that several project uses this File System in order to serve pages (and files) in a Web Server.


First of all we need to install a few dependencies. The most important is the File System uploader tool, which can be used from the Arduino IDE, Visual Studio Code, or command line. The steps for performing this installation can be found at project repository on GitHub.

If you are using Visual Studio Code, as I do, install the following extension: ESP8266FS. From the command line:

code --install-extension vscode-esp8266fs

Do not forget to install Arduino-ESP32 Core https://github.com/espressif/arduino-esp32#installation-instructions

Project configuration

When using the Arduino IDE, just selecting the board in the Board Manager will do the job. But when using Visual Studio Code, we have to set some values on .vscode/arduino.json.

    "sketch": "main.ino",
    "board": "esp32:esp32:featheresp32",
    "configuration": "FlashFreq=80m,UploadSpeed=921600,DebugLevel=none,PartitionScheme=default,FlashSize=4MB,FlashMode=keep",
    "port": "/dev/tty.SLAB_USBtoUART",
    "output": "output"

With this configuration 1M of Flash will be used for SPIFFS and the rest (3M out of 4M) for your code.

Testing the plugin configuration

In Arduino IDE using the Data Uploader is straightforward. But on Visual Studio Code the plugin should be configured carefully in order to work. The following is my Visual Studio Code configuration (settings.json) which is quite verbose for testing purposes.

    "esp8266fs.espota.debug": true,
    "esp8266fs.esptool.executable": "/Users/kimi/Documents/Arduino/hardware/espressif/esp32/tools/esptool.py",
    "esp8266fs.esptool.verbosity": "vvv",
    "esp8266fs.logLevel": "debug",
    "esp8266fs.mkspiffs.executable": "/Users/kimi/Documents/Arduino/hardware/espressif/esp32/tools/mkspiffs/mkspiffs",
    "esp8266fs.preferencesPath": "/Users/kimi/Library/Arduino15",
    "esp8266fs.arduinoUserPath": "/Users/kimi/Documents/Arduino",
    "esp8266fs.spiffsImage": "./spiffs.image",
    "esptool.py.spi_connection": "SPI",
    "esptool.py.compress": "true",
    "esptool.py.verify": "false",
ESP32 has not been installed correctly

Testing the Data Upload can be done by List SPIFFS command. cmd + shift P and select ESP8266FS: List SPIFFS. If you get an error saying

ESP32 has not been installed correctly – see https://github.com/espressif/arduino-esp32

Take into consideration that the Path of the ESP32 Tool is generated by splitting the Board key on .vscode/arduino.json in order to get three parameters: Package, Architecture and Board (ref: https://github.com/kash4kev/vscode-esp8266fs/…/esp8266fs.js#L467).

As my board is an Adafruit HUZZAH32, and my board config is

   "board": "esp32:esp32:featheresp32",

the three key parameters will be:

   "package": "esp32",
   "architecture": "esp32",
   "board": "featheresp32",

This parameters will be used by the ESP8266FS plugin to create the path where ESP tools are installed. In my setup it will result in /Users/kimi/Documents/Arduino/hardware/esp32/esp32. But, based on the ESP32 Arduino core tutorial, my hardware definition is installed on /Users/kimi/Documents/Arduino/hardware/espressif/esp32.

My workaround to this issue was to create a symbolic link so the esp32 directory was points to espressif.

ln -s espressif esp32
Couldn’t find match for argument

Another common error is Couldn’t find match for argument when running mkspiffs, which is a tool found in the ESP32 Arduino Core SDK that handles the creation, upload and download (among other responsibilities) of images.

This issue is already reported on GitHub at https://github.com/kash4kev/vscode-esp8266fs/issues/15. The workaround as explain there, is to disable the configuration esp8266fs.mkspiffs.allFiles.

Packing information into an Image

In your project directory, next to your main Arduino file, create a directory called data. All files stored in that folder will be transfer to your ESP32 microcontroller when uploading the File System.

All our data files are not transferred one by one to the ESP32, but inside an Image. In order to create that image we should pack those files using mkspiffs. The ESP8266FS extension has a command for doing that, but be can also use the command line tool.

The benefits of using the command line tool are clear, the operation can be automated inside a script.

/<Path To Arduino>/hardware/espressif/esp32/tools/mkspiffs/mkspiffs --create /<Your Arduino Project Directory>/data --size 0x30000 --page 256 --block 4096 /<Your Arduino Project Directory>/spiffs.image

Uploading files

Remember that uploading files from your Computer will replace the files present in your ESP32.

You will also find a handy command in the Visual Studio Code extension for uploading your currently created image. But if you want to do that using the command line, the following execution will do the trick.

/<Path To Arduino>/hardware/espressif/esp32/tools/esptool/esptool -vvv -ca 0x3D0000 -cd  -cp /dev/tty.SLAB_USBtoUART -cb 921600 -cf /<Your Arduino Project Directory>/spiffs.image

Where /dev/tty.SLAB_USBtoUART is the USB Serial port where I have my ESP32 connected. The result of running this command may look like

--- Uploading SPIFFS file with esptool.py ---
Python Executable: "python"
SPIFFS Uploading Image... (/Users/kimi/Works/eaceto.dev/embedded/ESP32/P1/spiffs.image)
  [SPIFFS] Python   : python
  [SPIFFS] EspTool  : /Users/kimi/Documents/Arduino/hardware/espressif/esp32/tools/esptool.py
  [SPIFFS] address  : 0x290000
  [SPIFFS] port     : /dev/tty.SLAB_USBtoUART
  [SPIFFS] speed    : 921600
  [SPIFFS] before   : default_reset
  [SPIFFS] after    : hard_reset
  [SPIFFS] flashMode: keep
  [SPIFFS] flashFreq: 80m
  [SPIFFS] flashSize: 4MB
Running: python /Users/kimi/Documents/Arduino/hardware/espressif/esp32/tools/esptool.py --chip esp32 --baud 921600 --port /dev/tty.SLAB_USBtoUART --before default_reset --after hard_reset write_flash --flash_mode keep --flash_freq 80m --flash_size 4MB 0x290000 /Users/kimi/Works/eaceto.dev/embedded/ESP32/P1/spiffs.image
esptool.py v2.8
Serial port /dev/tty.SLAB_USBtoUART
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:0c:94:78
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Configuring flash size...
Compressed 196608 bytes to 537...
Writing at 0x00290000... (100 %)
Wrote 196608 bytes (537 compressed) at 0x00290000 in 0.0 seconds (effective 136297.5 kbit/s)...
Hash of data verified.
Hard resetting via RTS pin...
ESP8266 SPIFFS interface finished.

Verifying what it’s inside an image

If you want to check which files are included in an image file, you can list them by running

<Path To Arduino>/hardware/espressif/esp32/tools/mkspiffs/mkspiffs --list --page 256 --block 4096 <Path to>/spiffs.image

Downloading an image form the ESP32 to your Computer

May be one of the most important steps when writing an image to the ESP32 is verifying that it was correctly done. For doing this you have to find how many bytes where written the uploading the image to the ESP32. This information can be found on the output of the write_flash operation. And as important as how many it is, where. This information it is also present in the same debug output.

In my previous example this two values where 196608 bytes and starting address 0x290000. So the command to execute in order to read that segment of Flash is:

<Path To Arduino>/hardware/espressif/esp32/tools/esptool.py --chip esp32 --baud 921600 --port /dev/tty.SLAB_USBtoUART read_flash  0x290000 196608 downloaded.image


iFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:0c:94:78
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
196608 (100 %)
196608 (100 %)
Read 196608 bytes at 0x290000 in 2.5 seconds (641.6 kbit/s)...
Hard resetting via RTS pin...

Using the command explained in Verifying what’s inside the image we can see which files are inside the image

<Path To Arduino>/hardware/esp32/esp32/tools/mkspiffs/mkspiffs --list --page 256 --block 4096 downloaded.image


159 /config_test.json

Next steps…

In the following post I will show how to read a JSON file and obtain a configuration parameter that will be use to configure the WiFi network to which our ESP32 will be connected.

Stay tuned!


BeagleBone Black and Linux Kernel 3.8 with Android support

Building Kernel 3.8 (with Device Tree)

cd ~/
git clone git://github.com/RobertCNelson/linux-dev.git
cd linux-dev/
git checkout origin/am33x-v3.8 -b tmp

If ./build_kernel.sh fails with ‘undefined references’ to some functions in files like ‘menubox.c’ try running: sudo apt-get install libncurses5 libncurses5-dev libelf-dev libncurses5 libncursesw5-dev and then retry with ./build_kernel.sh.

Setting up Kernel 3.8.x for Android

Once in the Kernel Configuration Utility (kConfig) scroll down, and enter, ‘Device Drivers’.

Beaglebone Black - Kernel Config for AndroidMake sure the ‘Staging drivers’ are enabled, or enable them (an asterisk will appear between brackets)

Beaglebone Black - Kernel Config for Android

Then, enter ‘Staging drivers’ -> ‘Android’. Enable all Android drivers. I recommend you to include them into the kernel, and not build them as module.

Beaglebone Black - Kernel Config for Android

Exit ‘kConfig’ and the Kernel will begin building.

Beaglebone Black - Kernel Config for Android

When it is done you will see something like

Beaglebone Black - Kernel Config for Android

Next: U-Boot for BeagleBone Black

Android 4.1.2 Image for Beagleboard XM

This Image can be loaded into an SD Card (4GBytes min). It can run entirely from the SD Card, or the Android OS can run from a USB Flash, and U-Boot, X-Loader and the Kernel on the SD Card.

Configure U-Boot

For running entirely from the SD Card

Setup U-BOOT for Android and Kernel on SD Card


For running Android OS from a USB Drive

Setup U-BOOT for Android on USB and Kernel on SD Card


copy rootfs.tar.bz2 to USB Drive and untar (all these commands should be executed as Administrator)

Create SDCard

Note: Script not yet optimized for configuration with USB Drive (it is not necessary to copy rootfs to SD Card when booting from USB)
sudo ./mkmmc.sh /dev/sdb MLO u-boot uImage boot.scr rootfs.tar.bz2

Files: Android Image for BeagleBoard xM

Setting up ADB on Beagleboard

On your Beagleboard

Enable USB Debugging on The Beagleboard

  1. Go to Settings’ app
  2. Developers Options
  3. Check “USB Debugging”
  4. Restart your Beagleboard


On your Host Machine (Ubuntu)

Allow device in udev

vim /etc/udev/rules.d/51-android.rules

SUBSYSTEM=="usb", SYSFS{idVendor}=="18d1", MODE="0666"
SUBSYSTEM=="usb", SYSFS{idVendor}=="0451", MODE="0666"

Save and change permissions

chmod a+r /etc/udev/rules.d/51-android.rules

Turn off any existent ADB

sudo killall adb

Restart udev

sudo service udev restart

Start ADB and look for devices

cd ~/adt-bundle-linux-x86_64/sdk/platform-tools
sudo ./adb/ start-server
sudo ./adb/ devices
You should see something like:

kimi@kimi-VAIO:~/adt-bundle-linux-x86_64/sdk/platform-tools$ ./adb devices
List of devices attached
20100720 device

Building Android Jelly Bean (4.1.2) for Beagleboard xM

Jelly Bean on Beagleboard xM


  • Ubuntu 12.04 LTS – AMD64
    • A 64-bit OS is needed in order to build Android 4.x from source code
  • Dual- or Quad-core  (recommended) CPU
  • At least 4GB of RAM
  • 45GB of free disk space
  • Internet connection

Installing utils and libs

From a Terminal console execute
sudo aptitude install ia32-libs
sudo apt-get install git-core gnupg flex bison gperf build-essential
zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev
libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386
libgl1-mesa-dev g++-multilib mingw32 openjdk-6-jdk tofrodos
python-markdown libxml2-utils xsltproc zlib1g-dev:i386

and then
sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1 /usr/lib/i386-linux-gnu/libGL.so

Installing Oracle Java JDK

  1. Download Oracle Java6 JDK from here (file: jdk-6u34-linux-x86.bin) to ~/Downloads
  2. In a Terminal cnosole execute
    1. cd ~/Downloads
    2. cp jdk-6u43-linux-x64.bin ~/
    3. cd ~/
    4. chmod +x  jdk-6u43-linux-x64.bin
    5. ./jdk-6u43-linux-x64.bin
    6. sudo mv jdk1.6.0_43/ /usr/lib/jvm/
  3. Add Oracle Java6 JDK to Ubuntu JVM list
    1. sudo update-alternatives –install /usr/bin/javac javac /usr/lib/jvm/jdk1.6.0_43/bin/javac 1
    2. sudo update-alternatives –install /usr/bin/java java /usr/lib/jvm/jdk1.6.0_43/bin/java 1
    3. sudo update-alternatives –install /usr/bin/javaws javaws /usr/lib/jvm/jdk1.6.0_43/bin/javaws 1
  4. Select Oracle Java6 JDK as default JVM
    1. sudo update-alternatives –config javac
    2. sudo update-alternatives –config java
    3. sudo update-alternatives –config javaws

In this three last commands, select Oracle Java6 JDK as default, like in the example below

kimi@X-Server:~$ sudo update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

Selection Path Priority Status
0 /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java 1061 auto mode
1 /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java 1061 manual mode
* 2 /usr/lib/jvm/jdk1.6.0_34/bin/java 1 manual mode
Press enter to keep the current choice[*], or type selection number: 2

Installing REPO

Repo is a tool created by Google in order to admin git repositories easyly.
In a Terminal console execute

  1. mkdir ~/bin
  2. export PATH=~/bin:$PATH
  3. curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
  4. chmod a+x ~/bin/repo

Initialize the repository

  1. mkdir ~/rowboat-android
  2. cd ~/rowboat-android
  3. repo init -u git://gitorious.org/rowboat/manifest.git -m rowboat-jb-am37x.xml                         (JB for Beagleboard)
  4. repo sync

If a warning telling you that there is a new REPO version appears. Stop the sync process and update

  1.  cp ~/rowboat-android/.repo/repo/repo  ~/bin/repo
  2. chmod a+x ~/bin/repo
  3. repo sync

Once the repo is successfully synced, you will see a message like this:

* [new branch]      rowboat-froyo -> rowboat/rowboat-froyo
* [new branch]      rowboat-gingerbread -> rowboat/rowboat-gingerbread
* [new branch]      rowboat-ics -> rowboat/rowboat-ics
* [new branch]      rowboat-jb -> rowboat/rowboat-jb
* [new branch]      ti-dsp     -> rowboat/ti-dsp
Fetching projects: 100% (261/261), done.
Checking out files: 100% (8843/8843), done.out files:  10% (949/8843)
Checking out files: 100% (24601/24601), done.ut files:  50% (12308/24601)
Checking out files: 100% (18021/18021), done.ut files:   3% (616/18021)
Checking out files: 100% (35638/35638), done.ut files:   1% (663/35638)
Checking out files: 100% (2088/2088), done. out files:   6% (134/2088)
Checking out files: 100% (974/974), done.ng out files:  34% (336/974)
Checking out files: 100% (667/667), done.ng out files:  18% (123/667)
Checking out files: 100% (2412/2412), done. out files:   4% (106/2412)
Checking out files: 100% (26958/26958), done.ut files:  24% (6516/26958)
Checking out files: 100% (81/81), done.
Checking out files: 100% (441/441), done.ng out files:  43% (194/441)
Checking out files: 100% (6505/6505), done. out files:   1% (108/6505)
Syncing work tree: 100% (261/261), done.


Cross compiling Jelly Bean for Beagleboard

Now we are going to modify the PATH variable in order to include the binary directory of the GCC compiler. The following command should be executed every time you open a new Terminal console and want to compile the code. Unless, you include the new PATH into your ‘.bashrc’ or ‘.bash_profile’ file.
export PATH=~/rowboat-android/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:$PATH


X-loader is a small first stage boot loader derived from the u-boot base code to be loaded into the internal static ram by the OMAP ROM code. Because the internal static ram is very small (64k-32k), x-loader is stripped down to the essentials and is used to initialize memory and enough of the peripheral devices to access and load the second stage loader (U-boot) into main memory.
In order to build X-loader we will follow these steps
cd ~/rowboat-android/x-loader/
make CROSS_COMPILE=arm-eabi- distclean
make CROSS_COMPILE=arm-eabi- omap3beagle_config
make CROSS_COMPILE=arm-eabi- -j4

the parameter ‘-j4’ will tell the make to use up to 4 threads to build the code. If you have a dual-core/two-threads CPU, use ‘-j2’. Omitting this parameter will also compile the code, but using just a single thread (which for x-loader or u-boot is not a big problem, but the Android source code can take many hours).
The result of this process is a file named ‘x-load.bin’ on the current directory. This file should be signed with a tool called ‘signGP’ before x-loader gets into the MMC card.

Downloading Rowboat-tools for Jelly Bean

cd ~
curl http://rowboat.googlecode.com/files/RowboatTools.tar.gz > RowboatTools.tar.gz
tar -zxvf RowboatTools.tar.gz

Signing x-load.bin

cp ~/RowboatTools/signGP/signGP ~/rowboat-android/x-loader/signGP
cd ~/rowboat-android/x-loader
./signGP x-load.bin
cp x-load.bin.ift MLO

Now we have a ‘MLO’ file which is a signed version of the binary x-loader, and this file can be used in the board.


Uboot is a universal bootloader program that developed for the loading and starting of embedded Linux systems. Uboot essentially can load a (linux) kernel from one of several locations, and start it with corresponding arguments.

cd ~/rowboat-android/u-boot/
make CROSS_COMPILE=arm-eabi- distclean
make CROSS_COMPILE=arm-eabi- omap3_beagle_config
make CROSS_COMPILE=arm-eabi- -j4

The result of this process is ‘u-boot.bin’ file. And a successful build generates an output like this:

api/libapi.a post/libpost.a board/ti/beagle/libbeagle.a --end-group /home/kimi/rowboat-android/u-boot/arch/arm/lib/eabi_compat.o -L /home/kimi/rowboat-android/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/../lib/gcc/arm-eabi/4.6.x-google -lgcc -Map u-boot.map -o u-boot
arm-eabi-objcopy -O srec u-boot u-boot.srec
arm-eabi-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin

Building Android, Kernel and SGX

In order to build Android, its kernel and SGX (which provides the Hardware Acceleration needed by Android 3.x+)

cd ~/rowboat-android
make TARGET_PRODUCT=beagleboard OMAPES=5.x -j4

(This step takes aprox. 1 hour)
If this commad successed you will see something like this on the console

Installation complete!

cat install.sh >install
chmod a+x install
make[1]: Leaving directory `/home/kimi/rowboat-android/hardware/ti/sgx’
If you don’t see an output like this, try running the command without “-j4”.
If everything is Ok, then it’s time to create the root filesystem and compress it into a tar.gz file. (20 minutes. aprox)
cd ~/rowboat-android
make TARGET_PRODUCT=beagleboard fs_tarball -j4

Building Kernel and Android separately

It is possible to build the kernel and Android separately, and this is recommended once you have done a full build and you have modified only a small part of the code.

Builing the Kernel

cd ~/rowboat-android/kernel
make ARCH=arm CROSS_COMPILE=arm-eabi- distclean
make ARCH=arm CROSS_COMPILE=arm-eabi- omap3_beagle_android_defconfig
make ARCH=arm CROSS_COMPILE=arm-eabi- uImage -j4

This will generate ‘uImage’ (kernel image) in “~/rowboat-android/kernel/arch/arm/boot”

Builing Android

cd ~/rowboat-android
make TARGET_PRODUCT=beagleboard droid -j4

Again, in order to create the root filesystem, run

cd ~/rowboat-android
make TARGET_PRODUCT=beagleboard fs_tarball

Creating a bootable SD-Card

Once x-load, Uboot, kernel and Android are built, it’s time to create a bootable SD-Card with all this files.

Boot arguments

Edit boot arguments for am37x.
cd ~/RowboatTools/am37x/mk-bootscr
gedit boot.scr

Change mem=256M with mem=448M. This will increase the amount of RAM available in Android for applications.
Generate boot script

Putting all together

Format the SD Card into a single FAT32 partition. A +4GB SD Card is recommended, while the minimum amount of memory is 2GB.

mkdir ~/rowboat-image
cp ~/rowboat-android/kernel/arch/arm/boot/uImage ~/rowboat-image
cp ~/rowboat-android/u-boot/u-boot.bin ~/rowboat-image
cp ~/rowboat-android/x-loader/MLO ~/rowboat-image
cp ~/RowboatTools/am37x/mk-bootscr/boot.scr ~/rowboat-image
cp ~/rowboat-android/out/target/product/beagleboard/rootfs.tar.bz2 ~/rowboat-image
cp ~/RowboatTools/am37x/mk-mmc/mkmmc-android.sh ~/rowboat-image

Execute the script

cd ~/rowboat-image
sudo ./mkmmc-android.sh /dev/sdb  MLO u-boot.bin uImage boot.scr rootfs.tar.bz2

Change /dev/sdb with the path for your SD Card
If you don’t see anything executed on the console, may be mkmmc-android.sh has a hidden char that generates problem. Try opening the file with gEdit and copying the content to another file, for example mkmmc.sh. Then make that file executable and try again.


Now you are ready to extract the SD Card, insert it into the Beagleboard and run Android. Be patience, the first start up can take several minutes. The second time you start up Android it takes minutes more or less.


Some SD Cards show a very poor performance. Most Kingston micro SDHC cards have this performance issue. San Disk micro SDHC or Sony micro SDHC are recommended.

Known issues

  • mmc0: error -110 whilst initializing SD card
Your are using a SDHC Card affected by preemption model in Kernel 2.6. Look to this post about loading “rootfs” from USB . This avoids the bug, and gives more performance & storage space.