How to create a Debian image for an Alix board


Posted by Diego Assencio on 2013.12.08 under Linux (Installation)

I have recently acquired an Alix board (model alix2c3) from PC Engines and decided to install Debian on it to use it as a server. This post is a step-by-step tutorial which describes how this can be done. I have made the assumption that you are using Ubuntu/Debian; if not, you might have to adapt some of the commands below to have them work on your distribution.

Unfortunately this task is not as easy as creating a Debian live USB stick, booting and installing from it. This limitation comes from the fact that the Alix boards come with a very simple firmware (called tinyBIOS) which does not support booting from a USB drive.

Fortunately there is a slot on the board for a Compact Flash (CF) card which the tinyBIOS can boot from. The solution is then to build a Linux image on a file, flash it directly to a CF card and insert it on the board. So let's get started!

1) Get a Debian installer image

Open a terminal, create and enter a directory where the work will be done:

mkdir debian
cd debian

You must now download a Debian installer image. I recommend you download a "network install" CD image directly from the Debian website for an i386 architecture. This CD image contains just the minimal amount of software you will need to start the installation; all necessary packages which do not come with it will be downloaded over the Internet.

To download a network install image directly (e.g. for Debian 7.2.0), run:

wget http://cdimage.debian.org/debian-cd/7.2.0/i386/iso-cd/debian-7.2.0-i386-netinst.iso

2) Install qemu

You will need qemu as a machine emulator. We will use it to create a disk image file (a file which can be used as virtual hard disk) and install Debian on it. To install qemu, run:

sudo apt-get install qemu

3) Create a disk image

You must first create a 1000MB disk image on a file. The file can be smaller than 1000MB (800MB should already be fine), but the installer failed during the partitioning step when I used 800MB so I increased the image size to get things to work smoothly:

qemu-img create debian.img 1000M

If you wish, you can make the image bigger than 1000M. Just make sure you don't create an image bigger than the size of your CF card.

4) Install Debian on the disk image

Start a virtual machine (VM) with qemu:

qemu-system-i386 -cdrom <debian-netinst.iso> -hda debian.img -boot d

with <debian-netinst.iso> replaced by the network install CD image you downloaded. This is what each part of the command above instructs qemu to do:

-cdrom debian-netinst.iso use debian-netinst.iso as a CD-ROM disk
-hda debian.img use debian.img as a hard disk
-boot d boot the VM from the CD-ROM disk

NOTE: if your mouse pointer gets captured by the VM window, press "Ctrl+Alt" (left keys) to recover it.

Now follow these steps (this is only an overview; these steps may be different depending on which version of Debian you are installing):

  • Select "Install"
  • Select your language
  • Select your country (for the time zone, locale etc.)
  • If you are prompted for a locale, choose the one which matches your country
  • Choose the keymap of your keyboard
  • Enter a hostname for your system (e.g. "alix-board")
  • Enter your domain name (e.g. "lan", or leave it blank if you wish)
  • Set the root password
  • You must now create a user (write the name of this user)
  • Choose a username for your user
  • Choose a password for your user
  • Partitioning method: Guided - use entire disk
  • Select disk to partition: SCSI1 (0,0,0) (sda) - 1.0 GB ATA QEMU HARDDISK
  • Partitioning scheme: All files in one partition
  • Select "Finish partitioning and write changes to disk"
  • Write the changes to disks? Yes
  • The base system will now be installed (this will take a while)
  • Select a country for a mirror (your country?)
  • Debian archive mirror: pick anyone you wish
  • HTTP proxy: you probably don't need this (leave it blank)
  • Participate in the package usage survey? This is up to you...
  • Additional things to install: SSH server and standard system utilities
  • Install the GRUB boot loader to the master boot record? Yes
  • Now finish the installation

Abort the reboot by pressing "Ctrl+C" on the terminal window in which you started qemu.

5) Make sure your packages are NOT for the i686 architecture

The Alix board has a 32 bit processor (in my case, the processor is an LX800) whose architecture is i586. Most packages from Debian are installed against the i486 architecture and will work just fine on an i586 processor, but there are two which might not follow this rule: libc and the kernel. We need to take a closer look at these.

To start, boot into your Debian image (I reserved 1024MB of RAM for it, you can use less if you wish):

qemu-system-i386 -hda debian.img -m 1024M

Now log in as "root". To show which libc package(s) you have installed, run:

dpkg --list | grep libc[0-9]

The output should look similar to this:

ii  libc6:i386           2.13-38     i386      Embedded GNU C Library: Shared libraries
ii  libc6-i686:i386      2.13-38     i386      Embedded GNU C Library: Shared libraries [i686 optimized]

In my case, both libc6 and libc6-i686 are installed since their corresponding lines start with "ii". The i686 version is, as the package description says, optimized for the i686 architecture and therefore undesirable for us, so you should remove it (replace libc6 with your libc version):

apt-get remove libc6-i686

Now let's take a look at the kernel. To find out which installed version(s) you have, run:

dpkg --list | grep linux-image

This is the kind of output you should expect:

ii  linux-image-3.2.0-4-686-pae          3.2.51-1                  i386         Linux 3.2 for modern PCs
ii  linux-image-686-pae                  3.2+46                    i386         Linux for modern PCs (meta-package)

This output shows that the installed Linux kernel has been compiled against the i686 architecture. We have to fix this since this kernel will not work on the Alix board. First, install the package which contains the kernel for the i486 architecture:

apt-get update
apt-get install linux-image-486

NOTE: if you have problems connecting to the Internet inside the VM, try editing the file /etc/resolv.conf and correct the nameserver (e.g. change it to the IP address of an OpenDNS server or to the nameserver given on the /etc/resolv.conf of the computer you are working on). This might fix your problem.

Reboot and select the i486 kernel on the GRUB screen. Now log in again as "root" and remove all installed kernel packages for the i686 architecture. To be clear, run:

dpkg --list | grep linux-image.*686

and remove every installed kernel package which you see with the following command:

apt-get purge linux-image-<version>

6) Set a static IP address for your board

Open the file/etc/network/interfaces:

nano /etc/network/interfaces

and add the following to it (remove or comment out whatever is already there for eth0):

auto eth0
iface eth0 inet static
address 192.168.1.254
netmask 255.255.255.0
gateway 192.168.1.1

Above 192.168.1.1 is the IP address of my router, 255.255.255.0 is the network mask of my local network and 192.168.1.254 is the desired static IP address for my board. Change these numbers according to your network settings.

This is what my /etc/network/interfaces looks like (lines I changed/added are emphasized):

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
#allow-hotplug eth0
#iface eth0 inet dhcp

auto eth0
iface eth0 inet static
address 192.168.1.254
netmask 255.255.255.0
gateway 192.168.1.1

7) Convert the created disk image to raw format

You need now to convert debian.img into a raw disk image. A raw disk image can be written (byte by byte) to an actual physical disk and can also be generated from a disk by copying its contents (again, byte by byte) to a file.

qemu-img convert debian.img -O raw debian.raw

8) Flash the raw image to the CF card

Insert a CF card into the card reader of your computer and run:

dmesg

The output of dmesg will show you the device node through which the CF card is accessible. Here are the bottom lines I get when I run it right after inserting a CF card:

[649459.289242] sd 28:0:0:1: [sdc] No Caching mode page present
[649459.289250] sd 28:0:0:1: [sdc] Assuming drive cache: write through
[649459.289256] sd 28:0:0:1: [sdc] Attached SCSI removable disk

This means the device node for the CF card on my setup is /dev/sdc. To flash the raw image to the card, run:

sudo dd if=debian.raw of=/dev/sdX status=progress

where /dev/sdX is the device node of your CF card. The status=progress flag on the command above is optional, but very useful since it will show the progress of the data transfer (which may take a while).

After dd is done, your image will be ready to be used. Insert the CF card on the board, connect an Ethernet cable to its network port which is right next to the serial port and turn on the device. If everything goes well, after some seconds you will be able to ssh into the board:

ssh root@<ip-of-your-board>

If even after a few minutes you cannot ssh into the board, boot your Debian image again using qemu and make sure you correctly removed the kernel and libc packages which were compiled against the i686 architecture (step 5). If everything is correct there, double-check your network configuration (step 6). Should you find any mistakes, redo steps 7 and 8.

9) OPTIONAL: resize the root partition to the whole disk

For my private servers I usually prefer having a single root partition (where all operational system and user files are stored) occupying the entire disk instead of several partitions with different purposes. In particular, I almost always get rid of the swap partition. If you wish to do this too, ssh into the board and edit the partition table from the CF card with:

fdisk /dev/sda

List all partitions:

Command (m for help): p

The partition list should look like this:

Disk /dev/sda: 4009 MB, 4009549824 bytes
5 heads, 35 sectors/track, 44749 cylinders, total 7831152 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
Disk identifier: 0x00020a69

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1853439      925696   83  Linux
/dev/sda2         1855486     2045951       95233    5  Extended
/dev/sda5         1855488     2045951       95232   82  Linux swap / Solaris

Write down the number on the "Start" column for /dev/sda1 since this is the (root) partition which we wish to extend. This value tells us the sector at which the partition starts.

Remove the swap partition (in my case, partition number 5 since the swap device node is /dev/sda5):

Command (m for help): d
Partition number (1-5): 5

Remove the extended partition (in my case, partition number 2 since its device node is /dev/sda2):

Command (m for help): d
Partition number (1-5): 2

List all partition agains (p). The result should look similar to this (I omitted the first lines for brevity):

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1853439      925696   83  Linux

To resize the root partition (sda1), first you must delete it by entering 'd'. Fdisk will automatically delete sda1 as it is the single partition left:

Command (m for help): d

Now create a new primary partition filling up the entire disk. This partition must start at the same sector as sda1 did initially:

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-7831151, default 2048): <start sector of sda1>
Last sector, +sectors or +size{K,M,G} (2048-7831151, default 7831151): <press Enter>
Using default value 7831151

If you list the partitions again (p), you should get the following:

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048     7831151     3914552   83  Linux

You need to make the recreated partition sda1 bootable again (its "bootable" state is under the column "Boot"; if you check the partition list you initially had, you will see it was bootable since it had a '*' on the "Boot" column):

Command (m for help): a
Partition number (1-4): 1

List the partitions again (p); you can now see that sda1 is again bootable:

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     7831151     3914552   83  Linux

Make sure the id (the partition type; you can see it on the "Id" column) of sda1 is the same as before. It should be, but if for some reason it isn't, press 't', then '1' and finally type in the same id number as you initially had.

Finally, save the changes to the partition table and exit fdisk (ignore the "Device or resource busy" error):

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

Now reboot the board:

reboot

Once the board has rebooted, run (this command will resize the filesystem of the root partition to the full partition size):

resize2fs /dev/sda1

Your root partition (mounted on /) should fill up the entire disk now (technically this is not true since there is a little bit of booting data at the beginning of the disk and also the first partition does not start right after that data). Reboot once again to make sure everything is fine. After rebooting, run:

df -h /

This is a typical output you should expect (for a 4GB CF card):

Filesystem                              Size  Used Avail Use% Mounted on
/dev/disk/by-uuid/<some-long-string>    3.7G  693M  2.9G  20% /

10) Enjoy your server

Your server is now ready to be used. Have fun with it! :-)

Comments

john on Feb 23, 2014:
really nice and explanatory tutorial.
how do you make it immune to power failures? i have my own as a router/home_server (PBX:asterisk,SAMBA, postfix, torrent) but it is very prone to power failures and i would like to make it read only without any success. if you manage to make it work, please let me know.
masoud on Apr 25, 2017:
"Unfortunately it does not show the progress of the data transfer"
you can use dd if=xxx.img of=/dev/sdx status=progress
it will work fine
Diego Assencio on Apr 25, 2017:
@masoud: Thank you very much for the hint! I updated the post accordingly :-)

Leave a reply

NOTE: A name and a comment (max. 1024 characters) must be provided; all other fields are optional. Equations will be processed if surrounded with dollar signs (as in LaTeX). You can post up to 5 comments per day.