2018-09-28 20:35:51 +02:00
/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hord<72> Nicolas */
/* */
2018-08-31 02:48:03 +02:00
# include "gdt.h"
# include "asm.h"
# include "types.h"
2018-10-02 02:16:14 +02:00
# include "memory.h"
2018-08-31 02:48:03 +02:00
2018-09-01 22:58:05 +02:00
/* registre gdt */
static struct gdtr gdtreg ;
/* table de GDT */
2018-10-02 02:16:14 +02:00
static gdtdes gdt [ GDT_SIZE ] ;
2018-09-01 22:58:05 +02:00
2018-09-18 15:11:50 +02:00
/* TSS */
static struct tss tss0 ;
2018-08-31 02:48:03 +02:00
/*******************************************************************************/
/* Initialise la GDT */
2018-09-17 18:17:11 +02:00
void initgdt ( u32 offset )
2018-08-31 02:48:03 +02:00
{
2018-09-27 17:47:27 +02:00
makegdtdes ( 0x0 , 0x00000 , 0x00 , 0x00 , & gdt [ 0 ] ) ; /* descripteur nul */
2018-10-02 02:16:14 +02:00
makegdtdes ( 0x0 , 0xFFFFF , SEG_PRESENT | SEG_NORMAL | SEG_CODE | SEG_RING0 | SEG_READ | SEG_ACCESSED , GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE , & gdt [ 1 ] ) ; /* code -> SEL_KERNEL_CODE */
makegdtdes ( 0x0 , 0x00000 , SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING0 | SEG_EXPAND_DOWN | SEG_READ_WRITE | SEG_ACCESSED , GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE , & gdt [ 2 ] ) ; /* pile -> SEL_KERNEL_STACK */
2018-12-09 00:40:25 +01:00
makegdtdes ( 0x0 , 0xFFFFF , SEG_PRESENT | SEG_NORMAL | SEG_CODE | SEG_RING3 | SEG_CONFORMING | SEG_READ | SEG_ACCESSED , GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE , & gdt [ 3 ] ) ; /* code -> SEL_USER_CODE */
makegdtdes ( 0x0 , 0x00000 , SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING3 | SEG_EXPAND_DOWN | SEG_READ_WRITE | SEG_ACCESSED , GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE , & gdt [ 4 ] ) ; /* pile -> SEL_USER_STACK */
2018-10-02 02:16:14 +02:00
makegdtdes ( 0x0 , 0xFFFFF , SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING0 | SEG_READ_WRITE | SEG_ACCESSED , GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE , & gdt [ 5 ] ) ; /* data -> SEL_KERNEL_DATA */
makegdtdes ( 0x0 , 0xFFFFF , SEG_PRESENT | SEG_NORMAL | SEG_DATA | SEG_RING3 | SEG_READ_WRITE | SEG_ACCESSED , GRANULARITY_4K | OPSIZE_32B | SYS_AVAILABLE , & gdt [ 6 ] ) ; /* data -> SEL_USER_DATA */
2018-09-18 14:29:35 +02:00
2018-09-18 15:11:50 +02:00
tss0 . trapflag = 0x00 ;
tss0 . iomap = 0x00 ;
tss0 . esp0 = 0x1FFF0 ;
tss0 . ss0 = SEL_TSS ;
2018-10-02 02:16:14 +02:00
makegdtdes ( & tss0 , 0x67 , SEG_PRESENT | SEG_CODE | SEG_RING3 | SEG_ACCESSED , 0x00 , & gdt [ 7 ] ) ; /* descripteur de tss */
2018-09-18 15:11:50 +02:00
2018-09-01 22:58:05 +02:00
/* initialise le registre gdt */
2018-10-04 14:55:41 +02:00
gdtreg . limite = GDT_SIZE * sizeof ( gdtdes ) ;
2018-10-02 02:16:14 +02:00
gdtreg . base = GDT_ADDR ;
2018-09-01 22:58:05 +02:00
/* recopie de la GDT a son adresse */
memcpy ( & gdt , ( u8 * ) gdtreg . base , gdtreg . limite , 1 ) ;
/* chargement du registre GDT */
lgdt ( & gdtreg ) ;
/* initialisation des segments */
2018-09-17 18:17:11 +02:00
initselectors ( offset ) ;
}
/*******************************************************************************/
2018-09-18 15:11:50 +02:00
/* Initialise le registre de t<> che (TSR) */
2018-09-27 17:47:27 +02:00
void inittr ( void )
2018-09-18 15:11:50 +02:00
{
2018-09-27 17:47:27 +02:00
ltr ( SEL_TSS ) ;
2018-09-18 15:11:50 +02:00
}
/*******************************************************************************/
2018-09-17 18:17:11 +02:00
/* Initialise les selecteurs avec la GDT */
void initselectors ( u32 executingoffset )
{
2018-09-27 17:47:27 +02:00
asm ( " movw %[data], %%ax \n \
2018-09-17 18:17:11 +02:00
movw % % ax , % % ds \ n \
movw % % ax , % % es \ n \
movw % % ax , % % fs \ n \
movw % % ax , % % gs \ n \
movl % [ offset ] , % % ebx \ n \
movw % [ stack ] , % % ax \ n \
movw % % ax , % % ss \ n \
movl % [ stackoff ] , % % esp \ n \
ljmp % [ code ] , $ raz \ n \
2018-09-01 22:58:05 +02:00
raz : \ n \
2018-09-17 18:17:11 +02:00
pushl % % ebx \ n \
2018-10-02 02:16:14 +02:00
ret \ n " ::[data] " i " (SEL_KERNEL_DATA),[code] " i " (SEL_KERNEL_CODE),[stack] " i " (SEL_KERNEL_STACK),[stackoff] " i " (KERNEL_STACK_ADDR),[offset] " m " (executingoffset));
2018-08-31 02:48:03 +02:00
}
2018-10-03 22:50:54 +02:00
/*******************************************************************************/
/* r<> cup<75> re la base d'un descripteur GDT */
u32 getdesbase ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( entry [ index ] . base0_15 + ( entry [ index ] . base16_23 < < 16 ) + ( entry [ index ] . base24_31 < < 24 ) ) ;
}
/*******************************************************************************/
/* r<> cup<75> re la limite d'un descripteur GDT */
u32 getdeslimit ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( entry [ index ] . lim0_15 + ( entry [ index ] . lim16_19 < < 16 ) ) ;
}
/*******************************************************************************/
/* r<> cup<75> re la limite d'un descripteur GDT */
u32 getdesdpl ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( entry [ index ] . acces > > 5 & 0 b11 ) ;
}
/*******************************************************************************/
/* r<> cup<75> re le type d'un descripteur GDT */
u8 getdestype ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( ( entry [ index ] . acces & 0 b10100 ) = = 0 ) & & ( ( entry [ index ] . acces & 0 b01000 ) > 0 ) & & ( ( entry [ index ] . acces & 0 b0001 ) > 0 ) & & ( ( entry [ index ] . flags & 0 b0110 ) = = 0 ) )
return ' T ' ;
else
return ( ( ( entry [ index ] . acces & 0 b1000 ) > 0 ) ? ' C ' : ' D ' ) ;
}
/*******************************************************************************/
/* r<> cup<75> re l'info 1 d'un descripteur GDT */
u8 getdesbit1 ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( ( entry [ index ] . acces & 0 b10100 ) = = 0 ) & & ( ( entry [ index ] . acces & 0 b01000 ) > 0 ) & & ( ( entry [ index ] . acces & 0 b0001 ) > 0 ) & & ( ( entry [ index ] . flags & 0 b0110 ) = = 0 ) )
return ( ( ( entry [ index ] . acces & 0 b10 ) > 0 ) ? ' B ' : ' - ' ) ;
else
return ( ( ( entry [ index ] . acces & 0 b1 ) > 0 ) ? ' A ' : ' - ' ) ;
}
/*******************************************************************************/
/* r<> cup<75> re l'info 2 d'un descripteur GDT */
u8 getdesbit2 ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( ( entry [ index ] . acces & 0 b10100 ) = = 0 ) & & ( ( entry [ index ] . acces & 0 b01000 ) > 0 ) & & ( ( entry [ index ] . acces & 0 b0001 ) > 0 ) & & ( ( entry [ index ] . flags & 0 b0110 ) = = 0 ) )
return ( ( ( entry [ index ] . flags & 0 b1 ) > 0 ) ? ' U ' : ' - ' ) ;
else if ( ( entry [ index ] . acces & 0 b1000 ) > 0 )
return ( ( ( entry [ index ] . acces & 0 b10 ) > 0 ) ? ' R ' : ' - ' ) ;
else
return ( ( ( entry [ index ] . acces & 0 b10 ) > 0 ) ? ' W ' : ' R ' ) ;
}
/*******************************************************************************/
/* r<> cup<75> re l'info 3 d'un descripteur GDT */
u8 getdesbit3 ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( entry [ index ] . acces & 0 b1000 ) > 0 )
return ( ( ( entry [ index ] . acces & 0 b100 ) > 0 ) ? ' C ' : ' - ' ) ;
else
return ( ( ( entry [ index ] . acces & 0 b100 ) > 0 ) ? ' D ' : ' U ' ) ;
}
/*******************************************************************************/
/* r<> cup<75> re l'alignement d'un descripteur GDT */
u16 getdesalign ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( ( ( entry [ index ] . flags & 0 b1000 ) > 0 ) ? 4096 : 1 ) ;
}
/*******************************************************************************/
/* r<> cup<75> re si descripteur GDT est valide */
bool isdesvalid ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( ( entry [ index ] . acces & 0 b10000000 ) > 0 ) ;
}
/*******************************************************************************/
/* r<> cup<75> re la dimension d'un descripteur GDT */
u32 getdessize ( u16 sel )
{
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( ( entry [ index ] . acces & 0 b10100 ) = = 0 ) & & ( ( entry [ index ] . acces & 0 b01000 ) > 0 ) & & ( ( entry [ index ] . acces & 0 b0001 ) > 0 ) & & ( ( entry [ index ] . flags & 0 b0110 ) = = 0 ) )
return 32 ;
else
return ( ( ( entry [ index ] . flags & 0 b1000 ) > 0 ) ? 32 : 16 ) ;
}
2018-08-31 02:48:03 +02:00
/*******************************************************************************/
/* Cr<43> <72> un descripteur GDT */
2018-09-27 17:47:27 +02:00
void makegdtdes ( u32 base , u32 limite , u8 acces , u8 flags , gdtdes * desc )
2018-08-31 02:48:03 +02:00
{
2018-09-27 17:47:27 +02:00
desc - > lim0_15 = ( limite & 0xffff ) ;
desc - > base0_15 = ( base & 0xffff ) ;
desc - > base16_23 = ( base & 0xff0000 ) > > 16 ;
desc - > acces = acces ;
desc - > lim16_19 = ( limite & 0xf0000 ) > > 16 ;
desc - > flags = ( flags & 0xf ) ;
desc - > base24_31 = ( base & 0xff000000 ) > > 24 ;
return ;
2018-08-31 02:48:03 +02:00
}