Installing Linux onto a CompactFlash Card

 

By Torrey Vigesaa

05/09/02

 

Putting an embedded Linux system together

As a demonstration of what steps are needed to put together Linux on an embedded system, I have included directions on how to put together Linux onto a 64MB Compact Flash card for use on an x86 system.  This Linux system setup was designed as the simplest method to put the pieces of Linux together onto a flash memory device without getting into compiling the kernel or any other parts of the operating system.  x86 hardware is used as the target system which is not a typical embedded platform but the hardware is very accessible, any x86 PC mother board with IDE and an Ethernet adapter, keyboard and monitor should work.  Also using a target system that is the same as the development host avoids the extra steps needed for cross-platform development. 

This system does not make good use of flash memory and would be considered unnecessarily large for an embedded system.  Also the Ext2 file system is used which does not make use of auto leveling of flash media as do many RAM file systems.  Auto leveling is a technique used to evenly use the cells of flash memory, which has a limited amount of read/write life cycles.  Many CF media devices support over 100,000 read/writes per cell.

This system creates a Linux system manually installed onto a CompactFlash card.  The CompactFlash system can then be booted and used as a hard drive-less Linux system for use as a web server or other services.

 

Setup of the CF Linux system requirements:

An x86 PC with 2 IDE adapters, monitor, keyboard, and an Ethernet adapter is required for the host development system.  This host system will then become the target system.  If the CF Linux system is for use on a different target system than the host, it will be easier if both target and host are as similar as possible, having the same Ethernet adapter is the most important. 

The target system software will be assembled on a CompactFlash card of 64MB or greater.  Also a hard to find CF-to-IDE adapter is required.  I purchase from PCEngines (www.pcengines.com) shown below with 128MB CF card.

 

 

For a development host I used a 500Mhz AMD mainboard with a Via chipset, Award BIOS, and a Realtech network adapter.  I recommend Realtech because of its RedHat 6.2 Linux kernel support.

 

CF Linux Development Host Setup:

On the host system, install RedHat Linux 6.2 and any other software that you may want on the target CF card onto the hosts IDE hard drive on the primary IDE adapter.  Installed the CF card into the CF-to-IDE adapter, and attach the adapter to the secondary IDE adapter.

 

The instructions for creating the CF system are listed below.  ‘%’ or ‘#’ is used to signify your command prompt.  I added notes to the instruction in italic. These are mostly the step by step instructions I performed in creating a CF system, along with important output captured.  Your output may differ.

 


Installing Linux on CompactFlash

 

CF setup  04/28/02, based on BAH RH6.2

Setup on 128MB CompactFlash SanDisk

 

1.  Partition the CompactFlash device

Here I use the Linux fdisk utility,  remember to login as root.

% fdisk /dev/hdc

 

Command (m for help): p

 

Disk /dev/hdc: 8 heads, 32 sectors, 980 cylinders

Units = cylinders of 256 * 512 bytes

 

   Device Boot    Start       End    Blocks   Id  System

/dev/hdc1   *         1       979    125296    6  FAT16

 

Command (m for help): d

Partition number (1-4): 1

 

Command (m for help): p

 

Disk /dev/hdc: 8 heads, 32 sectors, 980 cylinders

Units = cylinders of 256 * 512 bytes

 

   Device Boot    Start       End    Blocks   Id  System

 

Command (m for help): n

Command action

   e   extended

   p   primary partition (1-4)

p

Partition number (1-4): 1

First cylinder (1-980, default 1): 1

Last cylinder or +size or +sizeM or +sizeK (1-980, default 980): +2M

 

Command (m for help): n

Command action

   e   extended

   p   primary partition (1-4)

p

Partition number (1-4): 2

First cylinder (18-980, default 18):

Using default value 18

Last cylinder or +size or +sizeM or +sizeK (18-980, default 980):

Using default value 980

 

Command (m for help): p

 

Disk /dev/hdc: 8 heads, 32 sectors, 980 cylinders

Units = cylinders of 256 * 512 bytes

 

   Device Boot    Start       End    Blocks   Id  System

/dev/hdc1             1        17      2160   83  Linux

/dev/hdc2            18       980    123264   83  Linux

 

Make partition #1 bootable:

Command (m for help): a

Partition number (1-4): 1

 

Write out partition info to disk:

Command (m for help): w

The partition table has been altered!

 

Calling ioctl() to re-read partition table.

 

WARNING: If you have created or modified any DOS 6.x

partitions, please see the fdisk manual page for additional

information.

Syncing disks.

 

2.  Format CF:

 

% mke2fs /dev/hdc1

mke2fs 1.18, 11-Nov-1999 for EXT2 FS 0.5b, 95/08/09

Filesystem label=

OS type: Linux

Block size=1024 (log=0)

Fragment size=1024 (log=0)

272 inodes, 2160 blocks

108 blocks (5.00%) reserved for the super user

First data block=1

1 block group

8192 blocks per group, 8192 fragments per group

272 inodes per group

 

Writing inode tables: done

Writing superblocks and filesystem accounting information: done

 

% mke2fs /dev/hdc2

mke2fs 1.18, 11-Nov-1999 for EXT2 FS 0.5b, 95/08/09

Filesystem label=

OS type: Linux

Block size=1024 (log=0)

Fragment size=1024 (log=0)

30848 inodes, 123264 blocks

6163 blocks (5.00%) reserved for the super user

First data block=1

16 block groups

8192 blocks per group, 8192 fragments per group

1928 inodes per group

Superblock backups stored on blocks:

        8193, 24577, 40961, 57345, 73729

 

Writing inode tables: done

Writing superblocks and filesystem accounting information: done

 

 

3.  Copy files to CF

Many time I use the –dpR flag when using the cp command for coping files,

-d, --no-dereference         preserve links

-p, --preserve               preserve file attributes if possible

-R, --recursive              copy directories recursively

 

% cp /etc/* /mnt/cf/etc/

du = 1512

 

You can use df to display partition space:

# df

Filesystem           1k-blocks      Used Available Use% Mounted on

/dev/hda6              4008380    988908   2815852  26% /

/dev/hda1                23302      8817     13282  40% /boot

/dev/hdc2               119363      1512    111688   1% /mnt/cf

 

# du /bin

4072    /bin

 

# cp -dpR /bin/* /mnt/cf/bin/

# du

4197    .

 

# du /sbin/

8       /sbin/pam_filter

3228    /sbin

# cp -dpR /sbin/* ./

# du

5       ./pam_filter

3539    .

 

When coping files from /dev be sure to use the –dp flag.

/dev file are special files that refer to hardware devices.

Also if you are using Linux kernel 2.4.2 or greater the /dev directory is a virtual directory, much like /proc so, this procedure may not work.

 

# cp -dpR /dev /mnt/cf

du /dev

12      /dev/ida

0       /dev/pts

4       /dev/raw

32      /dev/rd

112     /dev

# du /mnt/cf/dev/

12      /mnt/cf/dev/ida

1       /mnt/cf/dev/pts

4       /mnt/cf/dev/raw

33      /mnt/cf/dev/rd

114     /mnt/cf/dev

 

 

# mkdir root

# cd root

# cp /root/.* ./

 

# mkdir home

[root@beathome cf]# mkdir var

[root@beathome cf]# mkdir var/log

# cp -dpR /var/lock/subsys/* /mnt/cf/var/lock/subsys/

# cp -dpR /var/run/random-seed ./

 

in /mnt/cf/usr/:

# mkdir bin

[root@beathome usr]# mkdir lib

[root@beathome usr]# mkdir sbin

[root@beathome usr]# mkdir share

 

in /usr/bin :

# cp -dpR /usr/bin/du ./

[root@beathome bin]# cp -dpR /usr/bin/find ./

[root@beathome bin]# cp -dpR /usr/bin/free ./

[root@beathome bin]# cp -dpR /usr/bin/ftp ./

[root@beathome bin]# cp -dpR /usr/bin/gzip ./

[root@beathome bin]# cp -dpR /usr/bin/killall ./

[root@beathome bin]# cp -dpR /usr/bin/passwd ./

[root@beathome bin]# cp -dpR /usr/bin/perl ./

[root@beathome bin]# cp -dpR /usr/bin/pico ./

[root@beathome bin]# cp -dpR /usr/bin/telnet ./

[root@beathome bin]# cp -dpR /usr/bin/top ./

[root@beathome bin]# cp -dpR /usr/bin/uptime ./

[root@beathome bin]# cp -dpR /usr/bin/uuidgen ./

[root@beathome bin]# cp -dpR /usr/bin/which ./

 

in /usr/lib :

]# cp -dpR /usr/lib/libcrypto.a ./

[root@beathome lib]# cp -dpR /usr/lib/libcrypto.so ./

[root@beathome lib]# cp -dpR /usr/lib/libcrypto.so.0 ./

[root@beathome lib]# cp -dpR /usr/lib/libcrypto.so.0.9.5 ./

[root@beathome lib]# cp -dpR /usr/lib/libncurses.a ./

[root@beathome lib]# cp -dpR /usr/lib/libncurses.so.4 ./

[root@beathome lib]# cp -dpR /usr/lib/libncurses.so.4.0 ./

[root@beathome lib]# cp -dpR /usr/lib/libpopt.a ./

[root@beathome lib]# cp -dpR /usr/lib/libpopt.la ./

[root@beathome lib]# cp -dpR /usr/lib/libpopt.so ./

[root@beathome lib]# cp -dpR /usr/lib/libpopt.so.0 ./

[root@beathome lib]# cp -dpR /usr/lib/libpopt.so.0.0.0 ./

[root@beathome lib]# cp -dpR /usr/lib/libreadline.a ./

[root@beathome lib]# cp -dpR /usr/lib/libreadline.so ./

[root@beathome lib]# cp -dpR /usr/lib/libreadline.so.3 ./

[root@beathome lib]# cp -dpR /usr/lib/libreadline.so.3.0 ./

[root@beathome lib]# cp -dpR /usr/lib/libz.a ./

[root@beathome lib]# cp -dpR /usr/lib/libz.so ./

[root@beathome lib]# cp -dpR /usr/lib/libz.so.1 ./

[root@beathome lib]# cp -dpR /usr/lib/libz.so.1.1.3 ./

# du

3393    .

 

in /usr/sbin:

# cp -dpR /usr/sbin/* ./

 

in /usr/share (defined terminal types):

# mkdir terminfo

# mkdir terminfo/l

# cp -dpR /usr/share/terminfo/l/linux ./

# mkdir terminfo/x

# cp /usr/share/terminfo/x/* ./

 

 

4.  Edit file system table (fstab).

  This defines how to mount partition that should be mounted on boot:

 

original RH6.2 install (development host):

# cat fstab

/dev/hda6               /                           ext2    defaults        1 1

/dev/hda1               /boot                               ext2    defaults        1 2

/dev/cdrom             /mnt/cdrom                     iso9660 noauto,owner,ro 0 0

/dev/fd0                  /mnt/floppy                      auto    noauto,owner    0 0

none                      /proc                     proc    defaults        0 0

none                      /dev/pts                            devpts  gid=5,mode=620  0 0

/dev/hda5              swap                                swap    defaults        0 0

 

change to (target):

# cat fstab

/dev/hda2            /                               ext2    defaults        1 1

/dev/hda1            /boot                   ext2    defaults        1 2

none                    /proc                   proc    defaults        0 0

 

 

5. Networking Setup:

you may need to modify network settings if the target  needs to be different from devel host.  Below are the settings I used.

in :  /mnt/cf/etc/sysconfig

]# cat network

NETWORKING=yes

HOSTNAME="tav14"

GATEWAY=192.168.1.1

in: /mnt/cf/etc/sysconfig/network-scripts

# cat ifcfg-eth0

DEVICE="eth0"

#BOOTPROTO="dhcp"

BOOTPROTO="static"

IPADDR="192.168.1.14"

NETMASK="255.255.255.0"

NETWORK=192.168.1.0

ONBOOT="yes"

 

6.  Setup boot partition

first mount the CF boot partition:

[root@beathome /mnt]# mkdir cfboot

# mount /dev/hdc1 /mnt/cfboot/

# df

Filesystem           1k-blocks      Used Available Use% Mounted on

/dev/hda6              4008380    988124   2816636  26% /

/dev/hda1                23302      8817     13282  40% /boot

/dev/hdc2               119363     16072     97128  14% /mnt/cf

/dev/hdc1                 2121        13      2000   1% /mnt/cfboot

 

in: /mnt/cfboot/ copy necessary file:

# cp -dpR /boot/System.map-2.2.14-logo ./

[root@beathome cfboot]# cp -dpR /boot/boot.b ./

[root@beathome cfboot]# cp -dpR /boot/chain.b ./

[root@beathome cfboot]# cp -dpR /boot/map ./

[root@beathome cfboot]# cp -dpR /boot/module-info-2.2.14-5.0 ./

[root@beathome cfboot]# cp -dpR /boot/os2_d.b ./

[root@beathome cfboot]# cp -dpR /boot/vmlinuz-beathome ./

 

 

7.  Prepare LILO bootloader configuration

Edit /etc/lilo.conf:

 

# cat lilo.conf

boot=/dev/hdc

disk=/dev/hdc

  bios = 0x80

map=/mnt/cfboot/map

install=/mnt/cfboot/boot.b

prompt

timeout=50

linear

default=linux

vga=normal

 

image=/mnt/cfboot/vmlinuz-beathome

        label=linux

        read-only

        root=/dev/hda2

 

Execute the LILO writer.  After execution, do not move files in the CF /boot partition, LILO keeps static memory addresses to some of these files.

# lilo -C /mnt/cf/etc/lilo.conf

 

8.  Add files to the CF that I forgot to add earlier

Added linux *

I forgot to create /proc and /lib:

# mkdir proc

# mkdir lib

# ls /lib

# cp -dpR /lib/* ./

 

9.  Dump directory size information

This is only to show the size of directories of my CF system:

# du

12      ./lost+found

3       ./etc/X11/applnk/Utilities

6       ./etc/X11/applnk/Internet

2       ./etc/X11/applnk/System

12      ./etc/X11/applnk

2       ./etc/X11/fs

31      ./etc/X11

1       ./etc/autorpm.d/addons

3       ./etc/autorpm.d/pools

12      ./etc/autorpm.d

2       ./etc/chatscripts

2       ./etc/cron.d

7       ./etc/cron.daily

1       ./etc/cron.hourly

2       ./etc/cron.monthly

3       ./etc/cron.weekly

2       ./etc/default

1       ./etc/dhcpc

1       ./etc/gtk

4       ./etc/logrotate.d

28      ./etc/mail

13      ./etc/pam.d

4       ./etc/ppp/peers

16      ./etc/ppp

10      ./etc/profile.d

45      ./etc/rc.d/init.d

32      ./etc/rc.d/rc0.d

29      ./etc/rc.d/rc1.d

29      ./etc/rc.d/rc2.d

32      ./etc/rc.d/rc3.d

27      ./etc/rc.d/rc4.d

29      ./etc/rc.d/rc5.d

32      ./etc/rc.d/rc6.d

276     ./etc/rc.d

1       ./etc/rpm

2       ./etc/security/console.apps

18      ./etc/security

4       ./etc/skel

1       ./etc/smrsh

8       ./etc/ssh

1       ./etc/ssl/certs

1       ./etc/ssl/private

10      ./etc/ssl

1       ./etc/sysconfig/apm-scripts

1       ./etc/sysconfig/console

42      ./etc/sysconfig/network-scripts

57      ./etc/sysconfig

1       ./etc/vga

1499    ./etc

4197    ./bin

5       ./sbin/pam_filter

3539    ./sbin

12      ./dev/ida

1       ./dev/pts

4       ./dev/raw

33      ./dev/rd

114     ./dev

1       ./boot

41      ./root

1       ./home

1       ./var/log

1       ./var/lock/subsys

2       ./var/lock

2       ./var/run

6       ./var

979     ./usr/bin

3393    ./usr/lib

2207    ./usr/sbin

3       ./usr/share/terminfo/l

76      ./usr/share/terminfo/x

80      ./usr/share/terminfo

81      ./usr/share

6661    ./usr

1       ./proc

48      ./lib/modules/2.2.14-5.0/net

126     ./lib/modules/2.2.14-5.0/misc

177     ./lib/modules/2.2.14-5.0

2558    ./lib/modules/misc

12      ./lib/modules/2.2.16/block

48      ./lib/modules/2.2.16/net

70      ./lib/modules/2.2.16/fs

87      ./lib/modules/2.2.16/misc

219     ./lib/modules/2.2.16

2623    ./lib/modules/misc.old

12      ./lib/modules/2.2.14/block

48      ./lib/modules/2.2.14/net

70      ./lib/modules/2.2.14/fs

440     ./lib/modules/2.2.14/misc

575     ./lib/modules/2.2.14

6153    ./lib/modules

446     ./lib/security

16670   ./lib

32743   .

 

10.  Attempt first boot

   shutdown the development host

   unplug the HDD and CF device

   plug the CF device into the primary IDE adapter

   boot system

 

---------------

BOOT OK

---------------

 

If your system does not boot check these items:

1.      Verify that the BIOS detected your CF device correctly

2.      Verify that the boot partition is setup correctly

3.      Verify that the /etc/lilo.conf is configured correctly

While attemping to boot you only get part of the message “LILO” from the boot loader then a problem exists with your LILO configuration.  For example, if you only get the message “LI” during boot, then the boot loader cannot find the loaders second stage boot.p.  For more trouble shooting, lookup LILO documentation not in this document.

 

My system booted, so I logged in, entered the df command to display partition info, entered ps to display the process table, and entered top to display process resource info.

 

# df

Filesystem           1k-blocks      Used Available Use% Mounted on

/dev/hda2               119363     32804     80396  29% /

/dev/hda1                 2121       696      1317  35% /boot

 

]# ps ax

  PID TTY      STAT   TIME COMMAND

    1 ?        S      0:04 init [3]

    2 ?        SW     0:00 [kflushd]

    3 ?        SW     0:00 [kupdate]

    4 ?        SW     0:00 [kpiod]

    5 ?        SW     0:00 [kswapd]

  283 ?        S      0:00 syslogd -m 0

  292 ?        S      0:00 klogd

  306 ?        S      0:00 crond

  316 ?        S      0:00 sshd

  333 tty3     S      0:00 login -- root

  334 tty4     S      0:00 /sbin/mingetty tty4

  335 tty5     S      0:00 /sbin/mingetty tty5

  336 tty6     S      0:00 /sbin/mingetty tty6

  342 tty3     S      0:00 -bash

  365 ?        S      0:00 sshd

  366 ttyp0    S      0:00 -bash

  386 ttyp0    R      0:00 ps ax

 

# top

 

  6:04am  up 3 min,  2 users,  load average: 0.03, 0.07, 0.03

17 processes: 16 sleeping, 1 running, 0 zombie, 0 stopped

CPU states:  0.0% user,  0.1% system,  0.0% nice, 99.8% idle

Mem:    55252K av,   13368K used,   41884K free,    8068K shrd,     372K buff

Swap:       0K av,       0K used,       0K free                    8880K cached

 

  PID USER     PRI  NI  SIZE  RSS SHARE STAT  LIB %CPU %MEM   TIME COMMAND

  387 root      17   0   840  840   668 R       0  0.1  1.5   0:00 top

    1 root       0   0   476  476   404 S       0  0.0  0.8   0:04 init

    2 root       0   0     0    0     0 SW      0  0.0  0.0   0:00 kflushd

    3 root       0   0     0    0     0 SW      0  0.0  0.0   0:00 kupdate

    4 root       0   0     0    0     0 SW      0  0.0  0.0   0:00 kpiod

    5 root       0   0     0    0     0 SW      0  0.0  0.0   0:00 kswapd

  283 root       0   0   732  732   592 S       0  0.0  1.3   0:00 syslogd

  292 root       0   0   480  480   364 S       0  0.0  0.8   0:00 klogd

  306 root       0   0   628  628   516 S       0  0.0  1.1   0:00 crond

  316 root       1   0  1088 1088   952 S       0  0.0  1.9   0:00 sshd

  333 root       0   0   972  972   736 S       0  0.0  1.7   0:00 login

  334 root       0   0   412  412   344 S       0  0.0  0.7   0:00 mingetty

  335 root       0   0   412  412   344 S       0  0.0  0.7   0:00 mingetty

  336 root       0   0   412  412   344 S       0  0.0  0.7   0:00 mingetty

  342 root       1   0   972  972   740 S       0  0.0  1.7   0:00 bash

  365 root       1   0  1696 1696  1396 S       0  0.0  3.0   0:00 sshd

  366 root      15   0   976  976   740 S       0  0.0  1.7   0:00 bash

 

 


Resources

Embedded Linux Journal has published a bi-monthly magazine covering Embedded Linux since January 2001.  http://embedded.linuxjournal.com/about/

 

LinuxDevice.com covers the embedded Linux industry and embedded Linux products.  http://www.linuxdevices.com

 

An on-line book covering ARM Linux.  http://www.aleph1.co.uk/armlinux/book/mail-list.html

 

The site where ARM Linux is maintained.  http://www.arm.linux.org.uk/

 

The Linux Documentation Project.  http://www.tldp.org/

 

Intel’s StrongARM product site.  http://developer.intel.com/design/pca/applicationsprocessors/1110_brf.htm

 

Lart Linux ARM development systems, good resource for beginning Linux ARM development.   http://www.aleph1.co.uk/armlinux/index.html