Kernel throws GPF exception when booted with GRUB 2 instead of GRUB 0.97

189 Views Asked by At

I am trying to switch from GRUB 0.97 (stage2_eltorito) to GRUB 2, generating an ISO image that boots the operating system. However, I am facing a peculiar error. Just to give some context, I have recently set up some exception handling ISRs and two IRQs: one for keyboard input, one for timer ticks. When booted with GRUB Legacy, the kernel works fine, and the keyboard input also works. When booting with GRUB 2, for some reason, the kernel catches a General Protection Fault exception and halts the system. I have proofread my code multiple times and I cannot find an error in it anywhere that may cause this GPF error. What is my problem, and how can it be fixed? Here is the Assembly entry point of the kernel, including the Multiboot header:

extern toc
extern init
extern kmain
extern load_gdt

global start32

MBALIGN equ 1<<0
MEMINFO equ 1<<1
MAGIC_NUMBER equ 0x1BADB002
FLAGS equ MBALIGN | MEMINFO
CHECKSUM equ -(MAGIC_NUMBER + FLAGS)

section .text
align 4
dd MAGIC_NUMBER
dd FLAGS
dd CHECKSUM

start32:
    call load_gdt

    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov esp, 0x9c000

    call init
    push ebx
    call kmain

(I don't think this a Multiboot issue, as the kernel actually loads perfectly in both cases) The load_gdt and associated labels mentioned here (as I think this may be part of the issue)

global toc
global load_gdt

section .text
load_gdt:
    lgdt[toc]
    ret
section .rodata
gdt32:
    dd 0
    dd 0

    dw 0x0FFFF
    dw 0
    db 0
    db 0x9A
    db 0xCF
    db 0

    dw 0x0FFFF
    dw 0
    db 0
    db 0x92
    db 0xCF
    db 0
gdt_end:
toc:
    dw gdt_end - gdt32 - 1
    dd gdt32 

The init() function that sets the OS up (before I make an initrd, of course)

#include <kernel.h>

void init()
{
    interrupt_disable();
    terminal_init(LGREEN, BLACK);

    idt_install();
    isr_install();
    irq_install();
    interrupt_enable();
    timer_install();
    keyboard_install();
    return;
}

And of course, my kmain

#include <kernel.h>
#include <multiboot.h>

char logo[1024] = {
":::::::::::///oyhhyo//:::::::::::/:\n" \
"://////////+yNNmhysoo+////////////:\n" \
"::/://:://yNdy+//::::::+o/:://////:\n" \
"::////://sNdy+//::-:-:::++/://////:\n" \
"::::::://dmdyo/:::::--::++/::::::::\n" \
":::::::/+mdhhysoo+:/++//+y/::::::::\n" \
":::::::/oddyooo+/o//+so+/o/::::::::\n" \   
"+       =     =   + +    +    +++++     Welcome to LunaOS!\n" \
"+       =     =   +   +  +    +===+     A simple 32-bit operating system\n" \
"+       =     =   +    + +    +   +     Written soley by Safal Aryal\n" \
"++++++  = = = =   +      +    +   +     All components of this OS,\n" \
":::::::/+hhyo///+s///::/+//::::::::     are in the public domain!\n" \
"::::::://oshs+/+hdhs+/////:::::::::     (excluding the GRUB bootloader)\n" \
"::::::::/++so+shdyhys+////:::::::::     Type `help` for a list of commands\n" \
"::::::::/+o++oosso++/+/:/::::::::::\n" \
":::::::/ossssysoso+//+/:/::::::::::\n" \
":::://ohysosysso+oo/:///:::::::::::\n" \
"::::--:/ssyoshhsoo+/::+:/-:::::::::\n" \
":::-----:+shysdyo/-.`-/::--:----:::\n" \
"--::------:+sssyo/.`.:/:----::-----\n" \
"-::/:--::-::---//////--------::----\n" \
};

void kmain(multiboot_info_t *mbd, uint32_t magic)
{
    uint32_t mmap;

    if((mbd->flags >> 6) & 1) {
        mmap = mbd->mmap_addr;
    }    
    terminal_puts(logo);
    terminal_puts("SHELL> ");

    for(;;){asm volatile("sti"); asm volatile ("hlt");};
}

Thanks in advance! (Note: multiboot_info_t is defined in the Multiboot header which I use to access the memory map, a pointer to its type is passed as a parameter to kmain by pushing EBX to the stack in kernel.asm)
P.S: kvm -kernel seems to work...

0

There are 0 best solutions below