[English] [Japanese]

Linux CD-ROM Game System

  YAMAMORI Takenori <yamamori@kt.rim.or.jp>

§ Making of initrd-game.img

The CD-ROM game system boots by using initrd skillfully as shown in the flow chart. So I explain a making method of initrd-game.img (an initrd for the game system) to the following.

¶ Making of cdmount.c

In boot of the system, initrd-game is mounted as a temporary root filesystem first. In the inside of the initrd, there are very few commands including /bin/sh but even a ls command doesn't exist (using "echo *" command instead of ls is a usual practice). And then we must do a mount of CD-ROM under this environment, but there is no mount command in the initrd.

We cannot copy a mount command from a usual Linux system because the mount command is dynamically linked with libc that is too big to make a boot floppy disk.

So we make a special, simple, and statically linked mount command with C language as follows. I name it cdmount.c.

· A list of cdmount.c
#include <sys/mount.h>

main(int argc, char **argv)
  int data = 0;
  return mount(argv[1], argv[2], argv[3], MS_RDONLY|MS_MGC_VAL, &data);

We must compile cdmount.c with the following option. It's a key to make a statically linked binary and to strip unnecessary symbol table.

gcc -O2 -static -s -o /tmp/cdmount cdmount.c

In cdmount.c, unnecessary processing is omitted entirely except that it returns a return value of whether mount() was successful.

Here, we can execute the following command for trial.

# /tmp/cdmount /dev/cdrom /mnt/cdrom iso9660

If a CD-ROM is mounted normally, it is OK.

¶ Making of initrd-game.img

In Linux, a shell script /sbin/mkinitrd to make initrd is prepared. This is a command needed by a system using a SCSI root filesystem to load a SCSI module in boot by an initrd.

The initrd is an ext2 filesystem image compressed by gzip, and it is read in boot.

We make initrd-game by using initrd which mkinitrd makes as a template.

The concrete procedure is the following:

(making a template of initrd)
# /sbin/mkinitrd -v -f /boot/initrd-game.img 2.2.14-1vl6
# zcat /boot/initrd-game.img > /tmp/initrd-game
					# Expand it with gzip and put it on tmp
(modifying initrd)
# mkdir /mnt/tmp
# mount -o loop /tmp/initrd-game /mnt/tmp  # loop-back mount as ext2
# cd /mnt/tmp                              # go into the inside of initrd-game
# mkdir -p mnt/cdrom
# mv bin dev etc lib mnt/cdrom
# ln -s mnt/cdrom/* .                  # symbolic links for bin, dev, etc,lib,
# ln -s mnt/cdrom/usr mnt/cdrom/sbin mnt/cdrom/var mnt/cdrom/root .
                      # Note: each symbolic link destination doesn't exist now
# touch fastboot                       # avoid fsck in boot
# mkdir proc
# mkdir tmp
# chmod 1777 tmp
# cp -a /dev/hd[abcd]* /dev/scd0 /dev/sda* mnt/cdrom/dev
# cp -p /tmp/cdmount .        # copy the cdmount we created
# vi linuxrc
      # ... see below about linuxrc ...
# cd /                                     # get out of initrd-game
# umount /mnt/tmp                          # umount the loop-back mount
# /sbin/losetup -d /dev/loop0
                      # losetup is needed because /etc/mtab has been modified
# gzip -9 < /tmp/initrd-game > /boot/initrd-game.img
                      # save it with gzip compressed

We add commands in linuxrc as follows. In linuxrc, there are a few lines described already by mkinitrd, but we just leave those.

· A list of linuxrc
#!/bin/sh                      # already described

echo "Loading aic7xxx module"  # described for a SCSI system
insmod /lib/aic7xxx.o          # described for a SCSI system

/cdmount /dev/hdc /mnt/cdrom iso9660 ||
/cdmount /dev/hdd /mnt/cdrom iso9660 ||
/cdmount /dev/hdb /mnt/cdrom iso9660 ||
/cdmount /dev/scd0 /mnt/cdrom iso9660 ||
  echo 'cannot mount CD-ROM, invoke /bin/sh'
mount -t proc none /proc
echo 0x100 > /proc/sys/kernel/real-root-dev
umount /proc

It's somewhat complexed, but you have to understand because it is a key of this system.

As a result, the directory tree of the inside of the initrd-game should be like the following:

· The inside of the initrd-game
 /sbin -> mnt/cdrom/sbin
 /bin -> mnt/cdrom/bin
 /usr -> mnt/cdrom/usr
 /lib -> mnt/cdrom/lib
 /etc -> mnt/cdrom/etc
 /var -> mnt/cdrom/var
 /dev -> mnt/cdrom/dev
 /root -> mnt/cdrom/root
           /   /insmod
           /lib/aic7xxx.o    # a SCSI module (there is none in case of IDE)

The directories like /bin made by mkinitrd are moved under /mnt/cdrom with symbolic links. Under /mnt/cdrom, there are minimum files that are needed even before mounting the CD-ROM. For example, the substance of /bin/sh exists in /mnt/cdrom/bin/sh.

In linuxrc, the cdmount command that we have made is executed, and CD-ROM is mounted. You will see that cdmount is executed a few times with changing a CD-ROM device in order of /dev/hdc,hdd,hdb,scd0. A shell systax "||" is used here. In other words, it tries to mount IDE or SCSI CD-ROM with each possible device file until an error code does not return. It is this purpose that we have made cdmount so as to return a return value of mount().

CD-ROM is mounted to cover whole /mnt/cdrom directory. Then each directory like /bin, /dev under /mnt/cdrom gets unable to be seen and each /bin, /dev on the CD-ROM can be seen instead of it.

By the way, if it cannot mount CD-ROM from every device, it invokes a shell with a message:
'cannot mount CD-ROM, invoke /bin/sh'
We can use this shell for testing with a hard drive before creating a CD-ROM.

After a mount of CD-ROM, linuxrc mounts a /proc filesystem by using a genuine mount command that is in the CD-ROM. And it writes 0x100, which is a device number of initrd, into real-root-dev in /proc so as to specify the initrd itself as a real root filesystem.

In addition, you will see that an empty file /fastboot is created in the inside of the initrd to prevent fsck in boot. If you forget it, the system won't start when it boots with just a CD-ROM because fsck complains about a hard drive corresponding to an old description of /etc/fstab.

When the modification of the initrd-game is finished, after unmounting it we compress the initrd with gzip and save it as /boot/initrd-game.img.

¶ Booting test for initrd-game.img

Now, there should be a complete initrd-game.img. At first, we test the initrd-game.img for booting with LILO on a hard drive.

Here, /etc/lilo.conf on a hard drive may be as follows:

· List of lilo.conf on a hard drive


We add the following description next to the above:

· List of lines to be added to lilo.conf
        root=0x101    # This must not be root=0x100, but actual value is ignored

Then we install the LILO.

# /sbin/lilo
Added linux *
Added game

By this state, we have a booting test with a hard drive. We don't insert any CD-ROM now.

Rebooting the machine, we type game just after the prompt of "LILO boot:". Then, after loading vmlinuz and initrd, a shell will be invoked from the linuxrc in the initrd-game as a result that it couldn't mount any CD-ROM. So we mount a hard drive by the cdmount command as follows:

# /cdmount /dev/hda1 /mnt/cdrom ext2  
               +--- change it with your actual hard drive partition.

Mounting the hard drive as read-only, we check that it can be a CD-ROM.

After executing the cdmount command, usual UNIX commands like ls should be available.

Exiting the shell, linuxrc is finished and /sbin/init gains control and the system starts. And the game should start as before.

To "Linux CD-ROM Game System" index

This page has been rewritten for the web from a manuscript of TECH Linux Vol. 2 "CD-ROM Game System" ASCII Corporation.
To "SunOS 4.1.4 the mystery" Home
© 2000 YAMAMORI Takenori