Page 1 of 2
GRUB and protected mode
Posted: Sat May 28, 2005 5:49 pm
by Travfar
Hi!
I am using GRUB to set up my kernel, which I wrote in C. I am currently using GRUB to boot it and I wanted to know if GRUB stes up the GDT. I also wanted to know if I could change the address of the GDT in the middle of my kernel.
Travfar
Re:GRUB and protected mode
Posted: Sat May 28, 2005 6:02 pm
by pini
When your kernel is executed, GRUB has already set up protected mode (and thus the GDT) , but it is highly recommended to load your own GDT. See the multiboot specification for more details on the machine state GRUB sets.
I guess you can change the address of the GDT anywhere in your kernel, but make sure to reload all the selectors to modified descriptors.
Re:GRUB and protected mode
Posted: Mon May 30, 2005 5:06 am
by srg
AFAIK the GDT that GRUB sets up is only really for it's own uses and as far as the kernel is concerned it's "undefined". So it's best to make your own.
srg
Re:GRUB and protected mode
Posted: Mon May 30, 2005 8:42 am
by travfar
Hi! Another question.
I have written and borrowed some functions to load the new GDT. However, when I load the new selectors into the segment registers, the computer just reboots right when I boot my kernel.
here is the code:
gdt.c:
Code: Select all
#include "kernel.h"
//this is a GDT entry
struct gdt_entry
{
unsigned short limit_low;
unsigned short base_low;
unsigned short base_middle;
unsigned short access;
unsigned short granularity;
unsigned short base_high;
} __attribute__((packed));
// This is the GDT pointer
struct gdt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
//define the GDT
struct gdt_entry gdt[3];
struct gdt_ptr gp;
extern void gdt_flush();
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
gdt[num].base_low=(base & 0xFFFF);
gdt[num].base_middle=(base >> 16) & 0xFF;
gdt[num].base_high=(base >> 24) & 0xFF;
//descriptor limits
gdt[num].limit_low=(limit & 0xFFFF);
gdt[num].granularity = ((limit >>16) & 0x0f);
//limits
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
};
void gdt_install()
{
const char* message="Loading new GDT. Well Flush isnt really there yet ;)\0";
k_printf(message,1,WHITE_TXT);
gp.limit=(sizeof(struct gdt_ptr) *3)-1;
gp.base=(unsigned int)&gdt;
gdt_set_gate(0,0,0,0,0);
gdt_set_gate(1,0,0xffffffff,0x9a,0xcf);
gdt_flush();
};
void gdt_flush_alert()
{
const char* message="Flushing GDT now!";
k_printf(message,2,WHITE_TXT);
};
asmfunc.asm:
Code: Select all
[BITS 32]
[global gdt_flush]
[extern gp]
[extern gdt_flush_alert]
gdt_flush:
call gdt_flush_alert
lgdt [gp]
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
jmp 0x08:flush2
flush2:
ret
IF i do not load the segment registers, then it does not just reboot. kernel.h defines k_printf and WHITE_TXT
P.S. the functions I borrowed were in the public domain.
Re:GRUB and protected mode
Posted: Mon May 30, 2005 10:08 am
by travfar
SOrry!
gdt.c should be:
Code: Select all
#include "kernel.h"
//this is a GDT entry
struct gdt_entry
{
unsigned short limit_low;
unsigned short base_low;
unsigned short base_middle;
unsigned short access;
unsigned short granularity;
unsigned short base_high;
} __attribute__((packed));
// This is the GDT pointer
struct gdt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
//define the GDT
struct gdt_entry gdt[3];
struct gdt_ptr gp;
extern void gdt_flush();
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
gdt[num].base_low=(base & 0xFFFF);
gdt[num].base_middle=(base >> 16) & 0xFF;
gdt[num].base_high=(base >> 24) & 0xFF;
//descriptor limits
gdt[num].limit_low=(limit & 0xFFFF);
gdt[num].granularity = ((limit >>16) & 0x0f);
//limits
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
};
void gdt_install()
{
const char* message="Loading new GDT. Well Flush isnt really there yet ;)\0";
k_printf(message,1,WHITE_TXT);
gp.limit=(sizeof(struct gdt_ptr) *3)-1;
gp.base=(unsigned int)&gdt;
gdt_set_gate(0,0,0,0,0);
gdt_set_gate(1,0,0xffffffff,0x9a,0xcf);
gdt_set_gate(2,0,0xffffffff,0x92,0xcf);
gdt_flush();
};
void gdt_flush_alert()
{
const char* message="Flushing GDT now!";
k_printf(message,2,WHITE_TXT);
};
Re:GRUB and protected mode
Posted: Mon May 30, 2005 11:56 am
by Warrior
From personal experience I suggest you learn how the GDT works and the vast ways it can be implemented to suit your individual design's needs.
I had the problem of using "cut n paste" code before and trust be it was bad..there are a lot of articles on how the GDT works and it's implementation floating around. I think the one I found was on osdcom.info in one of the protected mode tutorials.
Good luck.
Re:GRUB and protected mode
Posted: Mon May 30, 2005 1:54 pm
by travfar
You know, I did not just copy from a tutorial and put it in my code. An anyway, I found out what was wrong.
first of all there should only be two unsigned shorts in the struct gdt_entry, the rest should be unsigned char's.
it should be:
Code: Select all
struct gdt_entry
{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
this is because the size of a GDT entry should only be 8 bytes.
Second of all, I *accidentally* set the limit attribute of the struct gdt_ptr to 3 times the size of the struct gdt_ptr not the struct gdt_entry.
It should be changed to:
Code: Select all
gp.limit=(sizeof(struct gdt_entry) *3)-1;
gp.base=(unsigned int)&gdt;
Re:GRUB and protected mode
Posted: Mon May 30, 2005 3:59 pm
by Warrior
I know, it was more me giving helpful advice. Good Luck.
Re:GRUB and protected mode
Posted: Mon May 30, 2005 6:16 pm
by AR
I suggest also using __attribute__((__packed__)) because people apparently have unreliable results with __attribute__((packed))
Re:GRUB and protected mode
Posted: Wed Jun 01, 2005 4:42 pm
by travfar
I already have it working but what is the difference?
Re:GRUB and protected mode
Posted: Wed Jun 01, 2005 10:31 pm
by AR
Like I said, some people seem to get unreliable results with __attribute__((packed)). It may work or it may not, or it may work sometimes but not always but I've never had problems with __packed__.
Re:GRUB and protected mode
Posted: Thu Jun 02, 2005 3:34 am
by Pype.Clicker
surprisingly enough, i see no such thing like "__packed__" in my copy of gcc information (that should be for 3.3). If you're experiencing troubles with packed structures, you might want to compile with -Wpacked -Wpadded ...
Note also that you're supposed to pack
fields that require it, not the whole structure (or the effect is simply to have the whole structure with poor alignment when used in something else)
// from "info gcc, variable attributes"
struct foo
{
char a;
int x[2] __attribute__ ((packed));
};
Re:GRUB and protected mode
Posted: Thu Jun 02, 2005 4:41 am
by AR
Well it works, I have heaps of code that uses it. I avoid packing unless it is absolutely neccessary (stuff like BIOS structs which rarely contain any 32bit variables and are entirely unaligned even if they do). I don't see why you would pack a struct that is only used internally, alignment is good unless you are desperate for memory that is unless you are disassembling a larger variable into smaller parts using a union or something along those lines but then you could pack the whole struct anyway.
Re:GRUB and protected mode
Posted: Thu Jun 02, 2005 5:05 am
by Pype.Clicker
okay, googling further reveals that:
- "__name__" is equivalent to "name" for any attribute. It's just meant to avoid macro expansion (in case someone "#define packed" and want to __attribute__((packed)) aswell )
- using "packed" on a union/struct is equivalent to use it on every of its members
- the later rule cannot be applied on typedef's (which may be why people sometimes experiment troubles)
So if __attribute__((packed)) do not work and __attribute__((__packed__)) does, i suggest you use gcc -E and look at what the pre-processor made of your "packed" to find out what's wrong.
Re:GRUB and protected mode
Posted: Fri Jul 01, 2005 1:05 pm
by mar-rih
Pype.Clicker wrote:
surprisingly enough, i see no such thing like "__packed__" in my copy of gcc information (that should be for 3.3). If you're experiencing troubles with packed structures, you might want to compile with -Wpacked -Wpadded ...
Note also that you're supposed to pack
fields that require it, not the whole structure (or the effect is simply to have the whole structure with poor alignment when used in something else)
// from "info gcc, variable attributes"
struct foo
{
char a;
int x[2] __attribute__ ((packed));
};
could you explain this statement __attribute__, why we are using it befor or after definig variables and what is benifit of.