You are not logged in.

#1 2014-02-17 23:20:40

knarf
Member
Registered: 2012-07-16
Posts: 11

[SOLVED] Problems making a small linux image with initrd run in qemu

Hi,

I want to build a image with a kernel and an initramfs (that I can boot from qemu) for learning purpose but I'm stuck, here's what I've done so far:

  • build the kernel, end up with a bzImage file (compressed kernel image) for x86_64

  • make a 50MB ext2 disk:

    $ dd if=/dev/zero of=disk.raw bs=1M count=50
    $ mkfs.ext2 -F disk.raw
  • make a tiny initrd with a "hello world" init program:

    # hello world in asm with embed ELF header & using system calls
    $ cat > hello.asm
      BITS 32
      
                    org     0x08048000
      
      ehdr:                                                 ; Elf32_Ehdr
                    db      0x7F, "ELF", 1, 1, 1, 0         ;   e_ident
            times 8 db      0
                    dw      2                               ;   e_type
                    dw      3                               ;   e_machine
                    dd      1                               ;   e_version
                    dd      _start                          ;   e_entry
                    dd      phdr - $$                       ;   e_phoff
                    dd      0                               ;   e_shoff
                    dd      0                               ;   e_flags
                    dw      ehdrsize                        ;   e_ehsize
                    dw      phdrsize                        ;   e_phentsize
                    dw      1                               ;   e_phnum
                    dw      0                               ;   e_shentsize
                    dw      0                               ;   e_shnum
                    dw      0                               ;   e_shstrndx
      
      ehdrsize      equ     $ - ehdr
      
      phdr:                                                 ; Elf32_Phdr
                    dd      1                               ;   p_type
                    dd      0                               ;   p_offset
                    dd      $$                              ;   p_vaddr
                    dd      $$                              ;   p_paddr
                    dd      filesize                        ;   p_filesz
                    dd      filesize                        ;   p_memsz
                    dd      5                               ;   p_flags
                    dd      0x1000                          ;   p_align
      
      phdrsize      equ     $ - phdr
      
      _start:
      
    
      ; write(1, "hello\n", 6)
      mov eax, 4
      mov ebx, 1
      mov ecx, msg
      mov edx, msglen
      int 80h
      
      ; exit(0)
      mov eax, 1
      mov ebx, 0
      int 80h
    
      msg     db  "hello", 10
      msglen  equ $ - msg
      filesize      equ     $ - $$
    
    ^D
    
    $ nasm -f bin -o initrd/init hello.asm
    
    # test it out
    $ ./initrd/init
    hello
    
    # make the img
    $ cd initrd && find . | cpio --quiet -H newc -o | gzip -9 -n > ../initrd.img && cd ..
  • copy everything on the disk

    $ mkdir disk
    $ mount disk.raw disk
    $ mkdir disk/boot
    $ cp initrd.img bzImage disk/boot
  • install syslinux

    $ cat > disk/boot/syslinux.cfg
    DEFAULT linux
    LABEL   linux
    SAY     Booting linux
    LINUX   /boot/bzImage
    APPEND  root=/dev/sda
    INITRD  /boot/initrd.img
    ^D
    
    $ extlinux -i disk/boot
    $ umount disk
  • install mbr

    $ dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/mbr.bin of=disk.raw

But when I run the image in qemu

$ qemu-system-x86_64 disk.raw

I get the syslinux error: "Operating system load error" and it then tries to boot other devices (floppy, cd, net, ...).

You can get a script of the above command to test it out, along with the kernel here:

http://diobla.info/stuff/boot/mklinux
http://diobla.info/stuff/boot/bzImage (5MB)

Make a directory, cd in it, download the script and the kernel image then run script.
You need cpio, nasm, e2fsprogs, syslinux and finally qemu

The script must be run as root, be careful!


  • there's only a single filesystem without partition, is the root arg in the syslinux.cfg correct?

  • is syslinux.cfg the correct file? Could be syslinux.conf, extlinux.conf or extlinux.cfg but none of them seem work either.

Last edited by knarf (2014-02-20 17:42:27)

Offline

#2 2014-02-19 11:08:25

knarf
Member
Registered: 2012-07-16
Posts: 11

Re: [SOLVED] Problems making a small linux image with initrd run in qemu

Ok so

  • I've switched to partitions instead of whole disk

  • fixed some bugs in the script: heredoc string (<<EOF style) are expanded if you don't quote the EOF token, leading to the asm source being wrong.

Mounting partitions is not as simple as mounting the whole disk fs. See https://wiki.archlinux.org/index.php/Qe … disk_image

The updated script is at the same url.

...and it works! smile The kernet boots, runs init which prints hello and exit, and the kernel crashes (which is normal since init is not supposed to exit).

I'm now trying to enable the framebuffer in order to get the /dev/fb0 device. I've enabled a bunch of CONFIG_FB_* stuff in the kernel config which lets me change the resolution and add a logo with the vga=<code> kernel parameter but no /dev/fb0 device!

knarf ~/prog/c/linux-3.7.2 > grep '^C.*_FB' .config  
CONFIG_FB=y
CONFIG_FB_BOOT_VESA_SUPPORT=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_COPYAREA=y
CONFIG_FB_SYS_IMAGEBLIT=y
CONFIG_FB_SYS_FOPS=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
CONFIG_FB_VGA16=y
CONFIG_FB_UVESA=y
CONFIG_FB_VESA=y
CONFIG_FB_EFI=y
CONFIG_FB_VIRTUAL=y

Last edited by knarf (2014-02-19 23:26:19)

Offline

#3 2014-02-19 12:10:16

knarf
Member
Registered: 2012-07-16
Posts: 11

Re: [SOLVED] Problems making a small linux image with initrd run in qemu

To create the fb0 device you need to use the mknod system call. The framebuffer major device number is 29 and the minor one for fb0 is well 0.
Thus the call is:

mknod("/dev/fb0", S_IFCHR, makedev(29, 0))

I've compiled statically my init C code that draws a dumb xor-texture with musl-c and it works, here's the result smile

http://diobla.info/stuff/boot/draw.c


xor texture on framebuffer

Last edited by knarf (2014-02-19 12:15:16)

Offline

#4 2015-06-03 11:28:16

kenn
Member
Registered: 2014-06-25
Posts: 6

Re: [SOLVED] Problems making a small linux image with initrd run in qemu

@knarf thank you sharing your experience. I followed your instructions, built a kernel-2.6 bzImage and made an initrd with above hello.asm in /sbin/init. When I run it like qemu-system-x86_64 -kernel bzImage  -initrd rootfs.cpio.gz -append "root=/dev/ram0" it prints hello then crashes which is ok. But when I replace hello.asm example with hello.c example it fails to load init. It simply hangs after freeing memory line.
I also tried another advanced initrd images which is built from busybox but it also fails to start init process. Why does it fail to start init? What am I missing? It is most probably  related to kernel config. I also followed other kernel building for embedded systems to fit in a floppy but it didn't work. Perhaps I am missing some flags to run qemu-system-x86_64 ?

Offline

#5 2015-06-03 11:30:12

WorMzy
Forum Moderator
From: Scotland
Registered: 2010-06-16
Posts: 11,787
Website

Re: [SOLVED] Problems making a small linux image with initrd run in qemu

You have been warned about necrobumping before, kenn, please don't do it again.

https://wiki.archlinux.org/index.php/Fo … bumping.22

Closing.


Sakura:-
Mobo: MSI MAG X570S TORPEDO MAX // Processor: AMD Ryzen 9 5950X @4.9GHz // GFX: AMD Radeon RX 5700 XT // RAM: 32GB (4x 8GB) Corsair DDR4 (@ 3000MHz) // Storage: 1x 3TB HDD, 6x 1TB SSD, 2x 120GB SSD, 1x 275GB M2 SSD

Making lemonade from lemons since 2015.

Offline

Board footer

Powered by FluxBB