Help with linker on bare-bones
Help with linker on bare-bones
I am following the first bare bones tutorial on the wiki. I am using DJGPP on Windows (I like linux, but it doesn't have drivers for my ethernet card (can't get ndiswrapper to work either)).
The source files and linker files are identical to those in the tutorial. I had to remove the -Werror flag to get the C to compile, but otherwise am using the exact commands described in the tutorial. Everything compiles fine, but when I link I get this error:
>ld -T linker.ld -o kernel.bin loader.o kernel.o
loader.o: file not recognized: File format not recognized
How can I get this to link?
The source files and linker files are identical to those in the tutorial. I had to remove the -Werror flag to get the C to compile, but otherwise am using the exact commands described in the tutorial. Everything compiles fine, but when I link I get this error:
>ld -T linker.ld -o kernel.bin loader.o kernel.o
loader.o: file not recognized: File format not recognized
How can I get this to link?
Re: Help with linker on bare-bones
Bad Sign. Do not allow your code to compile with any warnings - they are there for a reason.Anubis208 wrote:I had to remove the -Werror flag to get the C to compile
You need a GCC Cross-Compilerloader.o: file not recognized: File format not recognized
Cheers,
Adam
Re: Help with linker on bare-bones
Here are the warnings I get
>gcc -o kernel.o -c kernel.c -Wall -Wextra -Werror -nostdlib -nostartfiles -nodefaultlibs
cc1.exe: warnings being treated as errors
kernel.c:1: warning: unused parameter 'mbd'
kernel.c:1: warning: unused parameter 'magic'
I think its because I don't use the arguments to kmain?
Also I'm kind of new to the whole command line copiling thing.
Your saying its the linker that's the problem and it doesn't recognize the ELF from the assembler?
If so, could I just get a cross-platform linker instead of building the whole GCC?
>gcc -o kernel.o -c kernel.c -Wall -Wextra -Werror -nostdlib -nostartfiles -nodefaultlibs
cc1.exe: warnings being treated as errors
kernel.c:1: warning: unused parameter 'mbd'
kernel.c:1: warning: unused parameter 'magic'
Code: Select all
void kmain( void* mbd, unsigned int magic)
{
unsigned char *videoram = (unsigned char *)0xB80000;
videoram[0] = 76;
videoram[1] = 0x07;
}
I think its because I don't use the arguments to kmain?
Also I'm kind of new to the whole command line copiling thing.
Your saying its the linker that's the problem and it doesn't recognize the ELF from the assembler?
If so, could I just get a cross-platform linker instead of building the whole GCC?
Re: Help with linker on bare-bones
Hi,
AFAIK, you can just build cross-binutils, which will provide you with the compatible ld, but my personal recommendation would be that if you are installing Cygwin and building binutils anyway, you may as well go the whole way and build yourself a cross-compiled version of GCC. It's what many people are using on the forums and if you hit problems later people are more likely to be able to help on this forum.
If you remove the parameter names from main a la:
You can keep -Werror turned on and just add the param names later when you need them. This way, GCC will continue to treat other warnings as errors.
Cheers,
Adam
AFAIK, you can just build cross-binutils, which will provide you with the compatible ld, but my personal recommendation would be that if you are installing Cygwin and building binutils anyway, you may as well go the whole way and build yourself a cross-compiled version of GCC. It's what many people are using on the forums and if you hit problems later people are more likely to be able to help on this forum.
If you remove the parameter names from main a la:
Code: Select all
void kmain( void*, unsigned int)
{
...
}
Cheers,
Adam
Re: Help with linker on bare-bones
I use MinGW for compiling on Windows. It's not the easiest compiler in the world to get set up but it does work very well. Its LD will accept ELF object files from the assembler.Your saying its the linker that's the problem and it doesn't recognize the ELF from the assembler?
If so, could I just get a cross-platform linker instead of building the whole GCC?
It only seems to build Windows PE format executables unfortunately, but this does not matter since GRUB will look for the Multiboot header and use that for loading it. You could also write a script to strip the PE header off the output executable file, possibly rearranging the sections into a new executable format, if you don't want it (which is what I did).
Re: Help with linker on bare-bones
I have Dev-Cpp installed on my computer. Is there any way I could use Mingw from that?
Re: Help with linker on bare-bones
Yup that's what I do, there is a gcc mingw compiler in the \bin\ of your dev-c++ directory, it works exactly like any other gcc compiler and you can use it in your command line to build you C/C++ files for your OS...
Jules
edit: the only problem with that is the gcc compiler that comes with even the newest version of dev-c++ is antiquated, but it still works, I've got the newest version and it comes with gcc 3.4.2...
Jules
edit: the only problem with that is the gcc compiler that comes with even the newest version of dev-c++ is antiquated, but it still works, I've got the newest version and it comes with gcc 3.4.2...
Re: Help with linker on bare-bones
Just a comment on that cross compiler guide aj linked, well I hadnt ever built a cross compiler before and I went through that guide and managed to get one built.It is a good guide and helped my understanding a fair bit.
Re: Help with linker on bare-bones
I downloaded the MinGW linker and replaced the DJGPP linker with it. Now I can link my kernel.
Now I have found another problem. I made the pad file using this assembly
and when assembled it made the file 750 bytes. Then I used the copy command to put the files together
copy /B stage1+stage2+pad+kernel.bin floppy.img
and got my img file. I then booted it using Qemu. It booted fine, but when I typed
kernel 200+8 at the GRUB prompt, it froze.
I got it to work with Bochs, but when I type kernel 200+8 it says
grub> kernel 200+8
Error 13: Invalid or unsupported executable format
grub>
Now I have found another problem. I made the pad file using this assembly
Code: Select all
times 750 db '.'
copy /B stage1+stage2+pad+kernel.bin floppy.img
and got my img file. I then booted it using Qemu. It booted fine, but when I typed
kernel 200+8 at the GRUB prompt, it froze.
I got it to work with Bochs, but when I type kernel 200+8 it says
grub> kernel 200+8
Error 13: Invalid or unsupported executable format
grub>
Re: Help with linker on bare-bones
"Error 13: Invalid or unsupported executable format" means GRUB couldn't either find or understand the Multiboot header, or the exe format. I got that message a lot until I read the Multiboot docs properly. In your case, the issue is that MinGW generates PE files, and GRUB can only boot ELF or Multiboot "a.out kludge" files. (The tutorial is aimed primarily at those compiling on Linux).
If you read the Multiboot docs, it explains that for other kernel formats you need to include the address fields flag (value 0x00010000) in the flags field, and specify the header_addr, load_addr, load_end_addr, bss_end_addr, and entry_addr fields in the header. (Notice that currently, you've not told GRUB where to actually put your kernel in memory.)
Don't worry it's not as hard as it sounds. Here's the header and entry code I use, (originally based on the bare bones tutorial in the wiki):
On a semi-related note, I'm not sure I agree with how the bare bones tutorial loads the kernel into the floppy image. Seems a bit error prone, and reliant on exact file sizes of a certain version of GRUB. From what I've read, the easiest way on Windows is to use something like Filedisk or Virtual Floppy Disk to mount the floppy image to a drive letter, copy the kernel file onto it the usual way, and unmount it back to a disk image so the emulator can read it. Beautifully, this can be done in a command line *.bat file to automate it as part of the compilation process. This makes it possible to include other OS files later, and to *automate* the GRUB command to load the kernel with a menu.cfg file. (Actually, I didn't know about these disk programs when I started, so I wrote a PHP script to open the floppy image file and interpret a FAT filesystem within it, to manipulate the files in it directly. Works but it's very complicated!)
If you read the Multiboot docs, it explains that for other kernel formats you need to include the address fields flag (value 0x00010000) in the flags field, and specify the header_addr, load_addr, load_end_addr, bss_end_addr, and entry_addr fields in the header. (Notice that currently, you've not told GRUB where to actually put your kernel in memory.)
Don't worry it's not as hard as it sounds. Here's the header and entry code I use, (originally based on the bare bones tutorial in the wiki):
Code: Select all
global _multiboot_header
global _multiboot_entry
extern _kmain
; setting up the Multiboot header - see GRUB docs for details
align 4
_multiboot_header:
MAGIC equ 0x1BADB002
FLAGS equ 0x00010002 ; MMAP + AOUT KLUDGE
magic dd MAGIC
flags dd FLAGS
checksum dd 0 - (FLAGS + MAGIC)
header_addr dd _multiboot_header
load_addr dd _multiboot_header
load_end_addr dd 0
bss_end_addr dd 0
entry_addr dd _multiboot_entry
_multiboot_entry:
mov esp, 0x00020000 ; set up the stack somewhere in low memory
push eax ; pass Multiboot magic number
push ebx ; pass Multiboot info structure
mov edx, 0x3f2 ; turn off the floppy drive before we enter the kernel
mov al, 0x0c
out dx, al
call _kmain ; call kernel proper
Re: Help with linker on bare-bones
That method didn't work.
I get this when I link:
ld: warning: cannot find entry symbol _loader; defaulting to 00100000
is that normal?
All I want to do is boot a kernel and have A20 and PMode enabled by the loader. If anyone could direct me to another bootloader that could do that, that would work too.
edit: I did the math and the pad puts my kernel at sector 200.
I get this when I link:
ld: warning: cannot find entry symbol _loader; defaulting to 00100000
is that normal?
All I want to do is boot a kernel and have A20 and PMode enabled by the loader. If anyone could direct me to another bootloader that could do that, that would work too.
edit: I did the math and the pad puts my kernel at sector 200.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Help with linker on bare-bones
Well the common way to use grub is to install it to a FAT-formatted floppy, then copy over the kernel to the disk like any other file.
There are several images containing FAT+GRUB around - if you have linux with grub installed you can make your own. Go have a look as it makes those things a lot easier.
There are several images containing FAT+GRUB around - if you have linux with grub installed you can make your own. Go have a look as it makes those things a lot easier.
Re: Help with linker on bare-bones
Does anyone know of another bootloader that enables A20 and PMode?
GRUB just doesn't seem to be made for me.
GRUB just doesn't seem to be made for me.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Help with linker on bare-bones
Write your own.
Re: Help with linker on bare-bones
Can you direct me to a tutorial that describes how to do it (I have already attempted several times without success)?