Contents

  1. Introduction
  2. Create the ramdisk
    1. Standard ramdisk
    2. Custom ramdisk
  3. cd /usr/src
  4. Build the kernel
  5. Insert ramdisk to kernel
  6. Make image bootable
  7. Credits
  8. Additional related links

Introduction

The purpose of this document is to guide you to create a RAM disk image and a custom kernel in order to boot your mini NetBSD off a Compact Flash or use it to debug it in an emulated environment, such as qemu.

The ramdisk image will have to be inserted into your kernel and then extracted to memory of your embedded device (or your emulator) and used as the root file system, which then can be used by your kernel as if it resided on a "normal" storage media like a hard drive.

The steps below were tested in a NetBSD 4.99.20 i386 box.

Create the ramdisk

First we need to create the ramdisk that will get embedded into the kernel. The ramdisk contains a filesystem with whatever tools are needed, usually ?basics/init and some tools like sysinst, ls(1), etc.

Standard ramdisk

To create the standard ramdisk (assuming your source tree lies at /usr/src and you have /usr/obj and /usr/tools):

# cd /usr/src
# ./build.sh -O ../obj -T ../tools -u tools
# cd /usr/src/etc/
# make MAKEDEV
# cd /usr/src/distrib/i386/ramdisks/ramdisk-big
# make TOOLDIR=/usr/tools

Custom ramdisk

If you want to customize the contents of the filesystem, customize the list file. Let's say for example that we need the ?basics/uname utility to be included in the ramdisk, which is not by default.

cd /usr/src

# ./build.sh -O ../obj -T ../tools -u tools
# cd /usr/src/etc/
# make MAKEDEV
# cd /usr/src/distrib/i386/ramdisks/ramdisk-big
# cp list list.old

Then we edit the list file, by adding the following line:

PROG    bin/uname

And after having done it:

# make TOOLDIR=/usr/tools

Either way, you will get something like this:

#    create  ramdisk-big/ramdisk-big.fs
Calculated size of `ramdisk-big.fs.tmp': 5120000 bytes, 65 inodes
Extent size set to 4096
ramdisk-big.fs.tmp: 4.9MB (10000 sectors) block size 4096, fragment size 512
        using 1 cylinder groups of 4.88MB, 1250 blks, 96 inodes.
super-block backups (for fsck -b #) at:
 32,
Populating `ramdisk-big.fs.tmp'
Image `ramdisk-big.fs.tmp' complete

And verify with:

$ ls -lh ramdisk-big.fs 
-rwxr-xr-x  1 root  wheel  4.9M Jun 19 08:33 ramdisk-big.fs

Build the kernel

Next we shall build our custom kernel with ramdisk support. We may choose any INSTALL* kernel configuration. Here, we will use INSTALL_TINY:

# cd /usr/src/sys/arch/i386/conf
# cp INSTALL_TINY MY_INSTALL_TINY

Then we edit MY_INSTALL_TINY file, and we go to the section:

# Enable the hooks used for initializing the root memory-disk.
options         MEMORY_DISK_HOOKS
options         MEMORY_DISK_IS_ROOT     # force root on memory disk
options         MEMORY_DISK_SERVER=0    # no userspace memory disk support
options         MEMORY_DISK_ROOT_SIZE=3100      # size of memory disk, in blocks

The size of MEMORY_DISK_ROOT_SIZE must be equal or bigger than the size of your image. To calculate the kernel value you can use following rule:

MEMORY_DISK_ROOT_SIZE=10000 would give 10000*512/1024 = 5000 kb

We check that the following lines are un-commented:

pseudo-device   md              1       # memory disk device (ramdisk)
file-system     MFS             # memory file system

Once we are done with the configuration file, we proceed with building our kernel:

# cd /usr/src
# ./build.sh  -O ../obj -T ../tools -u kernel=MY_INSTALL_TINY

Insert ramdisk to kernel

Having built our kernel, we may now insert the ramdisk to the kernel itself:

# cd /usr/src/distrib/i386/instkernel
# cp Makefile Makefile.old

Then we edit the Makefile, to make sure that the RAMDISKS and MDSETTARGETS variables are set properly. After the modifications, mine looks like this:

#       $NetBSD: how_to_create_bootable_netbsd_image.mdwn,v 1.3 2014/04/03 03:27:42 wiki Exp $                  

.include <bsd.own.mk>
.include "${NETBSDSRCDIR}/distrib/common/Makefile.distrib"

#       create ${RAMDISK_*} variables                                             
#                                                                                 
RAMDISKS=       RAMDISK_B       ramdisk-big

.for V F in ${RAMDISKS}
${V}DIR!=       cd ${.CURDIR}/../ramdisks/${F} && ${PRINTOBJDIR}
${V}=           ${${V}DIR}/${F}.fs
.endfor

MDSETTARGETS=   MY_INSTALL_TINY         ${RAMDISK_B}    -

MDSET_RELEASEDIR=       binary/kernel

.include "${DISTRIBDIR}/common/Makefile.mdset"

.include <bsd.prog.mk>

Next write:

make KERNOBJDIR=/usr/obj/sys/arch/i386/compile  TOOLDIR=/usr/tools

Should you encounter errors of the following form, try increasing the MEMORY_DISK_ROOT_SIZE at your kernel configuration file.

i386--netbsdelf-mdsetimage: fs image (5120000 bytes) too big for buffer (1587200 bytes)
*** Error code 1

Provided that everything went ok, you will have the following files in your current directory:

# ls -lh netbsd*
-rwxr-xr-x  1 root  wheel   21M Jun 20 11:07 netbsd-MY_INSTALL_TINY
-rw-r--r--  1 root  wheel  1.5M Jun 20 11:07 netbsd-MY_INSTALL_TINY.gz
-rw-r--r--  1 root  wheel   58K Jun 20 11:07 netbsd-MY_INSTALL_TINY.symbols.gz

Make image bootable

Finally:

# cd /usr/src/distrib/i386/floppies/bootfloppy-big
# cp Makefile Makefile.old

Edit the Makefile if your kernel config has a different name than INSTALL*. Replace FLOPPYKERNEL= netbsd-INSTALL.gz with FLOPPYKERNEL= netbsd-MY_INSTALL_TINY.gz (Where MY_INSTALL_TINY is of course the name of the custom kernel.)

# make TOOLDIR=/usr/tools
[...]
Final result:
-rw-r--r--  1 root  wheel  2949120 Jun 20 11:15 boot-big1.fs

Now you are ready to test your image, with qemu for example:

$ cd /usr/src/distrib/i386/floppies/bootfloppy-big
$ qemu boot-big1.fs

Credits

This article is based on ?Yazzy's work, who was kind enough to permit us include an article in this wiki. The original document may be found here.

Additional related links

  1. Creating a custom install/boot floppies for i386