↑ Back to main site.

EPOS

Experimental Protected-mode Operating System

gdt.c
/*
EPOS
http://www.atanaslaskov.com/epos/

FILE:        gdt.c
DESCRIPTION: Handling the IA32 Global Descriptor Table
 
BSD LICENSE
Copyright (c) 2006, Atanas Laskov
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
   1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
   2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ATANAS LASKOV BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


#include "..\init\init.h"
#include "..\service\service.h"
#include "..\memory\memory.h"
#include "..\process\process.h"
#include "gdt.h"

/*****************************
 Data Storage
*****************************/


struct GDT g_gdt;
struct LDT g_ldt[MAX_PROCESS_CNT];

// Internals
//
struct GDTDescriptorBase{
    unsigned short wBase15_0;
    unsigned char  bBase23_16;
    unsigned char  bBase31_24;
};
union GDTDescriptorBase_u{
    struct GDTDescriptorBase part;
    unsigned long dwBase;
};

struct GDTDescriptorLimit{
    unsigned short wLimit15_0;
    unsigned char  bLimit19_16 : 4;
    unsigned char  bFlags : 4;
    unsigned char  bReserved;
};
union GDTDescriptorLimit_u{
    struct GDTDescriptorLimit part;
    unsigned long dwLimit;
};

// Assembly functions for getting pointers
//
struct GDTDescriptor* gdt_getp_gdt();
struct GDTR*          gdt_getp_gdtr();

/*****************************
 Global Descriptor Table (GDT)
 Initialization
*****************************/


void gdtInit()
{
    struct GDTDescriptor *pCodeLDT0;
    struct GDTDescriptor *pCodeGDT;
    struct GDTDescriptor *pDataGDT;
    unsigned long i;

    //Get GDT pointer
    g_gdt.desc = gdt_getp_gdt();

    //Format LDT descriptors
    pCodeLDT0 = g_gdt.desc+INDEX_GDT_LDT0;
    for(i=1; i<MAX_PROCESS_CNT; i++)
    {
        g_gdt.desc[INDEX_GDT_LDT0+i] = g_gdt.desc[INDEX_GDT_LDT0];
    }

    //Format LDTs
    pCodeGDT = g_gdt.desc+INDEX_GDT_CODE;
    pDataGDT = g_gdt.desc+INDEX_GDT_DATA;
    for(i=0; i<MAX_PROCESS_CNT; i++)
    {
        //Copy main descriptor parameters
        g_ldt[i].desc[INDEX_LDT_CODE] = *pCodeGDT;
        g_ldt[i].desc[INDEX_LDT_DATA] = *pDataGDT;

        //Put descriptors in ring 3
        g_ldt[i].desc[INDEX_LDT_CODE].bAccess |= GDTD_ACCESS_RING3;
        g_ldt[i].desc[INDEX_LDT_DATA].bAccess |= GDTD_ACCESS_RING3;

        //Format LDT descriptor (additional)
        gdtSetBase(g_gdt.desc+INDEX_GDT_LDT0+i,
            0x600+(unsigned long)(g_ldt[i].desc));
    }
}

/*****************************
 Descriptor Access
*****************************/


struct GDTDescriptor* gdtGetDescriptorGDT(unsigned long ndesc){
    return g_gdt.desc+ndesc;
}

struct GDTDescriptor* gdtGetDescriptorLDT(unsigned long nldt, unsigned long ndesc){
    return g_ldt[nldt].desc+ndesc;
}

/*****************************
 Descriptor Manipulation
*****************************/


void gdtSetBase(struct GDTDescriptor* pDesc, unsigned long dwBase)
{
    union GDTDescriptorBase_u base;
    base.dwBase = dwBase;
    pDesc->wBase15_0  = base.part.wBase15_0;
    pDesc->bBase23_16 = base.part.bBase23_16;
    pDesc->bBase31_24 = base.part.bBase31_24;
}

void gdtSetLimit(struct GDTDescriptor* pDesc, unsigned long dwLimit)
{
    union GDTDescriptorLimit_u limit;
    limit.dwLimit = dwLimit;
    if(limit.part.bFlags!=0)    return;
    if(limit.part.bReserved!=0) return;
    pDesc->wLimit15_0  = limit.part.wLimit15_0;
    pDesc->bLimit19_16 = limit.part.bLimit19_16;
}

void  gdtFormPointer(struct GDTDescriptor* pDesc, void *DescLocalPtr, void** pptr)
{
    union GDTDescriptorBase_u base;
    base.part.wBase15_0  = pDesc->wBase15_0;
    base.part.bBase23_16 = pDesc->bBase23_16;
    base.part.bBase31_24 = pDesc->bBase31_24;
    *pptr = (void*)(base.dwBase-0x600+(unsigned long)(DescLocalPtr));
}

/*****************************
 Local Descriptor Table (LDT) Data Transfers
*****************************/


void gdtLDTDatasGetBufer(unsigned long ofs, unsigned char*pBuf, unsigned long size)
{
    unsigned long i;
    for(i=0; i<size; i++)
    {
        pBuf[i] = gdt_ldtdatas_getb(ofs+i);
    }
}

void gdtLDTDatasPutBufer(unsigned long ofs, unsigned char*pBuf, unsigned long size)
{
    unsigned long i;
    for(i=0; i<size; i++)
    {
        gdt_ldtdatas_setb(ofs+i, pBuf[i]);
    }
}

unsigned long gdt_linear_stack_getdw(unsigned long ofs)
{
    unsigned long a,b,c,d,r;

    a = gdt_linear_getb(ofs-0);
    b = gdt_linear_getb(ofs-1);
    c = gdt_linear_getb(ofs-2);
    d = gdt_linear_getb(ofs-3);

    r = a*0x1000000 + b*0x10000 + c*0x100 + d;
    return r;
}