GRUB and protected mode
GRUB and protected mode
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
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
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.
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
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
srg
Re:GRUB and protected mode
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:
asmfunc.asm:
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.
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);
};
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
P.S. the functions I borrowed were in the public domain.
Re:GRUB and protected mode
SOrry!
gdt.c should be:
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
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.
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
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:
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:
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));
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
I suggest also using __attribute__((__packed__)) because people apparently have unreliable results with __attribute__((packed))
Re:GRUB and protected mode
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__.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:GRUB and protected mode
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)
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
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.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:GRUB and protected mode
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.
- "__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
could you explain this statement __attribute__, why we are using it befor or after definig variables and what is benifit of.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));
};