diff --git a/include/kmemory.h b/include/kmemory.h new file mode 100644 index 0000000..66e72b4 --- /dev/null +++ b/include/kmemory.h @@ -0,0 +1,26 @@ +/***********************************/ +/* Librairie Kmemory.h */ +/* 20 Mars 2007 */ +/***********************************/ + + +#ifndef JREKCED_KERNEL_MEMORY +# define JREKCED_KERNEL_MEMORY + +# include "type.h" + +# define MEMORY_BLOC_SIZE (1024L) /* Taille des blocs */ + + // Initialise les gestionnaire de memoire. +void Kernel_InitMemory (void *DataMemory, // DataMemory pointe vers la zone de memoire disponible. + UDWORD TotalMemorySize); // TotalMemorySize est la quantite total de memoire disponible. + +void * Kernel_mballoc(UDWORD Size); // Alloue SIZE blocs de memoire et retourne un pointeur sur la zone. + // Retourne un pointeur nul si l'allocation est impossible. + +int Kernel_mbfree (void *Adresse); // Libere le bloc memoire alloue a l'adresse ADRESSE. + // Retourne -1 si adresse incorrecte et 0 si tout s'est bien deroule. + +void * Kernel_mbrealloc (void *Adresse, UDWORD Size); // Redimensionne un bloc, retourne NULL si le bloc + // n'est pas redimensionne. +#endif diff --git a/include/ldt.h b/include/ldt.h new file mode 100644 index 0000000..8a66458 --- /dev/null +++ b/include/ldt.h @@ -0,0 +1,85 @@ +/***********************************/ +/* Librairie LDT.h */ +/* 23 Mars 2007 */ +/***********************************/ + +#ifndef JREKCED_LDT +# define JREKCED_LDT + +# include "type.h" + +# define LDT_BLOC_SIZE (128) /* Nombre de descripteur LDT dans un bloc */ + +// Types d'acces +# define GLT_ACCESSED (0x1) + +# define LDT_DATA (0x0) +# define LDT_DATA_WRITE (0x2) +# define LDT_DATA_EXPAND (0x4) + +# define LDT_CODE (0x8) +# define LDT_CODE_READ (0xA) +# define LDT_CODE_CONFORMING (0xD) + +// Granularite +# define LDT_BYTE (0x0) +# define LDT_4KB (0x1) + +// Mode du CPU +# define LDT_16BIT (0x0) +# define LDT_32BIT (0x1) + + +typedef struct +{ + UWORD Limite_0_15; // Bit 00-15 : Limite (0-15) + UWORD Adresse_0_15; // Bit 16-31 : Adresse (0-15) + UBYTE Adresse_16_23; // Bit 32-39 : Adresse (16-23) + UBYTE Acces : 1; // 0 = System + // 1 = Code ou data + UBYTE Type : 4; // Bit 41-44 : Type + UBYTE DPL : 2; // Spécifie le niveau de privilège du segment + UBYTE Present : 1; // Indique si le segment est en mémoire (bit a 1) ou non (bit a 0) + UBYTE Limite_16_19 : 4; // Bit 48-51 : Limite (16-19) + UBYTE UserDefine : 1; // Bit 52 : Utilisation libre + UBYTE Unused : 1; // Bit 53 : Non utilise (toujours = 0) + UBYTE CPUMode : 1; // Bit 54 : = 0 -> 16-Bit + // = 1 -> 32-Bit + UBYTE Granularite : 1; // Si = 0 : Limite = 1 octet -> 1 Mo + // Si = 1 : Limite = 4 Ko -> 4 Go + UBYTE Adresse_24_31; // Bit 56-63 : Adresse (24-31) +} T_LDT; + + +typedef struct +{ + UWORD Size; // Taille de la GDT + void * Adresse; // Adresse phisique de la GDT; + UWORD Empty; + +} T_LDT_reg; + + +// T_LDT *GDT_BASE = ((T_LDT*)0x0800L); /* Addresse physique ou reside la GDT, le 1e element est toujours null */ + + +T_LDT * LDT_balloc (UWORD Size); // Alloue un bloc de Size LDT + +int LDT_bfree (void * Adresse); // Libere un bloc LDT + +T_LDT * LDT_brealloc (T_LDT * OldLDT, UWORD NewSize); // Redimensionne un bloc LDT, retourne NULL en cas d'erreur. + +T_LDT * LDT_AllocLDT (T_LDT *BaseLDT); // Cherche un LDT libre dans un bloc precedement + // alloue avec LDT_balloc. + // Retourne NULL si aucun bloc disponible. + // Si un bloc libre est trouve, il est marque comme + // utilise et un pointeur sur ce LDT est retourne. + +int LDT_FreeLDT (T_LDT *LDT); // Marque le LDT comme non utilise et le met a NULL. + +int LDT_MapMemory (T_LDT *LDT, void * Linear, // Met des donnees dans un LDT. + UDWORD Size, // Cette fonction est a tester. + UBYTE Granularite, + UBYTE DPL, UBYTE Type, + UBYTE CPUMode); +#endif diff --git a/include/type.h b/include/type.h new file mode 100644 index 0000000..b9d0b12 --- /dev/null +++ b/include/type.h @@ -0,0 +1,31 @@ +/***********************************/ +/* Librairie Type.h */ +/* 20 Mars 2007 */ +/***********************************/ + +#ifndef JREKCED_TYPE +# define JREKCED_TYPE + +# define NULL (0x0LL) + +typedef char int8; +typedef short int16; +typedef int int32; +typedef long long int64; + +typedef char BYTE; +typedef short WORD; +typedef long DWORD; +typedef long long QWORD; + +typedef signed char SBYTE; +typedef signed short SWORD; +typedef signed long SDWORD; +typedef signed long long SQWORD; + +typedef unsigned char UBYTE; +typedef unsigned short UWORD; +typedef unsigned long UDWORD; +typedef unsigned long long UQWORD; + +#endif diff --git a/lib/kmemory.c b/lib/kmemory.c new file mode 100644 index 0000000..4658bd9 --- /dev/null +++ b/lib/kmemory.c @@ -0,0 +1,156 @@ +/***********************************/ +/* Librairie Kmemory.c */ +/* 20 Mars 2007 */ +/***********************************/ + +#include +#include + +/* Structure table d'allocation memoire */ +typedef struct +{ + UBYTE Used : 1; // = 0 -> La zone memoire est libre. + // = 1 -> La zone memoire est utilisee. + UBYTE Expand : 1; // = 0 -> Fin du bloc. + // = 1 -> Le bloc se prolonge sur le bloc suivant. + UBYTE UnUsed : 6; // Zone libre. +} T_KernelMemoryMap; + + +T_KernelMemoryMap * BlocAllocate = NULL; // Table d'allocation des blocs memoire. +void * BaseDynAlloc = NULL; // Pointeur sur la zone memoire allouable. +UDWORD MaxMemoryBlocs; + + +// Initialisation du gestionnaire de memoire. +void Kernel_InitMemory (void *DataMemory, UDWORD TotalMemorySize) +{ + UDWORD Boucle; + UDWORD TableBlocs; + UDWORD TotalBlocs; + + // Alignement des bloc de memoire a un multiple de MEMORY_BLOC_SIZE + if ( (UDWORD)DataMemory % MEMORY_BLOC_SIZE != 0) + { DataMemory = ((void*) ((((UDWORD)DataMemory) / MEMORY_BLOC_SIZE) * MEMORY_BLOC_SIZE) + MEMORY_BLOC_SIZE ); }; + + TotalBlocs = (((void*)TotalMemorySize) - DataMemory) / MEMORY_BLOC_SIZE; + TableBlocs = TotalBlocs / MEMORY_BLOC_SIZE; + MaxMemoryBlocs = TotalBlocs - TableBlocs; + BlocAllocate = (T_KernelMemoryMap *)DataMemory; + BaseDynAlloc = DataMemory + (TableBlocs * MEMORY_BLOC_SIZE); + + for (Boucle = 0; Boucle < MaxMemoryBlocs; Boucle++) + { + BlocAllocate [Boucle].Used = 0; + BlocAllocate [Boucle].Expand = 0; + } +} + + +// Alloue SIZE blocs de memoire +void * Kernel_mballoc(UDWORD Size) +{ + UDWORD Counter = 0; + UDWORD Base = 0; + UDWORD Boucle, Boucle2; + + if (Size == 0) return NULL; + + for (Boucle = 0; Boucle < MaxMemoryBlocs; Boucle++) + { + if (BlocAllocate[Boucle].Used == 0) { Counter++; } + else { Counter = 0; Base = Boucle + 1; } + + if (Counter >= Size) + { + if (Base+Size > MaxMemoryBlocs) return NULL; + for (Boucle2=Base; Boucle2 < (Base+Size); Boucle2++) + { + BlocAllocate[Boucle2].Used = 1; + if (Boucle2+1 < (Base+Size) ) { BlocAllocate[Boucle2].Expand = 1; } + else { BlocAllocate[Boucle2].Expand = 0; } + } + return ((void*) (BaseDynAlloc + (Base * MEMORY_BLOC_SIZE) )); + } + } + return NULL; +} + +// Libere un bloc memoire +int Kernel_mbfree (void *Adresse) +{ + UDWORD Bloc; + + if (((Adresse - BaseDynAlloc) % MEMORY_BLOC_SIZE) != 0) return -1; + if ((((UDWORD)Adresse) % MEMORY_BLOC_SIZE) != 0) return -1; + + Bloc = (Adresse - BaseDynAlloc) / MEMORY_BLOC_SIZE; + + for (; BlocAllocate[Bloc].Expand == 1; Bloc++) + { + BlocAllocate[Bloc].Used = 0; + BlocAllocate[Bloc].Expand = 0; + } + + BlocAllocate[Bloc].Used = 0; + BlocAllocate[Bloc].Expand = 0; + + return 0; +}; + +void * Kernel_mbrealloc (void *Adresse, UDWORD Size) +{ + UDWORD Bloc, Boucle, OldSize, CopySize; + void * NewAdresse; + + if (((Adresse - BaseDynAlloc) % MEMORY_BLOC_SIZE) != 0) return NULL; + Bloc = (Adresse - BaseDynAlloc) / MEMORY_BLOC_SIZE; + if (BlocAllocate[Bloc].Used == 0) return NULL; + + for (Boucle = Bloc; BlocAllocate[Boucle].Expand == 1; Boucle++) + { if (Boucle >= MaxMemoryBlocs) break; }; + + OldSize = Boucle - Bloc + 1; + + // Si pas de changement de taille de bloc, ... + if ( Size == OldSize) return Adresse; + + // Si on reduit le nombre de bloc, ... + if ( Size < OldSize) + { + for (Boucle = (Bloc + Size); Boucle < (Bloc + OldSize) ; Boucle++) + { + BlocAllocate[Boucle].Used = 0; + BlocAllocate[Boucle].Expand = 0; + } + BlocAllocate[Size-1].Expand = 0; + return Adresse; + } + + // Si on augmente le nombre de bloc + for (Boucle = (Bloc + OldSize); Boucle < (Bloc + Size) ; Boucle++) + { + // Si le bloc ne peut etre simplement agrandit, ... + if ( BlocAllocate[Boucle].Used == 1 ) + { + NewAdresse = Kernel_mballoc (Size); + if (NewAdresse == NULL) return NULL; + CopySize = (OldSize * MEMORY_BLOC_SIZE) / sizeof (int64); + for (Boucle = 0; Boucle < CopySize; Boucle++) + { ((int64*) NewAdresse)[Boucle] = ((int64*) Adresse)[Boucle]; }; + Kernel_mbfree (Adresse); + return NewAdresse; + } + } + + // Le bloc est simplement agrandit + for (Boucle = (Bloc + OldSize - 1); Boucle < (Bloc + Size) ; Boucle++) + { + BlocAllocate[Boucle].Used = 1; + BlocAllocate[Boucle].Expand = 1; + } + BlocAllocate[Size-1].Expand = 0; + return Adresse; +} + +#undef MAX_MEMORY_BLOCS diff --git a/lib/ldt.c b/lib/ldt.c new file mode 100644 index 0000000..18b90df --- /dev/null +++ b/lib/ldt.c @@ -0,0 +1,236 @@ +/***********************************/ +/* Librairie LDT.c */ +/* 23 Mars 2007 */ +/***********************************/ + +#include "LDT.h" +#include "Kmemory.h" + +# define LDT_MANAGER_SIZE (127) + +typedef struct // Structure de gestion des bloc LDT +{ + void * Next; // Pointeur de chainage + UDWORD Empty; + T_LDT_reg LDTdesc [LDT_MANAGER_SIZE]; // Nombre de blocs LDT +} T_LDT_Manager; + +void LDT_initalloc (void *AllocTable, UDWORD Index, UDWORD SetSize, UDWORD TotalSize); +T_LDT_Manager * LDT_mballoc (UWORD Size); + +///////////////////////////////////////////////////////////////////////// + +T_LDT_Manager * LDT_Manager = NULL; + +///////////////////////////////////////////////////////////////////////// + +T_LDT * LDT_balloc (UWORD Size) // Alloue un bloc de Size LDT +{ + UWORD Boucle; + UDWORD Blocs, Boucle2; + T_LDT_Manager * * ptr_Manager = &LDT_Manager; + T_LDT_Manager * Manager = LDT_Manager; + + do + { + if (* ptr_Manager == NULL) + { + * ptr_Manager = Kernel_mballoc (1); + Manager = * ptr_Manager; + Manager->Next = NULL; + for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++) + { + Manager->LDTdesc [Boucle].Adresse = NULL; + Manager->LDTdesc [Boucle].Size = NULL; + } + } + + for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++) + { + if (Manager->LDTdesc [Boucle].Adresse == NULL) + { + + Blocs = Size * sizeof(T_LDT); + if (Blocs % MEMORY_BLOC_SIZE == 0) + { Blocs /= MEMORY_BLOC_SIZE; } else { Blocs = (Blocs / MEMORY_BLOC_SIZE) + 1; } + Manager->LDTdesc [Boucle].Adresse = Kernel_mballoc (Blocs); + if (Manager->LDTdesc [Boucle].Adresse == NULL) return NULL; + Manager->LDTdesc [Boucle].Size = (Blocs * MEMORY_BLOC_SIZE) / sizeof(T_LDT); + + // Mise a zero de la LDT + for (Boucle2 = 0; Boucle2 < Manager->LDTdesc [Boucle].Size; Boucle2++) + { ((int64*) Manager->LDTdesc [Boucle].Adresse)[Boucle2] = NULL; } + + return Manager->LDTdesc [Boucle].Adresse; + } + } + + *ptr_Manager = Manager; + Manager = Manager->Next; + } while (1); +} + + +int LDT_bfree (void * Adresse) // Libere un bloc LDT +{ + UWORD Boucle, Boucle2; + int RetVal; + T_LDT_Manager * * ptr_Manager = &LDT_Manager; + T_LDT_Manager * Manager = LDT_Manager; + + do + { + if (*ptr_Manager == NULL) { return -1; } + for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++) + { + if (Manager->LDTdesc [Boucle].Adresse == Adresse) + { + + RetVal = Kernel_mbfree(Manager->LDTdesc [Boucle].Adresse); + if (Boucle == 0) + { + Kernel_mbfree (*ptr_Manager); + *ptr_Manager = NULL; + return RetVal; + } + else + { + for (Boucle2 = Boucle; Boucle2 < LDT_MANAGER_SIZE-1; Boucle2++) + { Manager->LDTdesc [Boucle2] = Manager->LDTdesc [Boucle2+1]; } + + Manager->LDTdesc [Boucle2+1].Size = NULL; + Manager->LDTdesc [Boucle2+1].Adresse = NULL; + } + + Manager->LDTdesc [LDT_MANAGER_SIZE-1].Size = NULL; + Manager->LDTdesc [LDT_MANAGER_SIZE-1].Adresse = NULL; + + return RetVal; + } + } + + *ptr_Manager = Manager; + Manager = Manager->Next; + } while (1); + +} + +T_LDT * LDT_brealloc (T_LDT * OldLDT, UWORD NewSize) +{ + T_LDT * NewLDT; + UDWORD Blocs; + UWORD Boucle; + + T_LDT_Manager * * ptr_Manager = &LDT_Manager; + T_LDT_Manager * Manager = LDT_Manager; + Blocs = NewSize * sizeof(T_LDT); + + if (Blocs % MEMORY_BLOC_SIZE == 0) + { Blocs /= MEMORY_BLOC_SIZE; } else { Blocs = (Blocs / MEMORY_BLOC_SIZE) + 1; } + + do + { + if (*ptr_Manager == NULL) { return NULL; } + for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++) + { + if (Manager->LDTdesc [Boucle].Adresse == OldLDT) + { + NewLDT = Kernel_mbrealloc (OldLDT, Blocs); + if (NewLDT == NULL) return NULL; + Manager->LDTdesc [Boucle].Adresse = NewLDT; + Manager->LDTdesc [Boucle].Size = NewSize; + return NewLDT; + } + } + + *ptr_Manager = Manager; + Manager = Manager->Next; + } while (1); +} + +/////////////////////////////////////////////////////////////////////// + +T_LDT * LDT_AllocLDT (T_LDT *BaseLDT) +{ + UWORD Boucle; + UDWORD Boucle2; + UDWORD Size; + T_LDT_Manager * Manager = LDT_Manager; + + if (BaseLDT == NULL) return NULL; + + do + { + if (Manager == NULL) { return NULL; } + for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++) + { + Size = Manager->LDTdesc [Boucle].Size; + if (Manager->LDTdesc [Boucle].Adresse == ((void*)BaseLDT) ) + { + for (Boucle2 = 1; Boucle2 < Size; Boucle2++) // Le 1e LDT reste null + { + if ( BaseLDT[Boucle2].UserDefine == 0 ) + { + BaseLDT[Boucle2].UserDefine = 1; + return BaseLDT+Boucle2; + }; + } + return NULL; + } + } + Manager = Manager->Next; + } while (1); +} + +int LDT_FreeLDT (T_LDT *LDT) // Marque le LDT comme non utilise et le met a NULL +{ + if ( ((UDWORD)LDT & 0x07L) != NULL) { return -2; } + if (LDT->UserDefine == 0) { return -1; } + *((int64*)LDT) = NULL; + return 0; +} + +/////////////////////////////////////////////////////////////////////// + +int LDT_MapMemory (T_LDT *LDT, void * Linear, UDWORD Size, UBYTE Granularite, UBYTE DPL, UBYTE Type, UBYTE CPUMode) +{ + if ( ((UDWORD)LDT & 0x07L) != NULL) { return -2; } + + LDT->Adresse_0_15 = (DWORD)Linear & 0x0000FFFFL; + LDT->Adresse_16_23 = ((DWORD)Linear >> 16) & 0x000000FFL; + LDT->Adresse_24_31 = ((DWORD)Linear >> 24) & 0x000000FFL; + LDT->Limite_0_15 = Size & 0x0000FFFFL; + LDT->Limite_16_19 = (Size >> 16) & 0x0000000FL; + LDT->Granularite = Granularite; + LDT->Type = Type; + LDT->DPL = DPL; + LDT->CPUMode = CPUMode; + LDT->Present = 1; + LDT->UserDefine = 1; + return 0; +} + +int LDT_load (T_LDT *LDT) +{ + UWORD Boucle; + T_LDT_Manager * * ptr_Manager = &LDT_Manager; + T_LDT_Manager * Manager = LDT_Manager; + + do + { + if (*ptr_Manager == NULL) { return -1; } + for (Boucle = 0; Boucle < LDT_MANAGER_SIZE; Boucle++) + { + if (Manager->LDTdesc [Boucle].Adresse == LDT) + { + asm("lgdt %0\n" : : "m" (Manager->LDTdesc [Boucle])); + return 0; + } + } + + *ptr_Manager = Manager; + Manager = Manager->Next; + } while (1); +} + +