/* * (C) Copyright 1992, ..., 2007 the "DOSEMU-Development-Team". * * for details see file COPYING.DOSEMU in the DOSEMU distribution */ /* this is for the DPMI support */ #ifndef DPMI_H #define DPMI_H #include "emu-ldt.h" #include "emm.h" #include "dmemory.h" #define DPMI_VERSION 0x00 /* major version 0 */ #define DPMI_DRIVER_VERSION 0x5a /* minor version 0.90 */ #define DPMI_MAX_CLIENTS 32 /* maximal number of clients */ #define DPMI_page_size 4096 /* 4096 bytes per page */ #define DPMI_pm_stack_size 0xf000 /* locked protected mode stack for exceptions, */ /* hardware interrupts, software interrups 0x1c, */ /* 0x23, 0x24 and real mode callbacks */ #define DPMI_rm_stacks 6 /* RM stacks per DPMI client */ #define DPMI_max_rec_rm_func (DPMI_MAX_CLIENTS * DPMI_rm_stacks) /* max number of recursive real mode functions */ #define DPMI_rm_stack_size 0x0200 /* real mode stack size */ #define DPMI_private_paragraphs ((DPMI_rm_stacks * DPMI_rm_stack_size)>>4) /* private data for DPMI server */ #define RM_CB_Para_ADD (DTA_Para_ADD+DTA_Para_SIZE) #define RM_CB_Para_SIZE 1 #define current_client (in_dpmi-1) #define DPMI_CLIENT (DPMIclient[current_client]) #define PREV_DPMI_CLIENT (DPMIclient[current_client-1]) #ifdef __linux__ int modify_ldt(int func, void *ptr, unsigned long bytecount); #define LDT_WRITE 0x11 #endif void direct_ldt_write(int offset, int length, char *buffer); /* this is used like: SEL_ADR(_ss, _esp) */ void *SEL_ADR(unsigned short sel, unsigned int reg); #define HLT_OFF(addr) ((unsigned long)addr-(unsigned long)DPMI_dummy_start) enum { es_INDEX, cs_INDEX, ss_INDEX, ds_INDEX, fs_INDEX, gs_INDEX, eax_INDEX, ebx_INDEX, ecx_INDEX, edx_INDEX, esi_INDEX, edi_INDEX, ebp_INDEX, esp_INDEX }; typedef struct pmaddr_s { unsigned int offset; unsigned short selector; } INTDESC; typedef struct segment_descriptor_s { unsigned int base_addr; /* Pointer to segment in flat memory */ unsigned int limit; /* Limit of Segment */ unsigned int type:2; unsigned int is_32:1; /* one for is 32-bit Segment */ unsigned int readonly:1; /* one for read only Segments */ unsigned int is_big:1; /* Granularity */ unsigned int not_present:1; unsigned int useable:1; unsigned int used; /* Segment in use by client # */ /* or Linux/GLibc (0xfe) */ /* or DOSEMU (0xff) */ } SEGDESC; struct sel_desc_s { unsigned short selector; unsigned int descriptor[2]; } __attribute__((packed)); struct RealModeCallStructure { unsigned int edi; unsigned int esi; unsigned int ebp; unsigned int esp; unsigned int ebx; unsigned int edx; unsigned int ecx; unsigned int eax; unsigned short flags; unsigned short es; unsigned short ds; unsigned short fs; unsigned short gs; unsigned short ip; unsigned short cs; unsigned short sp; unsigned short ss; }; typedef struct { unsigned short selector; unsigned int offset; unsigned short rmreg_selector; unsigned int rmreg_offset; struct RealModeCallStructure *rmreg; unsigned rm_ss_selector; } RealModeCallBack; struct DPMIclient_struct { struct sigcontext_struct stack_frame; /* fpu_state needs to be paragraph aligned for fxrstor/fxsave */ struct _fpstate fpu_state __attribute__ ((aligned(16))); int is_32; dpmi_pm_block_root *pm_block_root; unsigned short private_data_segment; int in_dpmi_rm_stack; char *pm_stack; int in_dpmi_pm_stack; /* for real mode call back, DPMI function 0x303 0x304 */ RealModeCallBack realModeCallBack[0x10]; INTDESC Interrupt_Table[0x100]; INTDESC Exception_Table[0x20]; unsigned short LDT_ALIAS; unsigned short PMSTACK_SEL; /* protected mode stack selector */ /* used for RSP calls */ unsigned short RSP_cs[DPMI_MAX_CLIENTS], RSP_ds[DPMI_MAX_CLIENTS]; int RSP_state, RSP_installed; }; struct RSPcall_s { unsigned char data16[8]; unsigned char code16[8]; unsigned short ip; unsigned short reserved; unsigned char data32[8]; unsigned char code32[8]; unsigned int eip; }; struct RSP_s { struct RSPcall_s call; dpmi_pm_block_root *pm_block_root; }; EXTERN volatile int in_dpmi INIT(0);/* Set to 1 when running under DPMI */ EXTERN volatile int in_dpmi_dos_int INIT(0); EXTERN volatile int dpmi_mhp_TF INIT(0); EXTERN unsigned char dpmi_mhp_intxxtab[256] INIT({0}); EXTERN volatile int is_cli INIT(0); extern SEGDESC Segments[MAX_SELECTORS]; extern unsigned long dpmi_total_memory; /* total memory of this session */ extern unsigned long dpmi_free_memory; /* how many bytes memory client */ /* can allocate */ extern unsigned long pm_block_handle_used; /* tracking handle */ extern unsigned char *ldt_buffer; void dpmi_get_entry_point(void); #ifdef __x86_64__ extern void dpmi_iret_setup(struct sigcontext_struct *); #else #define dpmi_iret_setup(x) #endif int indirect_dpmi_switch(struct sigcontext_struct *); #ifdef __linux__ int dpmi_fault(struct sigcontext_struct *); #endif void dpmi_realmode_hlt(unsigned int); void run_pm_int(int); void run_pm_dos_int(int); void fake_pm_int(void); #ifdef __linux__ int dpmi_mhp_regs(void); void dpmi_mhp_getcseip(unsigned int *seg, unsigned int *off); void dpmi_mhp_getssesp(unsigned int *seg, unsigned int *off); int dpmi_mhp_get_selector_size(int sel); int dpmi_mhp_getcsdefault(void); int dpmi_mhp_setTF(int on); void dpmi_mhp_GetDescriptor(unsigned short selector, unsigned int *lp); int dpmi_mhp_getselbase(unsigned short selector); unsigned long dpmi_mhp_getreg(int regnum); void dpmi_mhp_setreg(int regnum, unsigned long val); void dpmi_mhp_modify_eip(int delta); #endif void add_cli_to_blacklist(void); dpmi_pm_block DPMImalloc(unsigned long size); dpmi_pm_block DPMImallocLinear(unsigned long base, unsigned long size, int committed); int DPMIfree(unsigned long handle); dpmi_pm_block DPMIrealloc(unsigned long handle, unsigned long size); dpmi_pm_block DPMIreallocLinear(unsigned long handle, unsigned long size, int committed); void DPMIfreeAll(void); int DPMIMapConventionalMemory(unsigned long handle, unsigned long offset, unsigned long low_addr, unsigned long cnt); int DPMISetPageAttributes(unsigned long handle, int offs, us attrs[], int count); int DPMIGetPageAttributes(unsigned long handle, int offs, us attrs[], int count); void GetFreeMemoryInformation(unsigned int *lp); int GetDescriptor(us selector, unsigned int *lp); void *dpmi_GetSegmentBaseAddress(unsigned short selector); void *GetSegmentBaseAddress(unsigned short); unsigned int GetSegmentBase(unsigned short); unsigned int GetSegmentLimit(unsigned short); int CheckSelectors(struct sigcontext_struct *scp, int in_dosemu); int ValidAndUsedSelector(unsigned short selector); extern char *DPMI_show_state(struct sigcontext_struct *scp); extern void dpmi_sigio(struct sigcontext_struct *scp); extern void run_dpmi(void); extern int ConvertSegmentToDescriptor(unsigned short segment); extern int ConvertSegmentToDescriptor_lim(unsigned short segment, unsigned long limit); extern int ConvertSegmentToCodeDescriptor(unsigned short segment); extern int ConvertSegmentToCodeDescriptor_lim(unsigned short segment, unsigned long limit); extern int SetSegmentBaseAddress(unsigned short selector, unsigned long baseaddr); extern int SetSegmentLimit(unsigned short, unsigned int); extern INTDESC dpmi_get_interrupt_vector(unsigned char num); extern void dpmi_set_interrupt_vector(unsigned char num, INTDESC desc); extern void save_pm_regs(struct sigcontext_struct *); extern void restore_pm_regs(struct sigcontext_struct *); extern unsigned short AllocateDescriptors(int); extern int SetSelector(unsigned short selector, unsigned long base_addr, unsigned int limit, unsigned char is_32, unsigned char type, unsigned char readonly, unsigned char is_big, unsigned char seg_not_present, unsigned char useable); extern int FreeDescriptor(unsigned short selector); extern void FreeSegRegs(struct sigcontext_struct *scp, unsigned short selector); extern void dpmi_setup(void); extern void dpmi_cleanup(void); extern int lookup_realmode_callback(unsigned int lina, int *num); extern void dpmi_realmode_callback(int rmcb_client, int num); extern int get_ldt(void *buffer); void dpmi_return_request(void); void dpmi_return(struct sigcontext_struct *scp); int dpmi_check_return(struct sigcontext_struct *scp); void dpmi_init(void); extern void copy_context(struct sigcontext_struct *d, struct sigcontext_struct *s, int copy_fpu); extern inline unsigned short dpmi_sel(void); extern void pm_to_rm_regs(struct sigcontext_struct *scp, unsigned int mask); extern void rm_to_pm_regs(struct sigcontext_struct *scp, unsigned int mask); static inline int DPMIValidSelector(unsigned short selector) { /* does this selector refer to the LDT? */ #if MAX_SELECTORS < 8192 if (selector < (MAX_SELECTORS << 3)) return 0; #endif return Segments[selector >> 3].used != 0xfe && (selector & 4); } #endif /* DPMI_H */