You are not logged in.

#1 2010-02-19 04:00:05

Lexion
Member
Registered: 2008-03-23
Posts: 510

problems with a kernel

I've started to write a kernel, and I have successfully gotten a kernel.bin file. But I don't know how to get this into a QEMU-bootable image with grub. Does anybody have any experience with this?

If you want it, here is my code (not all of it; I left out kernel.*, as it's mostly memcpy/strlen kind of stuff):

main.c

#include "kernel.h"
#include "screen.h"

void kmain(unsigned long magic, unsigned long addr)
{
    init_video();
    puts((unsigned char *)"hello, world");
    while(1);
}

bootstrap.asm

; bootstrap.asm
;
; Gets boot info from the bootloader, sets up the stack,
; and then runs the C function kmain.

[BITS 32]
global start
start:
    mov esp, _sys_stack
    jmp startkernel

ALIGN 4
mboot:
    MULTIBOOT_PAGE_ALIGN    equ 1<<0
    MULTIBOOT_MEMORY_INFO    equ 1<<1
    MULTIBOOT_HEADER_MAGIC    equ 0x1BADB002
    MULTIBOOT_HEADER_FLAGS    equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
    MULTIBOOT_CHECKSUM    equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

    dd MULTIBOOT_HEADER_MAGIC
    dd MULTIBOOT_HEADER_FLAGS
    dd MULTIBOOT_CHECKSUM

startkernel:
     EXTERN kmain
     call kmain
    jmp $

SECTION .bss
    resb 8192
_sys_stack:

screen.h

#ifndef __ONYX_SCREEN_H
#define __ONYX_SCREEN_H

#include "kernel.h"

// Screen Management Functions
unsigned short *__textbuf;
int attrib;
int __csr_x;
int __csr_y;

#define __ONYX_ROWS 80
#define __ONYX_COLS 24

void scroll();
void move_cursor();

extern void cls();
extern void putch(unsigned char c);
extern void puts(unsigned char *str);
extern void settextcolor(unsigned char fg, unsigned char bg);
extern void init_video();

#endif

screen.c

#include "screen.h"
#undef __ONYX_SCREEN_H

void scroll()
{
    unsigned space, temp;
    space = 0x20 | (attrib << 8);
    if (__csr_y > __ONYX_ROWS)
    {
        temp = __csr_y - __ONYX_ROWS + 1;
        memcpy((unsigned char *)__textbuf, (unsigned char *)__textbuf + (temp * __ONYX_COLS), (__ONYX_ROWS - temp) * __ONYX_COLS * 2);
        memsetw(__textbuf + (__ONYX_ROWS - temp)*__ONYX_COLS, space, __ONYX_COLS);
        __csr_y = __ONYX_ROWS - 1;
    }
}

void move_cursor()
{
    unsigned temp;
    temp = __csr_y * __ONYX_COLS * __csr_x;
    outportb(0x3D4, 14);
    outportb(0x3D5, temp >> 8);
    outportb(0x3D4, 15);
    outportb(0x3D5, temp);
}

extern void cls()
{
    unsigned space;
    int i;
    space = 0x20 | (attrib << 8);
    for (i = 0; i < __ONYX_ROWS; i++)
        memsetw(__textbuf + i*__ONYX_COLS, space, __ONYX_COLS);

    __csr_x = __csr_y = 0;
    move_cursor();
}

extern void putch(unsigned char c)
{
    unsigned short *where;
    unsigned att = attrib << 8;

    if (c == 0x08)
    {
        if (__csr_x != 0)
            __csr_x--;
    }
    else if (c == 0x09)
    {
        __csr_x = (__csr_x + 8) & ~(8-1);
    }
    else if (c == '\r')
    {
        __csr_x = 0;
        __csr_y++;
    }
    else if (c >= ' ')
    {
        where = __textbuf + (__csr_y * __ONYX_COLS + __csr_x);
        *where = c | att;
        __csr_x++;
    }

    if (__csr_x >= __ONYX_COLS)
    {
        __csr_x = 0;
        __csr_y++;
    }

    scroll();
    move_cursor();
}

extern void puts(unsigned char *str)
{
    int i;
    for (i = 0; i < strlen((const char *)str); i++)
        putch(str[i]);
}

extern void settextcolor(unsigned char fg, unsigned char bg)
{
    attrib = (bg << 4) | (fg & 0x0F);
}

extern void init_video()
{
    __textbuf = (unsigned short *)0xB8000;
    attrib = 0x0F;
    __csr_x = __csr_y = 0;
    cls();
}

NOTE: there are other files, if you want to see them, let me know.


urxvtc / wmii / zsh / configs / onebluecat.net
Arch will not hold your hand

Offline

#2 2010-02-21 12:57:49

Lexion
Member
Registered: 2008-03-23
Posts: 510

Re: problems with a kernel

I solved my own problem. Assuming that you have a file called kernel.elf or something and it has a bootstrap linked in, then the following will create a floppy disk image bootable via qemu.

dd if=/dev/zero of=kernel.img bs=1024 count=1440 # create image file
losetup /dev/loop0 kernel.img # create link between /dev/loop0 and kernel.img
mkfs -q /dev/loop0 # make filesystem
mount /dev/loop0 /mnt # mount filesystem
mkdir -p /mnt/boot/grub # setup file hiarchy
cp /boot/grub/stage* /mnt/boot/grub # install grub
cp kernel.img /mnt/ # load kernel
echo -e "device (fd0) /dev/loop0\nroot (fd0)\nsetup (fd0)\nquit\n" | grub --device-map=/dev/null # setup grub
umount /mnt # unmount filesystem
losetup -d /dev/loop0 # remove link

Then boot using qemu -fda kernel.img. You should get a grub prompt. Type this:

root (fd0)
kernel /kernel.img
boot

And it should boot your kernel.


urxvtc / wmii / zsh / configs / onebluecat.net
Arch will not hold your hand

Offline

#3 2010-02-22 22:45:00

Zerathidune
Member
Registered: 2007-02-25
Posts: 102

Re: problems with a kernel

If your kernel is multiboot compatible you can also just do:

qemu -kernel <kernel image>

and skip grub entirely. qemu supports booting multiboot and/or linux kernels natively.

Offline

#4 2010-02-22 23:23:42

Lexion
Member
Registered: 2008-03-23
Posts: 510

Re: problems with a kernel

GRUB initializes some hardware componentes (RAM, PIC, ...) and I rely on that, so I can't use your suggestion. But thanks anyway.


urxvtc / wmii / zsh / configs / onebluecat.net
Arch will not hold your hand

Offline

Board footer

Powered by FluxBB