2019-01-14 14:54:50 +01:00
//*******************************************************************************/
2018-12-30 12:25:20 +01:00
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
# include "types.h"
# include "asm.h"
# include "setup.h"
2019-01-01 13:30:06 +01:00
# include "memory.h"
2018-12-30 12:25:20 +01:00
2019-01-19 00:17:35 +01:00
extern hdr ;
/* paramètres de démarrage */
static bootparams params ;
2018-12-30 12:25:20 +01:00
2019-01-01 13:30:06 +01:00
/* registre gdt */
static struct gdtr gdtreg ;
/* table de GDT */
static gdtdes gdt [ GDT_SIZE ] ;
2019-01-02 15:47:56 +01:00
u8 kernel_version [ ] = " COS2000 Version " MACRO ( VERSION ) " - compiled " __DATE__ ;
2018-12-30 12:25:20 +01:00
u8 initmemory ( void )
{
u32 count = 0 ;
miniregs reg ;
2019-01-14 14:54:50 +01:00
cleanreg ( & reg ) ;
2018-12-30 12:25:20 +01:00
entrye820 * desc = params . e820_table ;
static struct entrye820 buf ;
do {
reg . ax = 0xe820 ;
reg . cx = sizeof ( buf ) ;
reg . edx = SMAP ;
reg . di = & buf ;
interrupt ( 0x15 , reg ) ;
if ( reg . eflags & EFLAGS_CF )
break ;
if ( reg . eax ! = SMAP )
{
count = 0 ;
break ;
}
* desc + + = buf ;
count + + ;
} while ( reg . ebx & & count < ARRAY_SIZE ( params . e820_table ) ) ;
return params . e820_numbers = count ;
}
2019-01-14 14:54:50 +01:00
void showstr ( u8 * str )
{
while ( * str ! = ' \000 ' )
showchar ( * str + + ) ;
}
void cleanreg ( miniregs * reg )
{
for ( u8 i ; i < sizeof ( miniregs ) ; i + + )
* ( ( u8 * ) reg + i ) = 0 ;
}
2018-12-30 12:25:20 +01:00
void showchar ( u8 achar )
{
miniregs reg ;
2019-01-14 14:54:50 +01:00
cleanreg ( & reg ) ;
2018-12-30 12:25:20 +01:00
reg . bx = 0x0007 ;
reg . cx = 0x0001 ;
reg . ah = 0x0e ;
reg . al = achar ;
interrupt ( 0x10 , reg ) ; /* INT 10 - VIDEO - TELETYPE OUTPUT */
}
u8 gettime ( void )
{
miniregs reg ;
2019-01-14 14:54:50 +01:00
cleanreg ( & reg ) ;
2018-12-30 12:25:20 +01:00
reg . ah = 0x02 ;
interrupt ( 0x1a , reg ) ; /* TIME - GET REAL-TIME CLOCK TIME (AT,XT286,PS) */
return reg . dh ;
}
u8 waitchar ( void )
{
miniregs reg ;
2019-01-14 14:54:50 +01:00
cleanreg ( & reg ) ;
2018-12-30 12:25:20 +01:00
reg . ah = 0x00 ;
interrupt ( 0x16 , reg ) ; /* INT 16 - KEYBOARD - GET KEYSTROKE */
return reg . al ;
}
void initkeyboard ( void )
{
miniregs reg ;
2019-01-14 14:54:50 +01:00
cleanreg ( & reg ) ;
2018-12-30 12:25:20 +01:00
reg . ah = 0x02 ;
interrupt ( 0x16 , reg ) ; /* INT 16 - KEYBOARD - GET SHIFT FLAGS */
params . kbflag = reg . al ;
reg . ah = 0x03 ;
reg . al = 0x05 ;
reg . bx = 0x00 ;
interrupt ( 0x16 , reg ) ; /* INT 16 - KEYBOARD - SET TYPEMATIC RATE AND DELAY */
}
u8 empty8042 ( void )
{
u8 status ;
u32 loops = LOOPS_8042 ;
u8 ffs = FF_8042 ;
while ( loops - - ) {
iodelay ( ) ;
status = inb ( 0x64 ) ;
if ( status = = 0xff ) {
if ( ! - - ffs )
return NULL ;
}
if ( status & 1 ) {
2019-01-02 15:47:56 +01:00
iodelay ( ) ;
2018-12-30 12:25:20 +01:00
( void ) inb ( 0x60 ) ;
} else if ( ! ( status & 2 ) ) {
return 1 ;
}
}
return NULL ;
}
void iodelay ( void )
{
//asm("outb %%al,$0x80" ::);
for ( u32 loop = LOOPS_DELAY ; loop > 0 ; loop - - ) nop ( ) ;
}
u8 testA20 ( void )
{
asm ( " xorw %%cx, %%cx \n \
decw % % cx \ n \
movw % % cx , % % gs \ n \
movw $ 0x4000 , % % cx \ n \
movw % % fs : ( 0x200 ) , % % ax \ n \
pushw % % ax \ n \
1 : \ n \
incw % % ax \ n \
movw % % ax , % % fs : ( 0x200 ) \ n \
call iodelay \ n \
cmpw % % gs : ( 0x210 ) , % % ax \ n \
loope 1 b \ n \
popw % % fs : ( 0x200 ) \ n \
xor % % ax , % % ax \ n \
je 2f \ n \
mov $ 0x1 , % % ax \ n \
2 : " ::: " ax " , " cx " );
}
void enableA20kbc ( void )
{
empty8042 ( ) ;
outb ( 0xd1 , 0x64 ) ;
empty8042 ( ) ;
outb ( 0xdf , 0x60 ) ;
empty8042 ( ) ;
outb ( 0xff , 0x64 ) ;
empty8042 ( ) ;
}
void enableA20fast ( void )
{
u8 port ;
port = inb ( 0x92 ) ;
port | = 0x02 ;
port & = ~ 0x01 ;
outb ( port , 0x92 ) ;
}
u8 enableA20 ( void )
{
int loops = LOOPS_A20_ENABLE ;
int kbcerr ;
while ( loops - - ) {
2019-01-15 01:15:58 +01:00
if ( ! testA20 ( ) )
return NULL ;
2018-12-30 12:25:20 +01:00
kbcerr = empty8042 ( ) ;
2019-01-15 01:15:58 +01:00
if ( ! testA20 ( ) )
return NULL ;
2018-12-30 12:25:20 +01:00
if ( ! kbcerr ) {
enableA20kbc ( ) ;
2019-01-15 01:15:58 +01:00
if ( ! testA20 ( ) )
return NULL ;
2018-12-30 12:25:20 +01:00
}
enableA20fast ( ) ;
2019-01-15 01:15:58 +01:00
if ( ! testA20 ( ) )
2018-12-30 12:25:20 +01:00
return NULL ;
}
return 1 ;
}
2019-01-01 13:30:06 +01:00
/*******************************************************************************/
/* Copie une portion de mémoire vers une autre */
2019-01-15 01:15:58 +01:00
void memcpyto ( void * src , void * dst , u32 count )
2019-01-01 13:30:06 +01:00
{
2019-01-15 01:15:58 +01:00
asm ( " push %%es \n \
cld \ n \
xor % % eax , % % eax \ n \
mov % % ax , % % es \ n \
rep movsb \ n \
pop % % es " :: " S " (src), " D " (dst), " c " (count):);
2019-01-01 13:30:06 +01:00
}
/*******************************************************************************/
/* Créé 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 ( )
{
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 */
2019-01-15 01:15:58 +01:00
makegdtdes ( 0x0 , 0x00000 , 0x00 , 0x00 , & gdt [ 3 ] ) ; /* LIBRE */
makegdtdes ( 0x0 , 0x00000 , 0x00 , 0x00 , & gdt [ 4 ] ) ; /* LIBRE */
2019-01-01 13:30:06 +01: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 */
2019-01-15 01:15:58 +01:00
makegdtdes ( 0x0 , 0x00000 , 0x00 , 0x00 , & gdt [ 6 ] ) ; /* LIBRE */
makegdtdes ( 0x0 , 0x00000 , 0x00 , 0x00 , & gdt [ 7 ] ) ; /* LIBRE */
2019-01-01 13:30:06 +01:00
/* initialise le registre gdt */
gdtreg . limite = GDT_SIZE * sizeof ( gdtdes ) ;
gdtreg . base = GDT_ADDR ;
/* recopie de la GDT a son adresse */
2019-01-15 01:15:58 +01:00
memcpyto ( & gdt , ( u8 * ) gdtreg . base , gdtreg . limite ) ;
2019-01-01 13:30:06 +01:00
/* chargement du registre GDT */
lgdt ( gdtreg ) ;
}
void maskinterrupts ( void )
{
cli ( ) ;
outb ( 0x80 , 0x70 ) ; /* Disable NMI */
iodelay ( ) ;
outb ( 0xff , 0xa1 ) ; /* Mask all interrupts on the secondary PIC */
2019-01-02 15:47:56 +01:00
iodelay ( ) ;
2019-01-01 13:30:06 +01:00
outb ( 0xfb , 0x21 ) ; /* Mask all but cascade on the primary PIC */
iodelay ( ) ;
}
void initcoprocessor ( void )
{
outb ( 0 , 0xf0 ) ;
iodelay ( ) ;
outb ( 0 , 0xf1 ) ;
iodelay ( ) ;
}
2019-01-15 01:15:58 +01:00
void initpmode ( )
2019-01-01 13:30:06 +01:00
{
if ( enableA20 ( ) ) {
showstr ( " impossible d'ouvrir la ligne A20... \n " ) ;
2019-01-02 15:47:56 +01:00
halt ( ) ;
2019-01-01 13:30:06 +01:00
}
maskinterrupts ( ) ;
initgdt ( ) ;
2019-01-15 01:15:58 +01:00
gotopmode ( ) ;
2019-01-01 13:30:06 +01:00
}
2019-01-19 00:17:35 +01:00
void initparams ( )
{
2019-01-19 16:23:57 +01:00
params . cmdline = ( ( header * ) & hdr ) - > cmd_line_ptr ;
params . ramdiskaddr = ( ( header * ) & hdr ) - > ramdisk_image ;
params . ramdisksize = ( ( header * ) & hdr ) - > ramdisk_size ;
2019-01-19 00:17:35 +01:00
asm ( " xorl %%eax,%%eax \n \
movw % % ds , % % ax \ n \
shl $ 4 , % % eax \ n \
addw % [ bootparams ] , % % ax \ n \
movl % % eax , % % cr3 " ::[bootparams] " i " (¶ms));
}
void initvideo ( )
{
}
2018-12-30 12:25:20 +01:00
void main ( void )
{
2019-01-14 14:54:50 +01:00
showstr ( " *** Chargement de COS2000 - mode reel *** \r \n " ) ;
2019-01-19 00:17:35 +01:00
initparams ( ) ;
2019-01-14 14:54:50 +01:00
showstr ( " -Initialisation de la memoire \r \n " ) ;
2018-12-30 12:25:20 +01:00
initmemory ( ) ;
2019-01-14 14:54:50 +01:00
showstr ( " -Initialisation du clavier \r \n " ) ;
2018-12-30 12:25:20 +01:00
initkeyboard ( ) ;
2019-01-14 14:54:50 +01:00
showstr ( " -Initialisation du coprocesseur \r \n " ) ;
2019-01-01 13:30:06 +01:00
initcoprocessor ( ) ;
2019-01-19 00:17:35 +01:00
showstr ( " -Initialisation video & passage en mode protege \r \n " ) ;
initvideo ( ) ;
2019-01-15 01:15:58 +01:00
initpmode ( ) ;
2018-12-30 12:25:20 +01:00
}