Search:  
Gentoo Wiki

HOWTO_Install_Filesystem_Tarball_to_CompactFlash

Contents

Introduction

Given a filesystem tarball containing the Gentoo Linux operating, this HOW TO describes how you might go about installing the tarball contents on CompactFlash. But why would you want to put Gentoo on CompactFlash? The idea is to run a Single-Board Computer (e.g. ECM-5612) on Gentoo Linux by booting off CompactFlash.

The HOW TO assumes you have the necessary tools which include

  1. a computer running Linux (not necessarily Gentoo)
  2. a USB card reader-writer, e.g.
  3. a CompactFlash card

Most if not all Linux operating system configurations, Gentoo included, install the usb-storage module by default. Hence, the card reader works automatically without any extra effort. Just plug and go!

The tarball contains the entire operating system. Here is an example.

Follow both links and download the tarball and its MD5 hash. After download, run the MD5 check as follows.

royr@b1ynn2j ~ $ md5sum -c gentoo-xenomai.tar.bz2.md5sum
gentoo-xenomai.tar.bz2: OK

This particular tarball includes Gentoo Linux host operating system for i686 architecture based on Linux kernel 2.6.17 with Gentoo patches version 17-11, plus Xenomai 2.1.3 real-time nanokernel.

Preparing the CompactFlash Card

Having the Gentoo tarball and a new CompactFlash card, what next? You need to extract the tarball contents and prepare the card for booting.

Let us assume the card is blank. Actually blank cards—as delivered—are usually not blank in the strictest sense. They typically come pre-formatted with a VFAT partition. Useful for Windows systems but not for running Linux. First task: remove VFAT partition, make a new Linux partition with a new ext2 filesystem. Once this is done, we can extract the Gentoo-Xenomai filesystem tarball.

Repartition the Blank CompactFlash Card

Insert the card into your USB card reader.

Desktop Automatically Opens CompactFlash

Immediately, if you are running in a desktop environment such as KDE, a window pops up asking to open the media. Continue here if you select yes. Skip to next section if you select no.

Once attached, the memory card will appear in the kernel's mount table. Enter mount at the command line. You will see a list of mount points. One entry reads something like:

/dev/sdb1 on /media/disk type vfat (rw,noexec,nosuid,nodev,noatime,uid=1000,utf8,shortname=lower)

This shows you the device node /dev/sdb1 and the mount point /media/disk. You can access the card filesystem at the mount point. You will see it currently empty, assuming a brand-new card.

However, in order to successfully repartition, you need to detach the filesystem (unmount in UNIX parlance) first. Log in as root user. Enter command umount followed by the mount point.

b1ynn2j ~ # umount /media/disk

Filesystem now detached.

Re-partition CompactFlash

Run fdisk on device /dev/sdb, the card's device node. Enter command p to print the partition table.

b1ynn2j ~ # fdisk /dev/sdb

Command (m for help): p

Disk /dev/sdb: 1024 MB, 1024966656 bytes
32 heads, 63 sectors/track, 993 cylinders
Units = cylinders of 2016 * 512 = 1032192 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1         993     1000912+   6  FAT16

Notice a single partition marked as FAT16. Delete this and create a new Linux partition. Interaction with fdisk continues.

Command (m for help): d
Selected partition 1

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-993, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-993, default 993):
Using default value 993

Command (m for help): p

Disk /dev/sdb: 1024 MB, 1024966656 bytes
32 heads, 63 sectors/track, 993 cylinders
Units = cylinders of 2016 * 512 = 1032192 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1         993     1000912+  83  Linux

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

Calling ioctl() to re-read partition table.
Syncing disks.

Automatically exits. At this point, assuming KDE or GNOME desktop environments running, you will again see a prompt to open the card. Select Cancel. Do not try to open. The card contains a new partition type but not a new Linux filesystem, yet.

Make a New Linux Filesystem

Create a new ext2 Linux filesystem on partition 1. Use mkfs.

b1ynn2j ~ # mkfs -t ext2 /dev/sdb1
mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
125184 inodes, 250228 blocks
12511 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=260046848
8 block groups
32768 blocks per group, 32768 fragments per group
15648 inodes per group
Superblock backups stored on blocks:
         32768, 98304, 163840, 229376

Writing inode tables: done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 34 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

You can now re-insert the card, let the desktop open the media. This time when you run mount without arguments you see a different kind of filesystem.

/dev/sdb1 on /media/disk type ext2 (rw,noexec,nosuid,nodev,sync)

Note, option sync indicates synchronous transfers, safe but slow.

Extract the Filesystem Tarball

Extract the tarball and unmount the device. Extract as follows assuming the Linux desktop automatically mounted the card with slow synchronous transfers. Skip to the next section for asynchronous.

b1ynn2j ~ # tar xvjpf gentoo-xenomai.tar.bz2 -C /media/disk/

This takes a little while, even on a USB 2.0 card reader. There is a lot of information to transfer! Hit Ctrl+C to abort if you loose patience. Then follow the subsection below to extract the tarball asynchronously.

Asynchronously Extract the Filesystem Tarball

Synchronous transfer speed is very slow, too slow. You can speed it up by re-mounting without the sync option. The desktop adds the synchronous option for safety. Asynchronous is the default otherwise, so you only need to re-mount at the command line.

b1ynn2j ~ # umount /media/disk/
b1ynn2j ~ # mkdir /mnt/sdb1
b1ynn2j ~ # mount /dev/sdb1 /mnt/sdb1
b1ynn2j ~ # mount

Final command in this sequence lists the current mount points. Output includes the new mount point:

/dev/sdb1 on /mnt/sdb1 type ext2 (rw)

Now extract using:

b1ynn2j ~ # tar xvjpf gentoo-xenomai.tar.bz2 -C /mnt/sdb1/

Extracting now runs a lot faster. It completes in seconds. But remember this is because the transfer is asynchronous meaning transfer occurs in memory without blocking the transfer process. Actually copying the cached blocks to the device runs in parallel, in background. Before ejecting the card therefore, you need to wait for actual transfer. You can wait either by un-mounting the device or by asking for synchronization explicitly.

b1ynn2j ~ # sync

Finally, umount the device.

b1ynn2j ~ # umount /mnt/sdb1

Filesystem ready to go! But not quite ready for booting. See next.

Install GRUB Boot Record

One final step before extracting the card: you need to set up the boot record. Without this the card cannot boot. Follow the instructions below. Note that hd1 corresponds to sdb. GRUB uses a different device identification scheme.

b1ynn2j ~ # grub
Probing devices to guess BIOS drives. This may take a long time.


    GNU GRUB  version 0.97  (640K lower / 3072K upper memory)

 [ Minimal BASH-like line editing is supported.  For the first word, TAB
   lists possible command completions.  Anywhere else TAB lists the possible
   completions of a device/filename. ]
grub> root (hd1,0)
root (hd1,0)
 Filesystem type is ext2fs, partition type 0x83
grub> setup (hd1)
setup (hd1)
 Checking if "/boot/grub/stage1" exists... yes
 Checking if "/boot/grub/stage2" exists... yes
 Checking if "/boot/grub/e2fs_stage1_5" exists... yes
 Running "embed /boot/grub/e2fs_stage1_5 (hd1)"...  15 sectors are embedded.
succeeded
 Running "install /boot/grub/stage1 (hd1) (hd1)1+15 p (hd1,0)/boot/grub/stage2 /boot/grub/menu.lst"... succeeded
Done.
grub> quit
quit

Now you can eject the card and boot from it. No need to synchronize; the filesystem has already been dismounted.

Booting the Single-Board Computer

Insert the card into the SBC and switch on! The GRUB boot screen automatically selects Gentoo Linux after a few seconds. Then you see the Gentoo splash screen.

After booting the system, Gentoo displays the console login prompt. You will notice the system automatically brings up network device eth0. This corresponds to LAN1 port. It automatically configures this Ethernet port via DHCP. So if DHCP is available, networking will automatically configure and you will see the SBC's assigned address.

You can log in remotely via SSH. Log in as root remotely as follows. You do not need a password.

royr@b1ynn2j ~ $ ssh 192.168.0.2 -l root
The authenticity of host '192.168.0.2 (192.168.0.2)' can't be established.
RSA key fingerprint is 36:f4:6d:23:b1:d8:cf:6c:4f:1b:60:21:f8:77:e2:4c.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.0.2' (RSA) to the list of known hosts.
Last login: Fri Jan 19 17:36:23 2007 from 192.168.0.12
localhost ~ #

You can set a root password at this point by entering passwd then entering a new password twice.

You can also access the console directly of course, assuming you have a keyboard attached. Just enter root to log in as root user; no password required.

Advantages of SSH

Having the SBC automatically start the Ethernet interface and SSH adds other advantages. You can easily open a terminal, as above. But you can also conveniently exchange files using secure copy scp or even rsync.

The Linux desktop environments also support remote filesystem access via SSH. KDE calls it fish! If the SBC's IP address is 192.168.0.2, for instance, just open the URL fish://root@192.168.0.2 then drag-and-drop files in either direction, from and to.

Note, the filesystem given above (Gentoo Xenomai) includes a complete base system, compiler and tools as well.

Testing the Real-Time Subsystem

Run Xenomai's latency test as follows.

localhost ~ # cd /usr/xenomai/testsuite/latency/
localhost latency # ./run
*
*
* Type ^C to stop this application.
*
*
== Sampling period: 100 us
== Test mode: periodic user-mode task
== All results in microseconds
warming up...
RTT|  00:00:01  (periodic user-mode task, 100 us period)
RTH|-----lat min|-----lat avg|-----lat max|-overrun|----lat best|---lat worst
RTD|       1.936|       2.060|       4.217|       0|       1.936|       4.217
RTD|       2.100|       2.213|       4.814|       0|       1.936|       4.814
RTD|       2.100|       2.212|       4.978|       0|       1.936|       4.978
RTD|       2.103|       2.209|       4.272|       0|       1.936|       4.978
RTD|       2.099|       2.212|       4.489|       0|       1.936|       4.978
RTD|       2.100|       2.214|       4.582|       0|       1.936|       4.978
---|------------|------------|------------|--------|-------------------------
RTS|       1.936|       2.186|       4.978|       0|    00:00:06/00:00:06
localhost latency #

How To Use Xenomai

The filesystem includes Xenomai real-time nanokernel, including libraries and headers. So you can easily compile real-time software. Here are some simple examples.

Periodic Task

File: periodic_task.c
/*
 * Periodic task example
 */

#include <native/task.h>

#include <sys/mman.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>

/*
 * Task placeholder
 */
RT_TASK task_ph;

/*
 * Periodic task entry point
 */
void
periodic_task(void *cookie)
{
  int err;

  /*
   * Make the task periodic, once every second, i.e. 1e9 nanoseconds.
   */
  err = rt_task_set_periodic(&task_ph, TM_NOW, 1000000000);
  if (err)
  {
    fprintf(stderr, "set periodic err=%d\n", err);
    return;
  }

  for (;;)
  {
    unsigned long overruns;

    /*
     * Wait for the next period.
     */
    err = rt_task_wait_period(&overruns);
    if (err)
    {
      fprintf(stderr, "wait period err=%d\n", err);
      return;
    }

    printf("%ld overruns\n", overruns);
  }
}

/*
 * Signal catcher
 */
void
clean_up(int sig)
{
  rt_task_delete(&task_ph);
}

int
main(int argc,
     char *argv[])
{
  int err;

  /*
   * Lock all memory, including pages currently acquired
   * and those allocated in the future.
   */
  mlockall(MCL_CURRENT | MCL_FUTURE);

  /*
   * Spawn a new task.
   */
  err = rt_task_spawn(&task_ph,
		      "periodic_task",
		      0, /* stack size, any */
		      50, /* priority */
		      0, /* mode */
		      &periodic_task, /* entry point */
		      NULL); /* cookie */
  if (err)
  {
    fprintf(stderr, "task spawn err=%d\n", err);
    return 1;
  }

  /*
   * Trap terminate and interrupt signals.  Hit Ctrl+C to exit.
   */
  signal(SIGTERM, &clean_up);
  signal(SIGINT, &clean_up);

  /*
   * Wait for terminate or interrupt signal then exit.
   */
  pause();
  return 0;
}

This C program starts a periodic task. The task runs once a second indefinitely. During each periodic run, the task prints the number of periodic overruns; normally 0! Hit Ctrl+C to exit.

Interrupt Handling

File: irq0.c
/*
 * Interrupt example
 */

#include <native/task.h>
#include <native/intr.h>

#include <sys/mman.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>

/*
 * Task and interrupt placeholders
 */
RT_TASK task_ph;
RT_INTR intr_ph;

void
interrupt_task(void *cookie)
{
  int err;

  for (;;)
  {
    /*
     * Wait for next interrupt.
     */
    err = rt_intr_wait(&intr_ph, TM_INFINITE);
    if (err < 0)
    {
      fprintf(stderr, "interrupt wait err=%d\n", err);
      return;
    }

    printf("%d interrupts\n", err);
  }
}

void
clean_up(int sig)
{
  rt_task_delete(&task_ph);
  rt_intr_delete(&intr_ph);
}

int
main(int argc,
     char *argv[])
{
  int err;

  mlockall(MCL_CURRENT | MCL_FUTURE);

  err = rt_intr_create(&intr_ph,
		       "irq0",
		       0, /* IRQ0 */
		       I_PROPAGATE);
  if (err)
  {
    fprintf(stderr, "interrupt create err=%d\n", err);
    return 1;
  }

  err = rt_task_spawn(&task_ph,
		      "interrupt_task",
		      0, /* stack size */
		      50, /* priority */
		      0, /* mode */
		      &interrupt_task, /* entry */
		      NULL); /* cookie */
  if (err)
  {
    fprintf(stderr, "task spawn err=%d\n", err);
    return 1;
  }

  signal(SIGTERM, &clean_up);
  signal(SIGINT, &clean_up);

  pause();
  return 0;
}

This program catches Interrupt ReQuest 0 (typically the system timer interrupt). It prints the number of pending interrupts at each request; normally 0 since none pending when rt_intr_wait returns. Hit Ctrl+C to exit.

Simple Makefile

Here is a simple makefile. To build the software listed above, just enter make periodic_task irq0. This assumes C sources and makefile exist in the current directory.

File: makefile
CFLAGS = $(shell xeno-config --xeno-cflags)
LDFLAGS = $(shell xeno-config --xeno-ldflags)
LDLIBS = -lnative
CC = gcc

Shutting Down

Just enter halt.

chroot Environment

You can also run the tarball from within a host environment using chroot.

As root user, create a subdirectory and extract the tarball. The following assumes you have created a subdirectory gentoo-xenomai and changed-directory to this location. It also assumes that the tarball is in the directory. Add path to the tarball if not.

b1ynn2j gentoo-xenomai # tar xjpf gentoo-xenomai.tar.bz2
b1ynn2j gentoo-xenomai # ls
bin  boot  dev  etc  home  lib  opt  proc  root  sbin  sys  tmp  usr  var

Create the following bash script in the new change-root's root directory. Contents listed below.

File: chroot script
#!/bin/bash
rootdir=$(dirname $0)
for dir in dev dev/pts dev/shm proc proc/bus/usb sys usr/portage tmp
do mount -o bind /${dir} ${rootdir}/${dir}
umountdirs="${rootdir}/${dir} ${umountdirs}"
done
trap "umount ${umountdirs}" EXIT
for conf in resolv.conf
do cp -pf /etc/${conf} ${rootdir}/etc
done
linux32 chroot ${rootdir} /bin/bash --login

Note linux32 belongs to the setarch package. It switches kernel architecture to i686, so that uname -m gives i686. You only need this on 64-bit hosts. Without it, the compiler tool-chain refuses to compile.

Make the script executable.

b1ynn2j gentoo-xenomai # chmod +x chroot

Now you can invoke the change-root using the script.

b1ynn2j gentoo-xenomai # ./chroot

The very next prompt comes from the 32-bit sub-environment.

Exit the environment by entering logout or exit.

Things to Remember

Remember that the chroot environment uses the same kernel as the host. Therefore any kernel-level interactions also affect the host. If you ask the chroot to reboot, for example, your host will reboot!

Troubleshooting

What if things go wrong?

Error exit delayed from previous errors

When extracting the tarball tar reports:

tar: Error exit delayed from previous errors

This can happen if you miss out the all important p option. Note the extract options are xvjpf. Option p preserves permissions. Some of the filesystem nodes are device nodes; many have special permissions.

Note also, you need root level access to extract device nodes and set special permissions; tar uses mknod, see Linux Programmer's Manual mknod(2) for more information. So you need to be logged in as root user or run via sudo.

Feedback

Concerns or Compliments? Please use the Discussion section.

Retrieved from "http://www.gentoo-wiki.info/HOWTO_Install_Filesystem_Tarball_to_CompactFlash"

Last modified: Sat, 13 Sep 2008 21:02:00 +0000 Hits: 1,398