lgdt not working, mov cr0, eax causing triple fault.

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
XeonX369
Member
Member
Posts: 29
Joined: Mon Sep 28, 2009 1:12 pm

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by XeonX369 »

Ok, the size of my kernel file is 38364 bytes. I don't know how correct that this is, as the kernel only contains a simple instruction for writing to the screen and to clear it (which is 1128 bytes by itself), and the "pre-kernel" is simply there to jump into the main kernel, and it comes to 89 bytes. Does the linking precess add a bunch of junk to a binary file? The linker is told to output to a binary in the configuration file passed to it.

OK, so I guess the real question of the day is... how would I load all 72 sectors of the kernel into memory using Interupt 13h. I would probably have to pass the int 13h command multiple times, with different parameters corresponding to the multiple cylinders and heads. Having multiple, fixed value disk reading functions will not be that large of a deal for now, until I implement a simple file system, because I only ever plan to use this with my own (and current) kernel.
Last edited by XeonX369 on Wed Jan 27, 2010 3:36 pm, edited 1 time in total.
Selenic
Member
Member
Posts: 123
Joined: Sat Jan 23, 2010 2:56 pm

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by Selenic »

briandknopp wrote:Ok, the size of my kernel file is 38364 bytes. I don't know how correct that this is, as the kernel only contains a simple instruction for writing to the screen and to clear it (which is 1128 bytes by itself)
That's a bit weird; any idea *why* it's so big? (How are you linking it? Where are your sections linked to? Looking at those might help to see where your problem is)
Considering the size, I imagine that the start of the file isn't your executable code, so you might have hit a ton of NULs or whatever, which helpfully don't correspond to NOPs in x86)
XeonX369
Member
Member
Posts: 29
Joined: Mon Sep 28, 2009 1:12 pm

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by XeonX369 »

Selenic wrote:That's a bit weird; any idea *why* it's so big? (How are you linking it? Where are your sections linked to? Looking at those might help to see where your problem is)
Considering the size, I imagine that the start of the file isn't your executable code, so you might have hit a ton of NULs or whatever, which helpfully don't correspond to NOPs in x86)
The way that I call ld is as so:

Code: Select all

ld -nostdlib -nodefaultlibs -T ./link.ld -o ../Binaries/kernel.xix ../Binaries/prekernel.krnl ../Binaries/kernel.krnl
where link.ld is my linker script, kernel.xix is my output file, and the remaining files are the 'pre-kernel' and kernel themselves.

Yes, I am compiling my base kernel with all the -nodefault(insert name here) options.

My linker script is as so:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(loader)
SECTIONS
{
  .text  0x8200 : {
    code = .; _code = .; __code = .;
    *(.text)
    . = ALIGN(4096);
  }
  .data  : {
    data = .; _data = .; __data = .;
    *(.data)
    . = ALIGN(4096);
  }
  .bss  :
  {
    bss = .; _bss = .; __bss = .;
    *(.bss)
    . = ALIGN(4096);
  }
  end = .; _end = .; __end = .;
}
My 'pre-kernel' and kernel code is attached. OK, back to the internet for a solution.
Attachments
prekernel.asm
Pre-Kernel
(685 Bytes) Downloaded 106 times
kernel.c
Kernel
(3.09 KiB) Downloaded 113 times
Last edited by XeonX369 on Thu Jan 28, 2010 11:41 am, edited 1 time in total.
XeonX369
Member
Member
Posts: 29
Joined: Mon Sep 28, 2009 1:12 pm

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by XeonX369 »

OK, I tried getting the kernel into ELF format, primarily by changing the output of the pre-kernel to output to standard elf. Apparently, the old aout format just bloats the file, and I can't use binary, because I get an error message about lack of support for external files (even with an underscore in the function name).

Why does Aout bloat the file?
User avatar
~
Member
Member
Posts: 1228
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by ~ »

What error do you get?

These are the commands I use to build the kernel (first compile the C file to an object file, then the ASM file to an AOUT object, and finally call the linker script):

Code: Select all

gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -c -o kernel.o kernel.c



nasm -f aout -o start.o prekernel.asm



ld -T link.ld -o kernel.bin prekernel.o kernel.o

This also seemed to be an error:

Code: Select all

	for( x = 10; x = x; x++ ) {	//UNRECOVERABLE LOOP
It should be (note the "x == x"; otherwise you aren't comparing but assigning a value):

Code: Select all

	for( x = 10; x == x; x++ ) {	//UNRECOVERABLE LOOP
Also, remember to properly set up DS, ES, FS, GS, SS, ESP, etc., before executing the kernel (at first it didn't display anything).

And I insist in that you should load your kernel at 0x100000 (a place just away from the confusion of the Real Mode space), or you will run over reserved memory if you load at 0x8200, but that's only an advice. If you ever note your kernel failing, the machine locking or whatever, take into account that it may be due to the fact that you might be overwritting reserved memory.

I'm using "GCC 3.4.6" and "ld 2.15.92.0.2, 2004-09-27".

Here I have attached the resulting object files, the kernel.bin file and modified versions of the source code, mainly for correcting the error above and changing the linker script so it links to 0x100000 instead of 0x8200.
Attachments
link.zip
(3.38 KiB) Downloaded 90 times
User avatar
Combuster
Member
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: lgdt not working, mov cr0, eax causing triple fault.

Post by Combuster »

briandknopp wrote:Why does Aout bloat the file?
Short answer: Because it sucks and is outdated and you really should not be using it.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by jal »

Combuster wrote:Short answer
No, that's the easy answer :).
Because it sucks and is outdated and you really should not be using it.
QFT.


JAL
XeonX369
Member
Member
Posts: 29
Joined: Mon Sep 28, 2009 1:12 pm

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by XeonX369 »

~,
The error I get:

Code: Select all

prekernel.asm:27: error: binary output format does not support external references
The resulting kernel.bin file in your packaging is quite small in size, about 4KB. Whereas, if I replicate this process using your modified source files, with the specified commands, my file is quite huge. I suspect that this has something to do with the version of ld. This size difference is ridiculous.

If I use your kernel.bin with my bootloader, the problem persists with the continued triple-faulting. I guess that it wasn't the kernel, but it still appears to be in the loader. This is absolutely crazy, and I just wish I could get to the bottom of this. I suspect that it is the jmp instruction, although I just don't know why.
briandknopp wrote:
Why does Aout bloat the file?
Short answer: Because it sucks and is outdated and you really should not be using it.
Combuster, I appreciate your knowledge of this situation. In this case, what sort of executable format should I be using? Elf?
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by jal »

XeonX369 wrote:what sort of executable format should I be using? Elf?
ELF is preferred over about anything else. It is well documented, and well supported. Native GRUB support, easy to parse yourself, relatively easy to add your own segments, etc. etc.


JAL
XeonX369
Member
Member
Posts: 29
Joined: Mon Sep 28, 2009 1:12 pm

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by XeonX369 »

OK, I have switched my pre-kernel file to be output to ELF. The final kernel file comes out to 7KB. So, I set my bootloader to load the 15 segments of floppy necessary for the loading of the kernel. The bootloader still does not work. It continues on to the jump instruction, and then it tripple faults.

~, I have given your bootsector and loader a try, and have found it to work. If I wanted to just use your bootsector to load my kernel, could I just substitute the "bootloader" functions and place them into the 'pre-kernel' file (eg, A20, GDT, PMode)? This would then be linked to the kernel itself. In all effect, the kernel would be loaded directly from the bootsector, with the linked pre-kernel acting as the "bootloader" that I have now.
User avatar
~
Member
Member
Posts: 1228
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by ~ »

The easiest way of doing things in that respect maybe would be to replicate the most important things into the second stage bootloader.

The sample bootsector tries to set up the A20 line through the keyboard controller, sets up Unreal Mode so now you are able to load the kernel above the 1MB mark (you can now reach 0x100000 and above).


I have attached a bootsector that I think is like the previous ones, and have also attached a second stage bootloader.

This bootloader tries again to enable the A20 line through several methods (keyboard controller, BIOS and Fast A20), but not without first testing if it's already enabled.

It also duplicates the small FAT12 code so now you can add other things to this bootloader before jumping to the kernel.

You must name this second stage bootloader, "LOADER.BIN" and the kernel "KERNEL.BIN" (you can change it in the source code).

Your second stage bootloader is loaded always at 8000h:0000h, so it has about 120KB of memory that you can use to gather things like the memory map, maybe some peripheral detection, some option you could implement to boot from a device other than the floppy (it is an advanced feature which is not implemented at all in this sample) and/or set up a graphics mode -- among many other things.

Your bootloader can use RAM from 80000h to 9FBFFh. If you use memory outside that region, with the current setup of loading it at 8000h:0000h, you will make a mistake.

The KERNEL.BIN file is loaded at 0x100000, and is a 32-bit protected mode image (you can reload your own GDT and other structures from your kernel to replace the ones used by the bootloader).

As you can see, both these bootsector and bootloader can now read from a FAT12 floppy since they duplicate the same FAT12 reading code and the second stage bootloader accesses the FAT12 fields located at 7C00h.

The code still needs a lot of cleanup, mainly to make the FAT12 code more ordered (it is optimized to be extremely compact, sacrificing simplicity) but it's a good start for being able to have a first and second stage bootloaders, both capable of reading the files from a standard FAT12 floppy that can be read and used under Windows.

If you wonder what's good about that, it is that as you know, 512 bytes of boot code aren't enough, so the second stage bootloader allows you to take advantage of BIOS calls, which will allow you to get many important pieces of information about your PC. If you made a 512-byte bootsector that jumped directly to a 32-bit kernel, you couldn't use the BIOS (not without heavy emulation on your own) and that would get your kernel rather lost in an unknown hardware environment.

So the configuration of memory for these programs is like this:

Code: Select all

7C00h   -- FAT12 bootsector
8000h   -- FAT tables read from disk
40000h  -- temporary sector-at-once buffer
80000h  -- second stage bootloader
100000h -- kernel image
The DL register will be set by the bootsector to the original drive number we were booted from just before jumping to the second stage.


You need to install the bootsector to the floppy, and copy to it (preferably empty) the files LOADER.BIN and KERNEL.BIN.

The KERNEL.BIN file included is the previous one, unchanged.

This bootsector program in general is very fragile because each instruction depends greatly on the results of the previous one(s) to reduce as much as possible the waste of space and try to do an "extreme" optimization, so it isn't easy to modify it arbitrarily without a lot of care.


Maybe I should suggest that you should first fully understand FAT filesystems and all of the code presented until now, which should now be able to pass control to 2nd stage and from there to a 32-bit kernel. Otherwise, there could be a chance of like 90% that you will make many failed kernel attempts which will span a lot of time.

Using an attempt of a kernel is a inconvenient choice if you still need to find out how the hardware works, it's a very deserted environment when you have entered Protected Mode and don't have yet available any way to use the 16-bit Real Mode code of the BIOS or useable drivers. When something about your low level design considerations don't fit with the hardware setup, it will cause bugs that will require you to start from scratch (or almost).
Attachments
2stages.zip
(10.29 KiB) Downloaded 125 times
XeonX369
Member
Member
Posts: 29
Joined: Mon Sep 28, 2009 1:12 pm

Re: lgdt not working, mov cr0, eax causing triple fault.

Post by XeonX369 »

I thank everyone who contributed to this thread here. I believe that my question has been answered and my problems (for now) have been solved. I will try to implement some sort of a basic FAT type file system for the disk (or maybe ext2), until I am ready to do a true build, using the files provided here. This will allow me to do some more hardware research and read more manuals, while doing kernel development of my own.

Many thanks, once again, to all who contributed.
Post Reply