

#ifndef linux

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <sys\stat.h>

#include "api.h"
#include "os\os.h"

#else

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/io.h>

#include "api.h"
#include "./os/os.h"


#endif // linux

void * Internal_API=NULL;

unsigned int KTAPI_Location;


_API_ * KT_API=NULL;
unsigned long KT_API_Size;

int __cdecl KT_API_CallBack(_API_Callback * Arg);

int  (__cdecl*KT_API_Proc)(int Function,AllArgs);

//_KT_API_Proc KT_API_Proc;

int __cdecl KT_API_Error(int Function,AllArgs)
{
	return _API_se_Error;
}


void (__cdecl *Proc_DebugOut)(char * Text)=NULL;

void KT_API_DebugOut(char * Text)
{
	if (Proc_DebugOut!=NULL)
	{
		Proc_DebugOut(Text);
	}
}
int KT_API_Init(_API_ * API)
{
int Status;


//	KT_API_DebugOut("KT_API_Init\n");

	if ((API->Magic[0]==0x5f544b24)&&(API->Magic[1]==0x24495041))
	{

//		KT_API_DebugOut("Call KT_API_Proc1\n");
		KT_API_Proc=(int (__cdecl *) (int Function,AllArgs)) &API->Entry;
		#ifdef KTAPI_32
		Status=KT_API_Proc(_API_fe_Init,(unsigned long long)((unsigned long)&KT_API_CallBack),(unsigned long long)0x24544b24);
		#else
		Status=KT_API_Proc(_API_fe_Init,(unsigned long long)&KT_API_CallBack,(unsigned long long)0x24544b24);
		#endif
		

    }
    else
    {
		KT_API_Proc=&KT_API_Error;
        Status=_API_se_Error;
    }
	return Status;
}

#ifndef _lib_
int KT_API_GetFunction(char * Name,void *pFunction)
#else
int _KT_API_GetFunction(char * Name,void *pFunction)
#endif // _lib_
{
	#ifdef KTAPI_32
	return KT_API_Proc(_API_fe_GetFunction,(unsigned long long)((unsigned long)Name),(unsigned long long)((unsigned long)pFunction));
	#else
	return KT_API_Proc(_API_fe_GetFunction,(unsigned long long)Name,(unsigned long long)pFunction);
	#endif
	
}


int __cdecl KT_API_CallBack(_API_Callback * Arg)
{
int Status;

	Status=_API_se_Error;

//	KT_API_DebugOut("KT_API_CallBack\n");
	

	switch((unsigned int)Arg->Function)
    {
    //---------------------------------
    case _API_cbe_MSG:
		KT_API_DebugOut("MSG : ");
		#ifdef KTAPI_32
		KT_API_DebugOut((char *)((unsigned long)Arg->Arg1));
		#else
		KT_API_DebugOut((char *)Arg->Arg1);
		#endif
		KT_API_DebugOut("\n");
		Status=_API_se_OK;
    	break;
    //---------------------------------
    case _API_cbe_MEM_Allocate:
//		KT_API_DebugOut("_API_cbe_MEM_Allocate\n");
		#ifdef KTAPI_32
		Arg->Return=(unsigned long long)((unsigned long)OS_Memory_Allocate(Arg->Arg1));
		#else
		Arg->Return=(unsigned long long)OS_Memory_Allocate(Arg->Arg1);
		
		#endif

		Status=_API_se_OK;
    	break;

	case _API_cbe_MEM_Free:
//		KT_API_DebugOut("_API_cbe_MEM_Free\n");

		#ifdef KTAPI_32
		OS_Memory_Free((void *) ((unsigned long)Arg->Arg1),Arg->Arg2);
		#else
		OS_Memory_Free((void *)Arg->Arg1,Arg->Arg2);
		
		#endif
		
		Status=_API_se_OK;
    	break;
    //---------------------------------
	case _API_cbe_Phys_MEM_Map:
//		KT_API_DebugOut("_API_cbe_Phys_MEM_Map\n");

		#ifdef KTAPI_32
		Arg->Return=(unsigned long long)((unsigned long)OS_Physical_Memory_Map((void *)((unsigned long)Arg->Arg1),Arg->Arg2));
		#else
		Arg->Return=(unsigned long long)OS_Physical_Memory_Map((void *)Arg->Arg1,Arg->Arg2);
		#endif
		Status=_API_se_OK;
		break;

	case _API_cbe_Phys_MEM_Unmap:
//		KT_API_DebugOut("_API_cbe_Phys_MEM_Unmap\n");

		#ifdef KTAPI_32
		OS_Physical_Memory_Unmap((void *)((unsigned long)Arg->Arg1),Arg->Arg2);
		#else
		OS_Physical_Memory_Unmap((void *)Arg->Arg1,Arg->Arg2);
		#endif
		
		Status=_API_se_OK;
		break;

    //-------------------------------------------
	case _API_cbe_IO_Block:
//		KT_API_DebugOut("_API_cbe_IO_Block\n");

		#ifdef KTAPI_32
		Arg->Return=OS_Execute_IO_Block((_API_IO_Struct *)((unsigned long)Arg->Arg1),Arg->Arg2);
		#else
		Arg->Return=OS_Execute_IO_Block((_API_IO_Struct *)Arg->Arg1,Arg->Arg2);
		#endif
		Status=_API_se_OK;
		break;
	//-------------------------------------------
	case _API_cbe_Microsecond_Delay:
//		KT_API_DebugOut("_API_cbe_Microsecond_Delay\n");
		Status=OS_Microsecond_Delay(Arg->Arg1);
		break;
		
	case _API_cbe_CPUID:
//		KT_API_DebugOut("_API_cbe_CPUID\n");
		#ifdef KTAPI_32
		Status=OS_CPUID((_API_ASM_REGS_Struct *)((unsigned long)Arg->Arg1));
		#else
		Status=OS_CPUID((_API_ASM_REGS_Struct *)Arg->Arg1);
		#endif
		Status=_API_se_OK;
		break;

	case _API_cbe_Write_MSR:
//		KT_API_DebugOut("_API_cbe_Write_MSR\n");
		#ifdef KTAPI_32
		Status=OS_Write_MSR((_API_ASM_REGS_Struct *)((unsigned long)Arg->Arg1));
		#else
		Status=OS_Write_MSR((_API_ASM_REGS_Struct *)Arg->Arg1);
		#endif
		break;
		
	case _API_cbe_Read_MSR:
//		KT_API_DebugOut("_API_cbe_Read_MSR\n");
		#ifdef KTAPI_32
		Status=OS_Read_MSR((_API_ASM_REGS_Struct *)((unsigned long)Arg->Arg1));
		#else
		Status=OS_Read_MSR((_API_ASM_REGS_Struct *)Arg->Arg1);
		#endif
		break;
	
	
	default:
//		KT_API_DebugOut("_API_cbe_Unknown\n");
		break;
    }

	return Status;
}

                              

int KT_API_Load_API_Disk(void)
{
int Status;
FILE * fpIn;
_API_ API_Header;
int Offset;


	Status=_API_se_Error;

	if ((fpIn=fopen("ktapi.bin","rb"))!=NULL)
    {

		Offset=0;
        fread((void *)&API_Header,1,sizeof(_API_),fpIn);

		//
		// Check for "$KT_API$"
		//
		
		if ((API_Header.Magic[0]==0x5f544b24)&&(API_Header.Magic[1]==0x24495041))
		{

			#ifdef KTAPI_64
			
			// check if lib is 64Bit 
			
			//if (API_Header.Type!=0x5f34365f)
			if (API_Header.Type!=64)
			{
				// skip 32Bit lib
				Offset=API_Header.PSize;
				fseek(fpIn,Offset,SEEK_SET);
				fread((void *)&API_Header,1,sizeof(_API_),fpIn);
			}
			#endif

		
			fseek(fpIn,Offset,SEEK_SET);
			KT_API=OS_Alloc_Execute_Read_Write(API_Header.Size);

        	fread(KT_API,1,API_Header.PSize,fpIn);
	        Status=_API_se_OK;
		}

    	fclose(fpIn);
    }
    else
    {
    	printf("Error : Can't open ktapi.bin\n");
    }

	return Status;
}

int KT_API_Get_Version_API_Disk(_API_ * API_Header)
{
int Status;
FILE * fpIn;


	Status=_API_se_Error;

	if ((fpIn=fopen("ktapi.bin","rb"))!=NULL)
    {

        fread((void *)API_Header,1,sizeof(_API_),fpIn);

		if ((API_Header->Magic[0]==0x5f544b24)&&(API_Header->Magic[1]==0x24495041))
		{
	        Status=_API_se_OK;
		}

    	fclose(fpIn);
    }

	if (Status!=_API_se_OK)
		memset((void *)API_Header,0x00,sizeof(_API_));

	return Status;
}





int KT_API_Load_API_BIOS(void)
{
int Status;
FILE * fpIn;
_API_ API_Header;

unsigned char * BIOS;
unsigned int i;



	Status=_API_se_Error;
	
	BIOS=(unsigned char *)OS_Physical_Memory_Map((void *)0xffc00000,0x00400000);
	

	for(i=0;i<0x003ff000;i+=0x10)
	{         
		if ((((_API_*)&BIOS[i])->Magic[0]==0x5f544b24) && (((_API_*)&BIOS[i])->Magic[1]==0x24495041))
		{

			#ifdef KTAPI_64
			
			// check if lib is 64Bit 
			
			if (((_API_*)&BIOS[i])->Type!=64)
			{
				// skip 32Bit lib
				i+=((_API_*)&BIOS[i])->PSize;
			}
			#endif
		
			KT_API=OS_Alloc_Execute_Read_Write(((_API_*)&BIOS[i])->Size);

			memcpy(KT_API,&BIOS[i],((_API_*)&BIOS[i])->PSize);
	        Status=_API_se_OK;
			break;
		}
	
	}

	OS_Physical_Memory_Unmap(BIOS,0x00400000);
	
	return Status;
}

int KT_API_Get_Version_API_BIOS(_API_ * API_Header)
{
int Status;
FILE * fpIn;

unsigned char * BIOS;
unsigned int i;



	Status=_API_se_Error;
 	
	BIOS=(unsigned char *)OS_Physical_Memory_Map((void *)0xffc00000,0x00400000);
	

	for(i=0;i<0x003ff000;i+=0x10)
	{
		if ((((_API_*)&BIOS[i])->Magic[0]==0x5f544b24) && (((_API_*)&BIOS[i])->Magic[1]==0x24495041))
		{

			memcpy(API_Header,&BIOS[i],sizeof(_API_));
	        Status=_API_se_OK;
			break;
		}
	
	}

	OS_Physical_Memory_Unmap(BIOS,0x00400000);
	
	if (Status!=_API_se_OK)
		memset((void *)API_Header,0x00,sizeof(_API_));

	return Status;


}

int KT_API_Load_API_Internal(void)
{
int Status;
_API_ * API_Header;

	Status=_API_se_Error;

	if (Internal_API!=NULL)
	{

		API_Header=(_API_ *)Internal_API;
		
		if ((API_Header->Magic[0]==0x5f544b24)&&(API_Header->Magic[1]==0x24495041))
		{
		
	
		
			#ifdef KTAPI_64

			// check if lib is 64Bit 
			
			if (API_Header->Type!=64)
			{
				// skip 32Bit lib
				API_Header=(_API_ *) ((unsigned long long)API_Header+API_Header->PSize);
			}
			#endif 
		
			KT_API=OS_Alloc_Execute_Read_Write(API_Header->Size);

			memcpy(KT_API,API_Header,API_Header->PSize);
	        Status=_API_se_OK;
		}

    }

	return Status;
}

int KT_API_Get_Version_API_Internal(_API_ * API_Header)
{


int Status;

	Status=_API_se_Error;

	if (Internal_API!=NULL)
	{

		memcpy(API_Header,Internal_API,sizeof(_API_));
		
		if ((API_Header->Magic[0]==0x5f544b24)&&(API_Header->Magic[1]==0x24495041))
		{
	        Status=_API_se_OK;
		}

    }
    
	if (Status!=_API_se_OK)
		memset((void *)API_Header,0x00,sizeof(_API_));
    

	return Status;


}

#ifndef _lib_
int KT_API_Open(int sf)
#else
int _KT_API_Open(int sf)
#endif // _lib_
{
int Status;

_API_ API_Header_DISK;
_API_ API_Header_BIOS;
_API_ API_Header_Internal;

unsigned int Build;



	Status=_API_se_Error;

	if (OS_Init())
	{
		
		if (sf==sfNewest)
		{
			KT_API_Get_Version_API_Disk(&API_Header_DISK);
			KT_API_Get_Version_API_BIOS(&API_Header_BIOS);
			KT_API_Get_Version_API_Internal(&API_Header_Internal);
			
			// Set default to disk
			sf=sfDISK;
			Build=API_Header_DISK.Build;
			

			if (Build<API_Header_BIOS.Build)
			{
				sf=sfBIOS;
				Build=API_Header_BIOS.Build;
			}

			if (Build<API_Header_Internal.Build)
			{
				sf=sfInternal;
				Build=API_Header_Internal.Build;
			}
			
		}
		
		switch (sf)
		{
		
		
		case sfDISK:
			
			if (KT_API_Load_API_Disk())
			{
				if (KT_API_Init(KT_API))
				{
			        Status=_API_se_OK;
				}
			}
			break;
			
		case sfBIOS:
			if (KT_API_Load_API_BIOS())
			{
				if (KT_API_Init(KT_API))
				{
			        Status=_API_se_OK;
				}
			}
			break;
							
		case sfInternal:
			if (KT_API_Load_API_Internal())
			{
				if (KT_API_Init(KT_API))
				{
			        Status=_API_se_OK;
				}
			}
			break;

									
		}
		
		KTAPI_Location=sf;
			
			
		if (Status!=_API_se_OK)
		{
			
			if (KT_API!=NULL)
				OS_Free_Execute_Read_Write((void *)KT_API,KT_API_Size);
				
			OS_Deinit();
		}
	}
	else
	{
		
	}



	return Status;
}

#ifndef _lib_
int KT_API_Close(void)
#else
int _KT_API_Close(void)
#endif // _lib_
{
	KT_API_Proc(_API_fe_Deinit);
	OS_Free_Execute_Read_Write((void *)KT_API,KT_API_Size);
	OS_Deinit();

	return _API_se_OK;
}
