Page 2 of 2
Posted: Tue Mar 25, 2008 3:24 pm
by brickhead20
Ok, fair point.
I tried a longer string, and adding the '\0' worked.
Heres the assembly that I pinched for this
Code: Select all
[BITS 32]
global start ; making entry point visible to linker
extern main ; _main is defined elsewhere
; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
section .text
align 4
MultiBootHeader:
dd MAGIC
dd FLAGS
dd CHECKSUM
; reserve initial kernel stack space
STACKSIZE equ 0x4000 ; that's 16k.
start:
mov esp, stack+STACKSIZE ; set up the stack
push eax ; pass Multiboot magic number
push ebx ; pass Multiboot info structure
call main ; call kernel proper
hlt ; halt machine should kernel return
section .bss
align 32
stack:
resb STACKSIZE ; reserve 16k stack on a quadword boundary
Posted: Tue Mar 25, 2008 3:34 pm
by -m32
Ok, two things that may cause issues:
1) Your 'start:' appears AFTER your multiboot spec, yet you're using the linker to put start's offset at 0x100000. This would mean, the multiboot info is being loaded at 0x100000 - 6 if I'm not mistaken. So, it's not being loaded correctly.
2) You said you're using a binary output file from your linker, yet you don't have an AOUT kludge here. The AOUT kludge is required if you're using a flat binary kernel.
Try something like this:
Code: Select all
start:
mov esp, stack+STACKSIZE ; set up the stack
push eax ; pass Multiboot magic number
push ebx ; pass Multiboot info structure
call main ; call kernel proper
hlt ; halt machine should kernel return
ALIGN 4
MultiBootHeader:
dd MAGIC
dd FLAGS
dd CHECKSUM
; + AOUT kludge if kernel is flat binary
Give it a try, hope it helps. Good luck!
Posted: Tue Mar 25, 2008 3:54 pm
by brickhead20
OK, I tried both, but it does not appear to be helping. The AOUT kludge should have been there, but I still get the same error 13.
Posted: Tue Mar 25, 2008 4:34 pm
by Wave
will be null-terminated, so don't worry.
If you get an error from GRUB then something is wrong with your executable.
If you are really using binary you need to use the A.OUT kludge. However, your linker script doesn't define the output format, so it will be the default that ld was compiled with. OUTPUT_FORMAT("binary") will make it use binary. But ELF is nicer to work with, since you don't need the A.OUT kludge.
If you're using binary you need to specify the entry point in the A.OUT kludge. If it starts running from the start as it's now, the computer will try to run your multiboot header.
You should use a separate section for the multiboot header to ensure it's placed first in the file.
Posted: Tue Mar 25, 2008 4:37 pm
by -m32
I suspect that your 'binary' isn't flat binary then. Are you doing this in Windows? It could be a PE file
try
objcopy -R .note -R .comment -S -O binary <input_file> <output_file>
eg:
objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin
and then use grub to boot the output file from objcopy.
I was able to recreate your problem with a PE output file.
Posted: Tue Mar 25, 2008 5:25 pm
by -m32
Do this:
Code: Select all
[BITS 32]
global start ; making entry point visible to linker
extern main ; _main is defined elsewhere
; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
AOUT equ 1<<16 ;<-------------------------------------- NOTE
FLAGS equ MODULEALIGN | MEMINFO | AOUT ; this is the Multiboot 'flag' field <----------------------------------
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
section .text
; reserve initial kernel stack space
STACKSIZE equ 0x4000 ; that's 16k.
start:
mov esp, stack+STACKSIZE ; set up the stack
push eax ; pass Multiboot magic number
push ebx ; pass Multiboot info structure
call main ; call kernel proper
hlt ; halt machine should kernel return
align 4
MultiBootHeader:
dd MAGIC
dd FLAGS
dd CHECKSUM
; AOUT KLUDGE
extern code, bss, end
dd MultiBootHeader
dd code
dd bss
dd end
dd start
section .bss
align 32
stack:
resb STACKSIZE ; reserve 16k stack on a quadword boundary
and at the top of your linkerscript add OUTPUT_FORMAT("binary"):
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
.text 0x100000 :
{
code = .; _code = .; __code = .;
*(.text)
. = ALIGN(4096);
}
.data :
{
data = .; _data = .; __data = .;
*(.data)
*(.rodata)
. = ALIGN(4096);
}
.bss :
{
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
If the linker complains about converting a PE to binary, then, remove the 'OUTPUT_FORMAT' bit and use objcopy to convert the PE to binary 'manually'
Posted: Tue Mar 25, 2008 5:53 pm
by JJeronimo
Wave wrote: will be null-terminated, so don't worry.
Yeah. .string is one of the directives that implicitly add the C endstring.
But ELF is nicer to work with, since you don't need the A.OUT kludge.
Let me disagree with you. I think there's nothing special with declaring the entry point in the MB header. It's rather easy...........
Actually, I think it's a more proper way to format a kernel (just doesn't make sense having an executable that has 2 headers, each from it's standard). Also, it's rather stupid the idea of presenting a boot protocol aimed to facilitate the interoperability between kernels and boot loaders, and then say "here is the format. then, if you are a boot loader, you also have to learn ELF (an OS specific format)"...
Sorry if I'm telling garbage! It's rather possible that there are many arguments for the multiboot spec to preview that the boot loader supports ELF, but I don't see them...
You should use a separate section for the multiboot header to ensure it's placed first in the file.
Not needed. Because of that strange file format that MB proposes, it just needs to be in the first X KB (see the multiboot specs) of the exe image. there's a way to do this with the linker script:
Code: Select all
.text :
{
start.o(.text) /* Or something like that... */
*(.text) /* Don't accept this code as correct...*/
/*it's not likely to be so, but get the idea and see the */
} /* LD documentation (yes, I agreee with the TR;DR */
/*portion of your argument!) */
The first statement includes everything that the file "start.o" has to contribute for the .text section, and the second one includes the other .text sections (i'm really not sure whether this includes the crowd from start.o again)...
I do prefer reserving for the header it's it's own section, though...
JJ
Posted: Tue Mar 25, 2008 6:18 pm
by brickhead20
No I'm running linux.
I tried all of the above except objcopy, since the command isn't quite right. I'm toying, trying to get it right, it says "kernel.bin - File format not recognized"
The linker never complained though, so I guess its ok.
Posted: Tue Mar 25, 2008 7:12 pm
by -m32
Well, if the linker didn't complain about 'OUTPUT_FORMAT("binary")' then you won't need to use objcopy.
All you should have to do is:
nasm -f elf -o start.o start.asm
gcc -o kernel.o -c kernel.c -ffreestanding -fno-builtin
ld -Tlink.ld -o kernel.bin start.o kernel.o
That's all I did and it booted fine.
Posted: Wed Mar 26, 2008 2:25 pm
by brickhead20
That worked!
It turned out that using the elf flag in nasm did the trick. Before I had aout instead, and it didn't work.
Thanks m32, you've been really really helpful!
Now I'm interested as to why this is the case.
So why would it not work with the aout flag specified, but with the elf flag instead?
Posted: Thu Mar 27, 2008 1:20 am
by JamesM
So why would it not work with the aout flag specified, but with the elf flag instead?
Try disassembling the file - it's possible your readonly data is being put in a different section in the a.out object file and not being correctly mapped into the resulting binary executable. Using a fully expressive intermediate object file format (ELF/PE) is always recommended.
Actually, I think it's a more proper way to format a kernel (just doesn't make sense having an executable that has 2 headers, each from it's standard). Also, it's rather stupid the idea of presenting a boot protocol aimed to facilitate the interoperability between kernels and boot loaders, and then say "here is the format. then, if you are a boot loader, you also have to learn ELF (an OS specific format)"...
Sorry if I'm telling garbage! It's rather possible that there are many arguments for the multiboot spec to preview that the boot loader supports ELF, but I don't see them...
ELF is used by all UNIX operating system, so while it is specific, it's specific to an entire class/range of OS's. The advantage to a bootloader being able to understand the file format of a kernel is that it can load the extra, ancilliary sections into memory too. GRUB will load in your ELF symbol table for you, along with every other section you may need, including debug information. This is extremely useful, and much nicer than embedding the information directly in the executable (at a known location, for example).
One of the architectures I use has no support for ELF kernels, only SREC (a very similar format to raw binary). I ended up embedding my ELF kernel in the .data section of a 'third stage bootloader' SREC, parsing that embedded ELF and executing it, because that was the only way I could get all the ancilliary data I wanted.
Posted: Thu Mar 27, 2008 6:52 am
by -m32
Thanks m32, you've been really really helpful!
No problem. I'm glad it's finally working
Posted: Thu Mar 27, 2008 2:55 pm
by brickhead20
ELF does seem to be quite a bit cleaner to use. I'm going to try to use that instead.
If I start with one format, would it be relatively easy to switch to another? Presumably the file type can be to some extent abstracted quite early, so only a small amount of code would need to be changed (provided the system is sufficiently modular).
I've just GASed myself my own assembly file, to help me understand, but the a.out kludge just seems messy to me.
Clearly ELF can be "wrapped" to work on other systems then, so sufficiently flexible.
Will look into compiling to ELF file format, while writing my own linker script (ish), so I don't have to pinch yours (JamesM)! I just like to feel I understand it all enough to write it.
Thanks again
Posted: Thu Mar 27, 2008 3:14 pm
by brickhead20
Ooo, working with an elf file now I believe. And it takes less work?
Interesting.
Hopefully, C files will now work with no problems too. Rewriting from scratch.