I am using GRUB for my bootloader and it works just fine but is GRUB causing that issue and is there a way to fix that?
Here are important parts of my code:
boot.s
Code: Select all
.global idt_flush
.type idt_flush, @function
idt_flush:
movl 4(%esp), %eax #; Get the pointer to the IDT, passed as a parameter.
lidt (%eax) #; Load the IDT pointer.
ret
.global gdt_flush
.type gdt_flush, @function
gdt_flush:
#movl 4(%esp), %eax #; Get the pointer to the GDT, passed as a parameter.
#lgdt (%eax) #; Load the new GDT pointer
#mov %ax, 0x10 #; 0x10 is the offset in the GDT to our data segment
#mov %ds, ax #; Load all data segment selectors
#mov %es, ax
#mov %fs, ax
#mov %gs, ax
#mov %ss, ax
#jmp $0x08, $flush
movl 4(%esp), %eax
movl 2(%eax),%eax
movl %ax, 8(%esp)
movl %eax, ax
lgdt (%eax)
ret
.flush:
ret
.macro ISR_NOERRCODE l #; define a macro, taking one parameter
.global isr\l #; %1 accesses the first parameter.
isr\l:
cli
push 0
push \l
jmp isr_common_stub
.endm
.macro ISR_ERRCODE l
.global isr\l
isr\l:
cli
push \l
jmp isr_common_stub
.endm
#.extern isr_handler
#; This is our common ISR stub. It saves the processor state, sets
#; up for kernel mode segments, calls the C-level fault handler,
#; and finally restores the stack frame.
isr_common_stub:
pusha #; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
mov %ax, ds ##; Lower 16-bits of eax = ds.
push %eax #; save the data segment descriptor
mov %ax, 0x10 #; load the kernel data segment descriptor
mov %ds, ax
mov %es, ax
mov %fs, ax
mov %gs, ax
call isr_handler
pop %eax # ; reload the original data segment descriptor
mov %ds, ax
mov %es, ax
mov %fs, ax
mov %gs, ax
popa #; Pops edi,esi,ebp...
add %esp, 8 #; Cleans up the pushed error code and pushed ISR number
sti
iret #; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
ISR_NOERRCODE 0
ISR_NOERRCODE 1
ISR_NOERRCODE 2
ISR_NOERRCODE 3
ISR_NOERRCODE 4
ISR_NOERRCODE 5
ISR_NOERRCODE 6
ISR_NOERRCODE 7
ISR_ERRCODE 8
ISR_NOERRCODE 9
ISR_ERRCODE 10
ISR_ERRCODE 11
ISR_ERRCODE 12
ISR_ERRCODE 13
ISR_ERRCODE 14
ISR_NOERRCODE 15
ISR_NOERRCODE 16
ISR_NOERRCODE 17
ISR_NOERRCODE 18
ISR_NOERRCODE 19
ISR_NOERRCODE 20
ISR_NOERRCODE 21
ISR_NOERRCODE 22
ISR_NOERRCODE 23
ISR_NOERRCODE 24
ISR_NOERRCODE 25
ISR_NOERRCODE 26
ISR_NOERRCODE 27
ISR_NOERRCODE 28
ISR_NOERRCODE 29
ISR_NOERRCODE 30
ISR_NOERRCODE 31
reloadSegments:
JMP $0x08, $.reload_CS
.reload_CS:
MOV %AX, 0x10
MOV %DS, %AX
MOV %ES, %AX
MOV %FS, %AX
MOV %GS, %AX
MOV %SS, %AX
RET
.Stage3:
mov %ax,0x10
mov %ds,%ax
mov %ss,%ax
mov %es,%ax
mov %esp,90000
.section .text
.global _start
.type _start, @function
_start:
movl $stack_top, %esp
call kernel_early
call _init
call kernel_main
jmp gdt_flush
jmp idt_flush
cli
mov %eax, %cr0
or %eax, 1
mov %cr0, %eax
jmp $0x08, $.Stage3
cli
.Lhang:
hlt
jmp .Lhang
.size _start, . - _start
DATA32
.entergdtmode:
cli
pusha
jmp reloadSegments
jmp gdt_flush
jmp idt_flush
sti
popa
ret
.STOP:
cli
hlt
Code: Select all
.....
#include <kernel/descriptor_tables.h>
....
void kernel_main(void)
{
init_descriptor_tables();
....
}
Code: Select all
#include <kernel/graphics/common.h>
#include <kernel/descriptor_tables.h>
// Lets us access our ASM functions from our C code.
extern void gdt_flush(uint32);
extern void idt_flush(uint32);
// Internal function prototypes.
static void init_gdt();
static void init_idt();
static void gdt_set_gate(sint32,uint32,uint32,uint8,uint8);
static void idt_set_gate(uint8,uint32,uint16,uint8);
gdt_entry_t gdt_entries[5];
gdt_ptr_t gdt_ptr;
idt_entry_t idt_entries[256];
idt_ptr_t idt_ptr;
// Initialisation routine - zeroes all the interrupt service routines,
// initialises the GDT and IDT.
// Initialisation routine - zeroes all the interrupt service routines,
// initialises the GDT and IDT.
void init_descriptor_tables()
{
// Initialise the global descriptor table.
init_gdt();
init_idt();
}
static void init_gdt()
{
gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
gdt_ptr.base = (uint32)&gdt_entries;
gdt_set_gate(0, 0, 0, 0, 0); // Null segment
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment
gdt_flush((uint32)&gdt_ptr);
}
// Set the value of one GDT entry.
static void gdt_set_gate(sint32 num, uint32 base, uint32 limit, uint8 access, uint8 gran)
{
gdt_entries[num].base_low = (base & 0xFFFF);
gdt_entries[num].base_middle = (base >> 16) & 0xFF;
gdt_entries[num].base_high = (base >> 24) & 0xFF;
gdt_entries[num].limit_low = (limit & 0xFFFF);
gdt_entries[num].granularity = (limit >> 16) & 0x0F;
gdt_entries[num].granularity |= gran & 0xF0;
gdt_entries[num].access = access;
}
static void init_idt()
{
idt_ptr.limit = sizeof(idt_entry_t) * 256 -1;
idt_ptr.base = (uint32)&idt_entries;
memset(&idt_entries, 0, sizeof(idt_entry_t)*256);
idt_set_gate( 0, (uint32)isr0 , 0x08, 0x8E);
idt_set_gate( 1, (uint32)isr1 , 0x08, 0x8E);
idt_set_gate( 2, (uint32)isr2 , 0x08, 0x8E);
idt_set_gate( 3, (uint32)isr3 , 0x08, 0x8E);
idt_set_gate( 4, (uint32)isr4 , 0x08, 0x8E);
idt_set_gate( 5, (uint32)isr5 , 0x08, 0x8E);
idt_set_gate( 6, (uint32)isr6 , 0x08, 0x8E);
idt_set_gate( 7, (uint32)isr7 , 0x08, 0x8E);
idt_set_gate( 8, (uint32)isr8 , 0x08, 0x8E);
idt_set_gate( 9, (uint32)isr9 , 0x08, 0x8E);
idt_set_gate(10, (uint32)isr10, 0x08, 0x8E);
idt_set_gate(11, (uint32)isr11, 0x08, 0x8E);
idt_set_gate(12, (uint32)isr12, 0x08, 0x8E);
idt_set_gate(13, (uint32)isr13, 0x08, 0x8E);
idt_set_gate(14, (uint32)isr14, 0x08, 0x8E);
idt_set_gate(15, (uint32)isr15, 0x08, 0x8E);
idt_set_gate(16, (uint32)isr16, 0x08, 0x8E);
idt_set_gate(17, (uint32)isr17, 0x08, 0x8E);
idt_set_gate(18, (uint32)isr18, 0x08, 0x8E);
idt_set_gate(19, (uint32)isr19, 0x08, 0x8E);
idt_set_gate(20, (uint32)isr20, 0x08, 0x8E);
idt_set_gate(21, (uint32)isr21, 0x08, 0x8E);
idt_set_gate(22, (uint32)isr22, 0x08, 0x8E);
idt_set_gate(23, (uint32)isr23, 0x08, 0x8E);
idt_set_gate(24, (uint32)isr24, 0x08, 0x8E);
idt_set_gate(25, (uint32)isr25, 0x08, 0x8E);
idt_set_gate(26, (uint32)isr26, 0x08, 0x8E);
idt_set_gate(27, (uint32)isr27, 0x08, 0x8E);
idt_set_gate(28, (uint32)isr28, 0x08, 0x8E);
idt_set_gate(29, (uint32)isr29, 0x08, 0x8E);
idt_set_gate(30, (uint32)isr30, 0x08, 0x8E);
idt_set_gate(31, (uint32)isr31, 0x08, 0x8E);
idt_flush((uint32)&idt_ptr);
}
static void idt_set_gate(uint8 num, uint32 base, uint16 sel, uint8 flags)
{
idt_entries[num].base_lo = base & 0xFFFF;
idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
idt_entries[num].sel = sel;
idt_entries[num].always0 = 0;
// We must uncomment the OR below when we get to using user-mode.
// It sets the interrupt gate's privilege level to 3.
idt_entries[num].flags = flags /* | 0x60 */;
}
Code: Select all
#include <kernel/graphics/common.h>
// Initialisation function is publicly accessible.
void init_descriptor_tables();
// This structure contains the value of one GDT entry.
// We use the attribute 'packed' to tell GCC not to change
// any of the alignment in the structure.
struct gdt_entry_struct
{
uint16 limit_low; // The lower 16 bits of the limit.
uint16 base_low; // The lower 16 bits of the base.
uint8 base_middle; // The next 8 bits of the base.
uint8 access; // Access flags, determine what ring this segment can be used in.
uint8 granularity;
uint8 base_high; // The last 8 bits of the base.
} __attribute__((packed));
typedef struct gdt_entry_struct gdt_entry_t;
// This struct describes a GDT pointer. It points to the start of
// our array of GDT entries, and is in the format required by the
// lgdt instruction.
struct gdt_ptr_struct
{
uint16 limit; // The upper 16 bits of all selector limits.
uint32 base; // The address of the first gdt_entry_t struct.
} __attribute__((packed));
typedef struct gdt_ptr_struct gdt_ptr_t;
// A struct describing an interrupt gate.
struct idt_entry_struct
{
uint16 base_lo; // The lower 16 bits of the address to jump to when this interrupt fires.
uint16 sel; // Kernel segment selector.
uint8 always0; // This must always be zero.
uint8 flags; // More flags. See documentation.
uint16 base_hi; // The upper 16 bits of the address to jump to.
} __attribute__((packed));
typedef struct idt_entry_struct idt_entry_t;
// A struct describing a pointer to an array of interrupt handlers.
// This is in a format suitable for giving to 'lidt'.
struct idt_ptr_struct
{
uint16 limit;
uint32 base; // The address of the first element in our idt_entry_t array.
} __attribute__((packed));
typedef struct idt_ptr_struct idt_ptr_t;
// These extern directives let us access the addresses of our ASM ISR handlers.
extern void isr0 ();
extern void isr1 ();
extern void isr2 ();
extern void isr3 ();
extern void isr4 ();
extern void isr5 ();
extern void isr6 ();
extern void isr7 ();
extern void isr8 ();
extern void isr9 ();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
Sorry for long post I don't know how to make a [spoiler] on this forum.