Page 1 of 1

booting a simple kernel with grub

Posted: Mon Jun 11, 2007 4:22 pm
by anon19287473
I pulled together a small kernel, which sets up a gdt and prints some stuff on the screen, and it is a valid multboot elf file, which grub recognizes, however, when I boot it, I don't see the character being printed, I've attached the code. I've tried everything I can think of, I just can't figure out the problem. (Note, this is my first attempt at a protected mode OS, cut me some slack if its a stupid mistake).

EDIT: I've also attached the ld script I used.

I compiled it with the following commands:

Code: Select all

nasm -f elf -o kernel.o kernel.asm
ld -T kernel.ld kernel.o
Thanks in advance.

Posted: Tue Jun 12, 2007 1:28 am
by Combuster
The problem is probably here:

Code: Select all

mov word [gs:0xb800], 0x641
I think you confused realmode segments with linear offsets. The correct address is

Code: Select all

mov word [gs:0xb8000], 0x641

Posted: Tue Jun 12, 2007 9:29 am
by anon19287473
Thanks, I'll try that. Still getting used to the whole protected mode thing :)

Posted: Tue Jun 12, 2007 4:46 pm
by anon19287473
Nope :( , it still does't work. Any other ideas?

Posted: Tue Jun 12, 2007 5:18 pm
by jnc100
Your gdt is wrong:

Code: Select all

gdt:
	;; NULL descriptor
	TIMES 8 db 0

	;; Unused descriptor
	TIMES 9 db 0
the second one I guess is a typo, try TIMES 8 db 0 like previously.

Also,

Code: Select all

DATA_SEL equ $-gdt
	dw 0xffff
	dw 0
	db 0
	db 0x92
	db 0xcf
	db 0
DATA_SEL isn't the correct selector for that descriptor - you need to use, as its the third entry (entry number 2 in a zero-based list):

2 << 3 + RPL, where I assume RPL for you is 0
= 0x10

Plus keep the fix Combuster posted.

Regards,
John.

Posted: Tue Jun 12, 2007 6:04 pm
by anon19287473
I made those changes and it still won't work :(

Code: Select all

[BITS 32]
section .text
global start
start:
	; mov esp, sys_stack
	
	lgdt [gdtr]
	mov ax, DATA_SEL
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov fs, ax
	mov gs, ax

	mov word [gs:0xb8000], 0x641
	
	jmp $
	
	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
	CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

	;; The Multiboot header
	align 4 
	dd MULTIBOOT_HEADER_MAGIC
	dd MULTIBOOT_HEADER_FLAGS
	dd CHECKSUM

section .data

[BITS 16]
	
gdtr:
	dw gdt_end - gdt - 1
	dd gdt

gdt:
;; NULL descriptor
	dw 0
	dw 0
	db 0
	db 0
	db 0
	db 0	

;; Unused descriptor
	dw 0
	dw 0
	db 0
	db 0
	db 0
	db 0

CODE_SEL equ $-gdt
	dw 0xFFFF
	dw 0
	db 0
	db 0x9A
	db 0xCF
	db 0

DATA_SEL equ $-gdt
	dw 0xFFFF
	dw 0
	db 0
	db 0x92
	db 0xCF
	db 0
gdt_end:

[BITS 32]
		
SECTION .bss
	resb 8192		; Reserve 8KBytes of memory for the stack
sys_stack:
With the same linker script. Note: I wrote out the empty GDT sels, to avoid similar problems :)

Posted: Wed Jun 13, 2007 3:23 am
by jnc100
Just noted in your linker script you're relocating to 0xc0000000. This means that the executable you're creating is expecting to be run at address 0xC0000000, whereas by the AT directive you're informing grub to actually load the sections at 0x100000. This means the memory access to load your gdt is wrong.

If you really want a higher half kernel, I suggest you follow the instructions in Higher Half With GDT. You'll note that it defines a special section in the output, called .setup, which contains the gdt to be loaded, and specifies both the virtual and physical addresses to be at 1MB, whereas the rest of the sections (.text, .data and .bss) are loaded above 1MB but relocated to above 0xc0000000.

Regards,
John.