QEMU Build Tutorial: Difference between revisions

From coreboot
Jump to navigation Jump to search
No edit summary
Line 7: Line 7:
While there are many ways to use LinuxBIOS to load and run a Linux kernel, this tutorial covers two of the most common:
While there are many ways to use LinuxBIOS to load and run a Linux kernel, this tutorial covers two of the most common:


* LinuxBIOS with FILO as payload, using FILO to load a Linux kernel and initramfs from a hard disk image.
* LinuxBIOS with FILO as payload, using FILO to load a Linux kernel (and optional initramfs) from a hard disk image.  This approach involves a bit more mechanism (it relies on FILO's built-in disk and filesystem drivers) but it produces a tiny LinuxBIOS image.
* LinuxBIOS with a Linux kernel and initramfs as payload.
* LinuxBIOS with a Linux kernel (and optional initramfs) as payload.  This cuts FILO out of the picture, but the main challenge with is approach is squeezing the resulting LinuxBIOS image into Qemu's BIOS ROM area (currently 2 MB, but easy to extend by patching Qemu).


=== Requirements ===   
=== Requirements ===   
Line 19: Line 19:
* [ftp://ftp.lnxi.com/pub/mkelfImage mkelfImage] 2.7 or greater (if not using FILO)
* [ftp://ftp.lnxi.com/pub/mkelfImage mkelfImage] 2.7 or greater (if not using FILO)


plus a Linux kernel and root filesystem and a working development environment (make, gcc, etc.).  gcc 4.0.x and 4.1.x are known to work.
plus a Linux kernel and root filesystem and a working development environment (make, gcc, etc.).  gcc 4.0.x and 4.1.x are known to work for all packages except Qemu, which requires gcc 3.2.


=== Building FILO ===
=== Building or finding a Linux kernel ===
 
If you are using FILO, you can simply grab a Linux kernel and initramfs from your favorite distribution.
 
Otherwise, you will probably need to build a kernel and initramfs from scratch, ensuring that the final LinuxBIOS image does not exceed Qemu's BIOS size limit.  Building the kernel and initramfs is beyond the scope of this tutorial; how you configure them depends on your application.
 
If you plan to use kexec to chain-boot another Linux kernel, tools from these projects can help automate the process of generating a kernel and initramfs for LinuxBIOS:
* [http://kboot.sourceforge.net/ kboot]
* [http://wiki.laptop.org/go/LinuxBIOS OLPC LinuxBIOS] (buildrom)
 
=== Building a FILO payload ===


If you plan to build your Linux kernel and root filesystem directly into LinuxBIOS, you can skip this section.
If you plan to build your Linux kernel and root filesystem directly into LinuxBIOS, you can skip this section.


Download FILO (I used filo-0.4.2.tar.bz2), decompress it, enter inside the created directory.
Download FILO (I used filo-0.4.2.tar.bz2), decompress it, and cd to the created directory.
    
    
First invocation of make creates the default Config file.
First invocation of make creates the default Config file.
Line 38: Line 48:
You will use this file (filo.elf) as the LinuxBIOS payload later on.
You will use this file (filo.elf) as the LinuxBIOS payload later on.


=== Creating LinuxBIOS ===
=== Building a Linux kernel payload ===


Download LinuxBIOS source code (I used LinuxBIOSv2-2394).   
If you are using FILO, skip this section.
Decompress it.  
 
 
Download mkelfImage (I used mkelfImage-2.7.tar.gz), decompress it, and cd to the created directory.
Change to directory targets/emulation/qemu-i386 and modify Config.lb to point to your filo.elf.   
 
Configure and build the mkelfImage binary.
  $ ./configure
  $ make
 
Now use mkelfImage to convert your Linux kernel image (vmlinuz) and initramfs (initrd) into a usable LinuxBIOS payload (linux.elf):
$ mkelfImage --initrd=initrd vmlinuz linux.elf
 
=== Building LinuxBIOS ===
 
Download the LinuxBIOS source code (I used LinuxBIOSv2-2394) and extract it.   
    
    
Change to directory targets/emulation/qemu-i386 and modify Config.lb:
* change payload to point to your payload (filo.elf or linux.elf)
* if you are using a Linux payload, increase the value of option ROM_SIZE to 2048*1024 (2 MB)
Return to targets directory and execute:   
Return to targets directory and execute:   
  $ ./buildtarget emulation/qemu-i386   
  $ ./buildtarget emulation/qemu-i386   


Go to targets/emulation/qemu-i386/qemu-i386 and execute:   
Go to targets/emulation/qemu-i386/qemu-i386 and execute:   
$ make 


  $ make  
This creates the LinuxBIOS image (qemu-bios.rom). Copy and rename this file to bios.bin in your home directory.  
 
=== Building or obtaining Qemu ===


It will create the file "qemu-bios.rom"  
If you plan to run Qemu version 0.8.2, you will have to build Qemu from source after applying a couple of patches(Later versions of Qemu might incorporate these patches, allowing you to run them unmodified; hopefully someone will be kind enough to update this tutorial if this happens.)
 
Rename this file to "bios.bin" and copy to your HOME directory.
 


=== Creating your disk image ===
Download the Qemu source code (I used qemu-0.8.2.tar.gz) and extract it.
Create a empty file (~ 200MB):


# dd if=/dev/zero of=disk.img bs=1M count=200
Download the two patches and save them to the Qemu source directory:
* [http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00155.html qemu-linuxbios.patch]
* [http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00156.html qemu-piix-ram-size.patch]


Format it as ext2:  
Enter the Qemu source directory and apply the patches:
$ patch -p1 <qemu-linuxbios.patch
$ patch -p1 <qemu-piix-ram-size.patch


  # mkfs.ext2 -F disk.img
Configure and make Qemu (use the --cc option if your default gcc is newer than version 3.2):
  $ ./configure --cc=gcc32 --target-list=i386-softmmu
$ make


Mount it on somewhere:
The Qemu binary is stored in the i386-softmmu directory.


# mount disk.img /mnt/rootfs -t ext2 -o loop
=== Creating a hard disk image ===


Now you need copy a root filesystem to it.  
If you are using FILO, you must create a hard disk image containing the Linux kernel and optional initramfs that FILO loads.


I create a directory /debian and used debootstrap command to create a basic root filesystem, but you can use any root filesystem from your distro (i.e. copy one from diskboot.img):
Whether or not you use FILO, you may also wish to populate the disk image with the root filesystem of whatever Linux distribution you want to run.


  # cp -R /debian/* /mnt/rootfs
Create an empty disk image:
  $ qemu-img create -f raw disk.img 200M


Open the file /mnt/rootfs/etc/inittab and change runlevel to level 1:  
Format it:
$ mkfs.ext2 -F disk.img


  id:1:initdefault:  
The remaining steps must be performed as root. Create a temporary mountpoint and mount the image:
# mkdir /mnt/rootfs
# mount -o loop disk.img /mnt/rootfs


Change to /mnt/rootfs/boot and copy your default vmlinuz and initrd:
Create a boot directory and copy your Linux kernel (vmlinuz) and initramfs (initrd) to it:
# mkdir /mnt/rootfs/boot
# cp vmlinuz vmlinuz
# cp initrd initrd


  # cp /boot/vmlinuz-2.6.16-2-686 vmlinuz
At this point, you can also copy a complete root filesystem to the disk image.  For example, with Debian you can use the debootstrap command to create a basic root filesystem:
# cp /boot/initrd.img-2.6.16-2-686 initrd
  # cp -R /debian/* /mnt/rootfs


Change to /root and umount /mnt/rootfs:
If you are using a debootstrap filesystem, open the file /mnt/rootfs/etc/inittab and change runlevel to level 1:
id:1:initdefault:  


cd out of /mnt/rootfs and umount it:
  # umount /mnt/rootfs
  # umount /mnt/rootfs


Exit of root account:
Exit from the root account:
 
  # exit
  # exit


=== Starting LinuxBIOS in Qemu ===
=== Starting LinuxBIOS in Qemu ===


Execute Qemu using the followings parameters:
Execute Qemu using the following parameters:
$ qemu -L ~ -hda disk.img -nographic


$ qemu -L ~ -hda disk.img -nographic -no-kqemu -d in_asm,exec
The -L option tells Qemu to look for bios.bin in your HOME directory. -nographic is needed to suppress the graphical VGA display; the virtual machine's serial port device is instead redirected to your console.


When appear "boot:" text enter it:
You should now see all sorts of interesting LinuxBIOS messages, followed by Linux kernel boot messages or a FILO prompt.


  boot: hda:/boot/vmlinuz root=/dev/hda initrd=/boot/initrd console=tty0 console=ttyS0,115200
If you are using FILO, enter at the boot: prompt:
  boot: hda:/boot/vmlinuz root=/dev/hda initrd=/boot/initrd console=ttyS0

Revision as of 00:36, 14 September 2006

Introduction

If you don't have a mainboard supported by LinuxBIOS don't worry: Qemu can help you to emulate one.

This nice tutorial was written by Alan Carvalho de Assis <acassis@gmail.com>, with additions by Ed Swierk <eswierk@arastra.com>.

While there are many ways to use LinuxBIOS to load and run a Linux kernel, this tutorial covers two of the most common:

  • LinuxBIOS with FILO as payload, using FILO to load a Linux kernel (and optional initramfs) from a hard disk image. This approach involves a bit more mechanism (it relies on FILO's built-in disk and filesystem drivers) but it produces a tiny LinuxBIOS image.
  • LinuxBIOS with a Linux kernel (and optional initramfs) as payload. This cuts FILO out of the picture, but the main challenge with is approach is squeezing the resulting LinuxBIOS image into Qemu's BIOS ROM area (currently 2 MB, but easy to extend by patching Qemu).

Requirements

You need the following software packages:

plus a Linux kernel and root filesystem and a working development environment (make, gcc, etc.). gcc 4.0.x and 4.1.x are known to work for all packages except Qemu, which requires gcc 3.2.

Building or finding a Linux kernel

If you are using FILO, you can simply grab a Linux kernel and initramfs from your favorite distribution.

Otherwise, you will probably need to build a kernel and initramfs from scratch, ensuring that the final LinuxBIOS image does not exceed Qemu's BIOS size limit. Building the kernel and initramfs is beyond the scope of this tutorial; how you configure them depends on your application.

If you plan to use kexec to chain-boot another Linux kernel, tools from these projects can help automate the process of generating a kernel and initramfs for LinuxBIOS:

Building a FILO payload

If you plan to build your Linux kernel and root filesystem directly into LinuxBIOS, you can skip this section.

Download FILO (I used filo-0.4.2.tar.bz2), decompress it, and cd to the created directory.

First invocation of make creates the default Config file.

$ make

Edit this file as you like. The default configuration worked for me.

$ vi Config   

Run make again to create filo.elf, the ELF FILO image.

$ make   

You will use this file (filo.elf) as the LinuxBIOS payload later on.

Building a Linux kernel payload

If you are using FILO, skip this section.

Download mkelfImage (I used mkelfImage-2.7.tar.gz), decompress it, and cd to the created directory.

Configure and build the mkelfImage binary.

$ ./configure
$ make

Now use mkelfImage to convert your Linux kernel image (vmlinuz) and initramfs (initrd) into a usable LinuxBIOS payload (linux.elf):

$ mkelfImage --initrd=initrd vmlinuz linux.elf

Building LinuxBIOS

Download the LinuxBIOS source code (I used LinuxBIOSv2-2394) and extract it.

Change to directory targets/emulation/qemu-i386 and modify Config.lb:

  • change payload to point to your payload (filo.elf or linux.elf)
  • if you are using a Linux payload, increase the value of option ROM_SIZE to 2048*1024 (2 MB)

Return to targets directory and execute:

$ ./buildtarget emulation/qemu-i386  

Go to targets/emulation/qemu-i386/qemu-i386 and execute:

$ make  

This creates the LinuxBIOS image (qemu-bios.rom). Copy and rename this file to bios.bin in your home directory.

Building or obtaining Qemu

If you plan to run Qemu version 0.8.2, you will have to build Qemu from source after applying a couple of patches. (Later versions of Qemu might incorporate these patches, allowing you to run them unmodified; hopefully someone will be kind enough to update this tutorial if this happens.)

Download the Qemu source code (I used qemu-0.8.2.tar.gz) and extract it.

Download the two patches and save them to the Qemu source directory:

Enter the Qemu source directory and apply the patches:

$ patch -p1 <qemu-linuxbios.patch
$ patch -p1 <qemu-piix-ram-size.patch

Configure and make Qemu (use the --cc option if your default gcc is newer than version 3.2):

$ ./configure --cc=gcc32 --target-list=i386-softmmu
$ make

The Qemu binary is stored in the i386-softmmu directory.

Creating a hard disk image

If you are using FILO, you must create a hard disk image containing the Linux kernel and optional initramfs that FILO loads.

Whether or not you use FILO, you may also wish to populate the disk image with the root filesystem of whatever Linux distribution you want to run.

Create an empty disk image:

$ qemu-img create -f raw disk.img 200M

Format it:

$ mkfs.ext2 -F disk.img 

The remaining steps must be performed as root. Create a temporary mountpoint and mount the image:

# mkdir /mnt/rootfs
# mount -o loop disk.img /mnt/rootfs

Create a boot directory and copy your Linux kernel (vmlinuz) and initramfs (initrd) to it:

# mkdir /mnt/rootfs/boot
# cp vmlinuz vmlinuz
# cp initrd initrd

At this point, you can also copy a complete root filesystem to the disk image. For example, with Debian you can use the debootstrap command to create a basic root filesystem:

# cp -R /debian/* /mnt/rootfs 

If you are using a debootstrap filesystem, open the file /mnt/rootfs/etc/inittab and change runlevel to level 1:

id:1:initdefault: 

cd out of /mnt/rootfs and umount it:

# umount /mnt/rootfs

Exit from the root account:

# exit

Starting LinuxBIOS in Qemu

Execute Qemu using the following parameters:

$ qemu -L ~ -hda disk.img -nographic

The -L option tells Qemu to look for bios.bin in your HOME directory. -nographic is needed to suppress the graphical VGA display; the virtual machine's serial port device is instead redirected to your console.

You should now see all sorts of interesting LinuxBIOS messages, followed by Linux kernel boot messages or a FILO prompt.

If you are using FILO, enter at the boot: prompt:

boot: hda:/boot/vmlinuz root=/dev/hda initrd=/boot/initrd console=ttyS0