#include <stddef.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>

#define __GDT__
#include "Gdt.h"

struct tss DefaultTss;

void InitGdtDescriptor(uint32_t base, uint32_t limite, uint8_t acces, uint8_t other, struct GdtDescriptor *Descriptor){
        Descriptor->lim0_15 = (limite & 0xffff);
        Descriptor->base0_15 = (base & 0xffff);
        Descriptor->base16_23 = (base & 0xff0000) >> 16;
        Descriptor->acces = acces;
        Descriptor->lim16_19 = (limite & 0xf0000) >> 16;
        Descriptor->other = (other & 0xf);
        Descriptor->base24_31 = (base & 0xff000000) >> 24;
        return;
}

void InitGdt(void){
        DefaultTss.debug_flag = 0x00;
	DefaultTss.io_map = 0x00;
	DefaultTss.esp0 = 0x20000;
	DefaultTss.ss0 = 0x18;

	/* initialisation des descripteurs de segment */
	InitGdtDescriptor(0x0, 0x0, 0x0, 0x0, &kgdt[0]);
	InitGdtDescriptor(0x0, 0xFFFFF, 0x9B, 0x0D, &kgdt[1]);	/* code */
	InitGdtDescriptor(0x0, 0xFFFFF, 0x93, 0x0D, &kgdt[2]);	/* data */
	InitGdtDescriptor(0x0, 0x0, 0x97, 0x0D, &kgdt[3]);		/* stack */

	InitGdtDescriptor(0x0, 0xFFFFF, 0xFF, 0x0D, &kgdt[4]);	/* ucode */
	InitGdtDescriptor(0x0, 0xFFFFF, 0xF3, 0x0D, &kgdt[5]);	/* udata */
	InitGdtDescriptor(0x0, 0x0, 0xF7, 0x0D, &kgdt[6]);		/* ustack */

	InitGdtDescriptor((uint32_t) & DefaultTss, 0x67, 0xE9, 0x00, &kgdt[7]);	/* descripteur de tss */
	kgdtr.limite = GDTSIZE * 8;
	kgdtr.base = GDTBASE;
	memcpy((char *) kgdtr.base, (char *) kgdt, kgdtr.limite);
	asm("lgdtl (kgdtr)");
	asm("   movw $0x10, %ax	\n \
            movw %ax, %ds	\n \
            movw %ax, %es	\n \
            movw %ax, %fs	\n \
            movw %ax, %gs	\n \
            ljmp $0x08, $next	\n \
            next:		\n");
}