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
2019-01-15 01:15:58 +01:00
/* registre gdt */
static struct gdtr gdtreg ;
/* table de GDT */
static gdtdes gdt [ GDT_SIZE ] ;
2018-09-18 15:11:50 +02:00
/* TSS */
static struct tss tss0 ;
2019-01-15 01:15:58 +01:00
/*******************************************************************************/
/* Cr<43> <72> un descripteur GDT */
void makegdtdes ( u32 base , u32 limite , u8 acces , u8 flags , gdtdes * desc )
{
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 ;
}
/*******************************************************************************/
/* Initialise la GDT */
void initgdt ( u32 offset )
{
makegdtdes ( 0x0 , 0x00000 , 0x00 , 0x00 , & gdt [ 0 ] ) ; /* descripteur nul */
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 */
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 */
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 */
tss0 . trapflag = 0x00 ;
tss0 . iomap = 0x00 ;
tss0 . esp0 = 0x6000 ;
tss0 . ss0 = SEL_TSS ;
makegdtdes ( & tss0 , 0x67 , SEG_PRESENT | SEG_CODE | SEG_RING3 | SEG_ACCESSED , 0x00 , & gdt [ 7 ] ) ; /* descripteur de tss */
/* initialise le registre gdt */
gdtreg . limite = GDT_SIZE * sizeof ( gdtdes ) ;
gdtreg . base = GDT_ADDR ;
/* recopie de la GDT a son adresse */
memcpy ( & gdt , ( u8 * ) gdtreg . base , gdtreg . limite , 1 ) ;
/* chargement du registre GDT */
lgdt ( gdtreg ) ;
/* initialisation des segments */
initselectors ( offset ) ;
}
2018-08-31 02:48:03 +02:00
/*******************************************************************************/
2019-01-01 13:30:06 +01:00
/* Initialise les selecteurs avec la GDT */
2018-08-31 02:48:03 +02:00
2019-01-01 13:30:06 +01:00
void initselectors ( u32 executingoffset )
2018-08-31 02:48:03 +02:00
{
2019-01-01 13:30:06 +01:00
asm ( " movw %[data], %%ax \n \
movw % % ax , % % ds \ n \
movw % % ax , % % es \ n \
movw % % ax , % % fs \ n \
movw % % ax , % % gs \ n \
movw % [ stack ] , % % ax \ n \
2019-01-19 00:17:35 +01:00
movl % [ offset ] , % % ebx \ n \
2019-01-01 13:30:06 +01:00
movw % % ax , % % ss \ n \
movl % [ stackoff ] , % % esp \ n \
2019-01-19 00:17:35 +01:00
pushl % % ebx \ n \
ljmp % [ code ] , $ raz \ n \
raz : \ n \
2019-01-01 13:30:06 +01:00
xor % % eax , % % eax \ n \
xor % % ebx , % % ebx \ n \
xor % % ecx , % % ecx \ n \
xor % % edx , % % edx \ n \
xor % % esi , % % esi \ n \
xor % % edi , % % edi \ n \
xor % % ebp , % % ebp \ n \
2019-01-19 00:17:35 +01:00
ret " ::[data] " i " (SEL_KERNEL_DATA),[code] " i " (SEL_KERNEL_CODE),[stack] " i " (SEL_KERNEL_STACK),[stackoff] " i " (KERNEL_STACK_ADDR),[offset] " m " (executingoffset));
2018-09-17 18:17:11 +02:00
}
2018-12-10 19:12:20 +01:00
/*******************************************************************************/
/* Change le TSS courant */
2018-12-12 15:25:04 +01:00
void setTSS ( u32 ss , u32 sp )
2018-12-10 19:12:20 +01:00
{
2019-01-01 13:30:06 +01:00
tss0 . trapflag = 0x00 ;
tss0 . iomap = 0x00 ;
tss0 . ss0 = SEL_TSS ;
2018-12-10 19:12:20 +01:00
tss0 . esp0 = sp ;
tss0 . ss0 = ss ;
}
2018-09-17 18:17:11 +02:00
/*******************************************************************************/
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-10-03 22:50:54 +02:00
/*******************************************************************************/
/* r<> cup<75> re la base d'un descripteur GDT */
u32 getdesbase ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( entry [ index ] . base0_15 + ( entry [ index ] . base16_23 < < 16 ) +
( entry [ index ] . base24_31 < < 24 ) ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re la limite d'un descripteur GDT */
u32 getdeslimit ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( entry [ index ] . lim0_15 + ( entry [ index ] . lim16_19 < < 16 ) ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re la limite d'un descripteur GDT */
u32 getdesdpl ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( entry [ index ] . acces > > 5 & 0x03 ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re le type d'un descripteur GDT */
u8 getdestype ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( ( entry [ index ] . acces & 0x14 ) = = 0 )
& & ( ( entry [ index ] . acces & 0x08 ) > 0 )
& & ( ( entry [ index ] . acces & 0x01 ) > 0 )
& & ( ( entry [ index ] . flags & 0x06 ) = = 0 ) )
return ' T ' ;
else
return ( ( ( entry [ index ] . acces & 0x08 ) > 0 ) ? ' C ' : ' D ' ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re l'info 1 d'un descripteur GDT */
u8 getdesbit1 ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( ( entry [ index ] . acces & 0x14 ) = = 0 )
& & ( ( entry [ index ] . acces & 0x08 ) > 0 )
& & ( ( entry [ index ] . acces & 0x01 ) > 0 )
& & ( ( entry [ index ] . flags & 0x06 ) = = 0 ) )
return ( ( ( entry [ index ] . acces & 0x04 ) > 0 ) ? ' B ' : ' - ' ) ;
else
return ( ( ( entry [ index ] . acces & 0x01 ) > 0 ) ? ' A ' : ' - ' ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re l'info 2 d'un descripteur GDT */
u8 getdesbit2 ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( ( entry [ index ] . acces & 0x20 ) = = 0 )
& & ( ( entry [ index ] . acces & 0x08 ) > 0 )
& & ( ( entry [ index ] . acces & 0x01 ) > 0 )
& & ( ( entry [ index ] . flags & 0x06 ) = = 0 ) )
return ( ( ( entry [ index ] . flags & 0x01 ) > 0 ) ? ' U ' : ' - ' ) ;
else if ( ( entry [ index ] . acces & 0x8 ) > 0 )
return ( ( ( entry [ index ] . acces & 0x02 ) > 0 ) ? ' R ' : ' - ' ) ;
else
return ( ( ( entry [ index ] . acces & 0x02 ) > 0 ) ? ' W ' : ' R ' ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re l'info 3 d'un descripteur GDT */
u8 getdesbit3 ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( entry [ index ] . acces & 0x08 ) > 0 )
return ( ( ( entry [ index ] . acces & 0x04 ) > 0 ) ? ' C ' : ' - ' ) ;
else
return ( ( ( entry [ index ] . acces & 0x04 ) > 0 ) ? ' D ' : ' U ' ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re l'alignement d'un descripteur GDT */
u16 getdesalign ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( ( ( entry [ index ] . flags & 0x08 ) > 0 ) ? 4096 : 1 ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re si descripteur GDT est valide */
bool isdesvalid ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
return ( ( entry [ index ] . acces & 0x80 ) > 0 ) ;
2018-10-03 22:50:54 +02:00
}
/*******************************************************************************/
/* r<> cup<75> re la dimension d'un descripteur GDT */
u32 getdessize ( u16 sel )
{
2018-12-12 15:25:04 +01:00
gdtdes * entry = GDT_ADDR ;
u8 index = sel / sizeof ( gdtdes ) ;
if ( ( ( entry [ index ] . acces & 0x14 ) = = 0 )
& & ( ( entry [ index ] . acces & 0x08 ) > 0 )
& & ( ( entry [ index ] . acces & 0x01 ) > 0 )
& & ( ( entry [ index ] . flags & 0x06 ) = = 0 ) )
return 32 ;
else
return ( ( ( entry [ index ] . flags & 0x08 ) > 0 ) ? 32 : 16 ) ;
2018-10-03 22:50:54 +02:00
}