Page 1 of 2
bkerndev 16kb+ problem
Posted: Thu Jul 07, 2005 11:30 am
by Martius
hi there,
i've done this great tutorial:
http://osdever.net/bkerndev/index.php?the_id=90
and i've built a nice and small kernel now, but i have a problem:
as soon as the kernel gets larger than 16 kb, grub does no longer want to boot it
after hours of searching i found that the multibootheader in start.asm caused the problem, because bit 0 is set in it:
Code: Select all
MULTIBOOT_PAGE_ALIGN equ 1<<0 ; align loaded modules on page boundaries
that means the code modules must stay within the page (4kb) boundaries to let grub load it, but i want to build a kernel larger than those 16kb's actually.
how do i solve it? do i need to set up paging myself? or are there any other solutions?
Re:bkerndev 16kb+ problem
Posted: Thu Jul 07, 2005 1:33 pm
by AR
I doubt that is the cause of your problem. GRUB does not set up paging for you, page align is there to make it easier for you to setup paging.
Re:bkerndev 16kb+ problem
Posted: Thu Jul 07, 2005 2:26 pm
by Tora OS
I used the same tutorial to start from and my kernel is 18 kb....
I dont think grub is the problem child here. Otherwise minilinux or whatever it is called woudnt boot. (i dont think...)
Re:bkerndev 16kb+ problem
Posted: Thu Jul 07, 2005 6:26 pm
by mystran
The alignment bit is only to tell GRUB that each module should start from a 4kb boundary. That's all it does. Modules (and kernel) can be of any size, as long as they fit in memory.
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 2:27 am
by Martius
So you guys say I'm wrong :P
Maybe this can help a bit:
This is the kernel entry point. Everything works fine. I've tested the divide by Zero Exception. And the keyboard and timer in the C-code work great.
But as I told if I make the kernel larger than 16 kb (by printing very much gibberish to the screen with main.c) it doesn't work anymore.
Is that the problem? That I try to fill the 16k's with text and not with code?
Well here's the code anyway:
Code: Select all
; start.asm
[BITS 32]
global start
start:
mov esp, _sys_stack ; This points the stack to our new stack area
jmp stublet
ALIGN 4
mboot:
MULTIBOOT_PAGE_ALIGN equ 1<<0 ; align loaded modules on page boundaries
MULTIBOOT_MEMORY_INFO equ 1<<1 ; provide memory map
MULTIBOOT_AOUT_KLUDGE equ 1<<16
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE ; this is the Multiboot 'flag' field
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
EXTERN code, bss, end
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM
; AOUT kludge - must be physical addresses. Make a note of these:
; The linker script fills in the data for these ones!
dd mboot
dd code
dd bss
dd end
dd start
stublet:
extern _main
call _main
jmp $
; This will set up our new segment registers. We need to do
; a far jump order to set CS.
; This is declared in C as 'extern void gdt_flush();'
global _gdt_flush
extern _gp
_gdt_flush:
lgdt [_gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
jmp 0x08:flush2
flush2:
ret
; Loads the IDT defined in '_idtp' into the processor.
; This is declared in C as 'extern void idt_load();'
global _idt_load
extern _idtp
_idt_load:
lidt [_idtp]
ret
global _isr0
;.... etc. (to _isr31)
; 0: Divide By Zero Exception
_isr0:
cli
push byte 0
push byte 0
jmp isr_common_stub
;.... etc.
extern _fault_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
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, _fault_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
global _irq0
;.... etc. (to _irq15)
; 32: IRQ0
_irq0:
cli
push byte 0
push byte 32
jmp irq_common_stub
;.... etc.
extern _irq_handler
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, _irq_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
; Here is the definition of our BSS section. Right now, we'll use
; it just to store the stack. Remember that a stack actually grows
; downwards, so we declare the size of the data before declaring
; the identifier '_sys_stack'
SECTION .bss
resb 8192 ; This reserves 8KBytes of memory here
_sys_stack:
and this is the linker script:
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x0100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
I've tried to change the 'phys' in the linkerscript and to align the sections with words like 8192.
But as soon as I change the ALIGN in .text to a greater value than 4096. Grub says: Error 13 invalid or unsupported executable format.
-Can I change something in the linkerscript to solve it. Like the 'phys'. Or should I change the stacksize in the kernel entry point.
-Can someone explain to me what the sections actually mean and what they're for.
-I use GRUB 0.94 and I use DJGPP 2.03
-@ Tora OS: Do you dev on Win32 or not? :P Maybe it's just m$ that causes the problem :P
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 2:45 am
by Martius
one thing I forgot to say is that I'm using Bochs 2.02
I don't think that has any effect on the process, because when I boot a floppy with my computer GRUB gives the same error
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 2:52 am
by Solar
Yes I know I'm cherry-picking.
Martius wrote:
-Can someone explain to me what the sections actually mean and what they're for.
.text holds your executable code.
.data holds values you use to initialize local variables (like the MULTIBOOT_* ones in your start.asm).
.bss is not actually part of your binary, but a number that tells the loader how much reserved, zero-initialized space your binary is requesting. (Your stack, for example.)
First thing you should do is adding *(.rodata) to your .text section. .rodata holds what global constants are initialized to; even if you don't need it now you will need it later.
Sorry that I'm only answering the easiest part of your question, but I don't have the time to delve into code details ATM. But I don't think it has something to do with alignment, either.
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 3:00 am
by AR
You're wrong there Solar, assembly does exactly what it's told the MULTIBOOT_* are part of .text as he hasn't explicitly put SECTION .data, without explicitly saying .data everything ends up in .text.
The only thing I've noticed so far is that you haven't externed all the linker variables used to make the multiboot header.
Try generating a link map for the kernel to see what values it fills in for the a.out kludge (ld .... -Map LinkMap.txt ....)
Edit: You also mentioned using strings? Add *(.rodata*) to the .text section of the linkscript
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 3:27 am
by Martius
I've added the *(.rodata*) right after *(.text) as grub-how.txt says. But it also says that that *(.rodata*) is an ELF read-only data section(s) and I use the a.out format. And when I make a linkmap it only says . = ALIGN (0x1000) at the *(.rodata*).
Even If I put many printf's in main.c.
The problem with using ELF is that ld doesn't understand the elf format from NASM.
First I'm going to add functionality to the kernel. And I hope that only pure text and not code is stressing GRUB.
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 3:33 am
by AR
GRUB doesn't read the binary, once it has the multiboot header it simply interprets it and relocates the kernel accordingly, can you post the whole linkmap? (You do not need to ask NASM for ELFs, LD can understand other INPUT formats, ELF is only the OUTPUT)
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 3:43 am
by Martius
The linkmaps were too large for this messagebox
You can find them here:
http://home.wanadoo.nl/frank.silvis/LinkMaps.txt
Thanks for all the replies yet
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 3:50 am
by Solar
AR wrote:
You're wrong there Solar, assembly does exactly what it's told the MULTIBOOT_* are part of .text as he hasn't explicitly put SECTION .data, without explicitly saying .data everything ends up in .text.
Yes, but it's the next best thing to a variable initialization seeing as there isn't any C code to comment on.
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 4:11 am
by AR
I still can't see what exactly is wrong but I have noticed another misc problem, COMMON is not accounted for by your linkscript so is being created after the BSS, add *(COMMON) to the .bss section.
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 4:19 am
by Martius
I've done that now:
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
*(COMMON)
. = ALIGN(4096);
}
Re:bkerndev 16kb+ problem
Posted: Fri Jul 08, 2005 4:31 am
by AR
What binary format are using in NASM? Did you try EXTERN-ing all the mutliboot header values?
I'm afraid I'm out of ideas, whatever it is doesn't seem very obvious.