Reload GDT

This commit is contained in:
Loic Guegan 2021-04-05 14:46:31 +02:00
parent b54b87ad2d
commit ba7e57138c
8 changed files with 182 additions and 19 deletions

View file

@ -1,5 +1,5 @@
EXEC := bringelle
CC := gcc -c -m32 -fno-pie -fno-builtin
CC := gcc -c -m32 -fno-pie -fno-builtin -fno-stack-protector
UTILS_SRC := $(wildcard utils/*.c)
@ -16,14 +16,19 @@ bringelle.o: bringelle.c
$(CC) $^
utils.o: $(UTILS_SRC)
$(CC) $^ -o $@
for src in $^ ;\
do \
obj=$$(basename $${src} ".c")".o" ;\
$(CC) $${src} -o utils/$${obj} ;\
done
ld -melf_i386 -relocatable utils/*.o -o utils.o
boot.o: ./boot/boot.S
as --32 -o $@ $^ -mx86-used-note=no
clean:
find ./ -name "*.o" -delete
- rm $(EXEC)
- rm ./*.o
.PHONY: clean

View file

@ -1,4 +1,5 @@
.extern bringelle
.extern gdt_memcpy
.globl _start
.text
@ -23,5 +24,28 @@ mb_header:
.long MB_ENTRY_ADDR
_start:
call bringelle
# Copy GDT into memory then load its register
call gdt_memcpy
lgdtl (GDTR)
# Update all segments register
# with the new GDT offset
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
# Update code segment
ljmp $0x08, $cs_new
cs_new:
# Update stack segment
movw $0x18, %ax
movw %ax, %ss
movl $0x20000,%esp
# Start kernel main function
call bringelle

52
src/utils/gdt.c Normal file
View file

@ -0,0 +1,52 @@
#include "gdt.h"
#include "print.h"
#include "mem.h"
struct GDT_REGISTER GDTR = { 0, 0 };
void gdt_memcpy(){
GDTR.limit=8*4; // Each entry is 8 bytes and 4 entries
GDTR.base=0x800;
GDT_ENTRY cs_desc;
cs_desc.base=0;
cs_desc.limit=0xFFFFF;
cs_desc.flags=GDT_SZ|GDT_GR;
cs_desc.access=GDT_PR|GDT_PRVL_0|GDT_S|GDT_EXEC|GDT_RW;
GDT_ENTRY ds_desc;
ds_desc.base=0;
ds_desc.limit=0xFFFFF;
ds_desc.flags=GDT_SZ|GDT_GR;
ds_desc.access=GDT_PR|GDT_PRVL_0|GDT_S|GDT_RW;
GDT_ENTRY ss_desc;
ss_desc.base=0;
ss_desc.limit=0;
ss_desc.flags=GDT_SZ|GDT_GR;
ss_desc.access=GDT_PR|GDT_PRVL_0|GDT_S|GDT_RW|GDT_DC;
// Write GDT descriptors into memory
gdt_write_entry((GDT_ENTRY){0,0,0,0},GDTR.base); // First one must be null
gdt_write_entry(cs_desc, GDTR.base+8); // Each entry is 64 bits (8 bytes)
gdt_write_entry(ds_desc, GDTR.base+8*2);
gdt_write_entry(ss_desc, GDTR.base+8*3);
}
void gdt_write_entry(GDT_ENTRY entry, u32 addr){
int descriptor[2];
// First row of the descriptor
descriptor[0]=(entry.limit & 0xFFFF)|(entry.base << 16);
// Format second row of the descriptor
u16 base=(entry.base >> 16) & 0xFF;
u16 access=entry.access & 0xFF;
u16 limit=(entry.limit >> 16) & 0xF; // Remember: limits it is on 20 bits so 4 last bits
u8 flags=entry.flags & 0xF;
u8 base2=entry.base >> 24; // Take the last 8 bits
descriptor[1]=base|access<<8|limit<<16|flags<<20|base2<<24;
// Copy descriptor into memory
memcpy(descriptor,(void*)addr,8);
}

44
src/utils/gdt.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef GDT_H
#define GDT_H
#include "types.h"
// Access byte
#define GDT_AC 1 // Access bit
#define GDT_RW 1 << 1 // Read/Write bit
#define GDT_DC 1 << 2 // Direction bit/Conforming bit
#define GDT_EXEC 1 << 3 // Executable bit
#define GDT_S 1 << 4 // Descriptor type
#define GDT_PRVL_0 0 // Privilege (from 0 to 3)
#define GDT_PRVL_1 1 << 5
#define GDT_PRVL_2 2 << 5
#define GDT_PRVL_3 3 << 5
#define GDT_PR 1 << 7 // Present Bit
// Flags
#define GDT_SZ 1 << 2 // Size bit
#define GDT_GR 1 << 3 // Granularity bit
typedef struct GDT_ENTRY {
u32 base;
u32 limit;
u8 flags;
u8 access;
} GDT_ENTRY;
struct GDT_REGISTER {
u16 limit;
u32 base;
} __attribute__((packed));
/**
* Copy GDT in memory
*/
void gdt_memcpy();
/**
* Write a GDT entry at address addr
*/
void gdt_write_entry(GDT_ENTRY entry, u32 addr);
#endif

8
src/utils/mem.c Normal file
View file

@ -0,0 +1,8 @@
#include "mem.h"
void memcpy(void *src, void *dst, int size){
u8 *char_src=(u8 *)src;
u8 *char_dst=(u8 *)dst;
for(int i=0;i<size;i++)
char_dst[i]=char_src[i];
}

9
src/utils/mem.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef MEM_H
#define MEM_H
#include "types.h"
void memcpy(void *src, void *dst, int size);
#endif

View file

@ -1,24 +1,36 @@
#include "print.h"
#include "types.h"
#define MAX_COL 80
#define MAX_LINE 25
char *video=(char *)0xB8000;
u8 col=0;
u8 line=0;
struct VIDEO_STATE {
u8 *mem;
u8 col;
u8 line;
u8 bg;
u8 fg;
};
VIDEO_STATE VS={
(u8 *)0xB8000,
0,
0,
BLACK,
GRAY,
};
void putchar(char c){
// Print char
video[col*2+MAX_COL*line*2]=c;
VS.mem[VS.col*2+MAX_COL*VS.line*2]=c;
VS.mem[VS.col*2+MAX_COL*VS.line*2+1]=VS.fg|VS.bg<<4;
// Refresh location
col+=1;
if(col>= MAX_COL){
col=0;
line+=1;
if(line>=MAX_LINE){
line=MAX_LINE-1;
VS.col+=1;
if(VS.col>= MAX_COL){
VS.col=0;
VS.line+=1;
if(VS.line>=MAX_LINE){
VS.line=MAX_LINE-1;
scrollup();
}
}
@ -39,13 +51,13 @@ void clear(){
}
void scrollup(){
// Move line up
// Move VS.line up
for(char i=1;i<=MAX_LINE;i++){
for(char j=0;j<=MAX_COL;j++)
video[j*2+MAX_COL*(i-1)*2]=video[j*2+MAX_COL*i*2];
VS.mem[j*2+MAX_COL*(i-1)*2]=VS.mem[j*2+MAX_COL*i*2];
}
// Clear last line
// Clear last VS.line
for(char i=0;i<=MAX_COL;i++){
video[col*2+MAX_COL*(MAX_LINE-1)*2]='\0';
VS.mem[i*2+MAX_COL*(MAX_LINE-1)*2]='\0';
}
}

View file

@ -1,6 +1,15 @@
#ifndef PRINT_H
#define PRINT_H
#include "types.h"
typedef enum VIDEO_COLORS {
BLACK=0, BLUE=1, GREEN=2,CYAN=3, RED=4,PURPLE=5,BROWN=6,GRAY=7,
DARK_GRAY=8,LIGHT_BLUE=9,LIGHT_GREEN=10,LIGHT_CYAN=11,LIGHT_RED=12,LIGHT_PURPLE=13,YELLOW=14,WHITE=15
} VIDEO_COLORS;
typedef struct VIDEO_STATE VIDEO_STATE;
/**
* Print char