📄 pm.c
字号:
;/****************************************************************************** SciTech OS Portability Manager Library** ========================================================================** The contents of this file are subject to the SciTech MGL Public* License Version 1.0 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.scitechsoft.com/mgl-license.txt** Software distributed under the License is distributed on an* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or* implied. See the License for the specific language governing* rights and limitations under the License.** The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.** The Initial Developer of the Original Code is SciTech Software, Inc.* All Rights Reserved.** ========================================================================** Portions copyright (C) Josh Vanderhoof** Language: ANSI C* Environment: Linux** Description: Implementation for the OS Portability Manager Library, which* contains functions to implement OS specific services in a* generic, cross platform API. Porting the OS Portability* Manager library is the first step to porting any SciTech* products to a new platform.*****************************************************************************/#include "pmapi.h"#include "drvlib/os/os.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/mman.h>#include <sys/kd.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/vt.h>#include <sys/wait.h>#include <sys/types.h>#include <sys/time.h>#include <unistd.h>#include <termios.h>#include <fcntl.h>#include <syscall.h>#include <signal.h>#include <time.h>#include <ctype.h>#include <errno.h>#include <asm/io.h>#include <asm/types.h>#ifdef ENABLE_MTRR#include <asm/mtrr.h>#endif#include <asm/vm86.h>#ifdef __GLIBC__#include <sys/perm.h>#endif/*--------------------------- Global variables ----------------------------*/#define REAL_MEM_BASE ((void *)0x10000)#define REAL_MEM_SIZE 0x10000#define REAL_MEM_BLOCKS 0x100#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK)#define DEFAULT_STACK_SIZE 0x1000#define RETURN_TO_32_INT 255/* Quick and dirty fix for vm86() syscall from lrmi 0.6 */static intvm86(struct vm86_struct *vm) { int r;#ifdef __PIC__ asm volatile ( "pushl %%ebx\n\t" "movl %2, %%ebx\n\t" "int $0x80\n\t" "popl %%ebx" : "=a" (r) : "0" (113), "r" (vm));#else asm volatile ( "int $0x80" : "=a" (r) : "0" (113), "b" (vm));#endif return r; }static struct { int ready; unsigned short ret_seg, ret_off; unsigned short stack_seg, stack_off; struct vm86_struct vm; } context = {0};struct mem_block { unsigned int size : 20; unsigned int free : 1; };static struct { int ready; int count; struct mem_block blocks[REAL_MEM_BLOCKS]; } mem_info = {0};int _PM_console_fd = -1;int _PM_leds = 0,_PM_modifiers = 0;static ibool inited = false;static int tty_vc = 0;static int console_count = 0;static int startup_vc;static int fd_mem = 0;static ibool in_raw_mode = false;#ifdef ENABLE_MTRRstatic int mtrr_fd;#endifstatic uint VESABuf_len = 1024; /* Length of the VESABuf buffer */static void *VESABuf_ptr = NULL; /* Near pointer to VESABuf */static uint VESABuf_rseg; /* Real mode segment of VESABuf */static uint VESABuf_roff; /* Real mode offset of VESABuf */#ifdef TRACE_IOstatic ulong traceAddr;#endifstatic void (PMAPIP fatalErrorCleanup)(void) = NULL;/*----------------------------- Implementation ----------------------------*/#ifdef TRACE_IOextern void printk(char *msg,...);#endifstatic inline void port_out(int value, int port){#ifdef TRACE_IO printk("%04X:%04X: outb.%04X <- %02X\n", traceAddr >> 16, traceAddr & 0xFFFF, (ushort)port, (uchar)value);#endif asm volatile ("outb %0,%1" ::"a" ((unsigned char) value), "d"((unsigned short) port));}static inline void port_outw(int value, int port){#ifdef TRACE_IO printk("%04X:%04X: outw.%04X <- %04X\n", traceAddr >> 16,traceAddr & 0xFFFF, (ushort)port, (ushort)value);#endif asm volatile ("outw %0,%1" ::"a" ((unsigned short) value), "d"((unsigned short) port));}static inline void port_outl(int value, int port){#ifdef TRACE_IO printk("%04X:%04X: outl.%04X <- %08X\n", traceAddr >> 16,traceAddr & 0xFFFF, (ushort)port, (ulong)value);#endif asm volatile ("outl %0,%1" ::"a" ((unsigned long) value), "d"((unsigned short) port));}static inline unsigned int port_in(int port){ unsigned char value; asm volatile ("inb %1,%0" :"=a" ((unsigned char)value) :"d"((unsigned short) port));#ifdef TRACE_IO printk("%04X:%04X: inb.%04X -> %02X\n", traceAddr >> 16,traceAddr & 0xFFFF, (ushort)port, (uchar)value);#endif return value;}static inline unsigned int port_inw(int port){ unsigned short value; asm volatile ("inw %1,%0" :"=a" ((unsigned short)value) :"d"((unsigned short) port));#ifdef TRACE_IO printk("%04X:%04X: inw.%04X -> %04X\n", traceAddr >> 16,traceAddr & 0xFFFF, (ushort)port, (ushort)value);#endif return value;}static inline unsigned int port_inl(int port){ unsigned long value; asm volatile ("inl %1,%0" :"=a" ((unsigned long)value) :"d"((unsigned short) port));#ifdef TRACE_IO printk("%04X:%04X: inl.%04X -> %08X\n", traceAddr >> 16,traceAddr & 0xFFFF, (ushort)port, (ulong)value);#endif return value;}static int real_mem_init(void){ void *m; int fd_zero; if (mem_info.ready) return 1; if ((fd_zero = open("/dev/zero", O_RDONLY)) == -1) PM_fatalError("You must have root privledges to run this program!"); if ((m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd_zero, 0)) == (void *)-1) { close(fd_zero); PM_fatalError("You must have root privledges to run this program!"); } mem_info.ready = 1; mem_info.count = 1; mem_info.blocks[0].size = REAL_MEM_SIZE; mem_info.blocks[0].free = 1; return 1;}static void insert_block(int i){ memmove( mem_info.blocks + i + 1, mem_info.blocks + i, (mem_info.count - i) * sizeof(struct mem_block)); mem_info.count++;}static void delete_block(int i){ mem_info.count--; memmove( mem_info.blocks + i, mem_info.blocks + i + 1, (mem_info.count - i) * sizeof(struct mem_block));}static inline void set_bit(unsigned int bit, void *array){ unsigned char *a = array; a[bit / 8] |= (1 << (bit % 8));}static inline unsigned int get_int_seg(int i){ return *(unsigned short *)(i * 4 + 2);}static inline unsigned int get_int_off(int i){ return *(unsigned short *)(i * 4);}static inline void pushw(unsigned short i){ struct vm86_regs *r = &context.vm.regs; r->esp -= 2; *(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i;}ibool PMAPI PM_haveBIOSAccess(void){ return true; }void PMAPI PM_init(void){ void *m; uint r_seg,r_off; if (inited) return; /* Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) * and the physical framebuffer and ROM images from (0xa0000 - 0x100000) */ real_mem_init(); if (!fd_mem && (fd_mem = open("/dev/mem", O_RDWR)) == -1) { PM_fatalError("You must have root privileges to run this program!"); } if ((m = mmap((void *)0, 0x502, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd_mem, 0)) == (void *)-1) { PM_fatalError("You must have root privileges to run this program!"); } if ((m = mmap((void *)0xA0000, 0xC0000 - 0xA0000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd_mem, 0xA0000)) == (void *)-1) { PM_fatalError("You must have root privileges to run this program!"); } if ((m = mmap((void *)0xC0000, 0xD0000 - 0xC0000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd_mem, 0xC0000)) == (void *)-1) { PM_fatalError("You must have root privileges to run this program!"); } if ((m = mmap((void *)0xD0000, 0x100000 - 0xD0000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd_mem, 0xD0000)) == (void *)-1) { PM_fatalError("You must have root privileges to run this program!"); } inited = 1; /* Allocate a stack */ m = PM_allocRealSeg(DEFAULT_STACK_SIZE,&r_seg,&r_off); context.stack_seg = r_seg; context.stack_off = r_off+DEFAULT_STACK_SIZE; /* Allocate the return to 32 bit routine */ m = PM_allocRealSeg(2,&r_seg,&r_off); context.ret_seg = r_seg; context.ret_off = r_off; ((uchar*)m)[0] = 0xCD; /* int opcode */ ((uchar*)m)[1] = RETURN_TO_32_INT; memset(&context.vm, 0, sizeof(context.vm)); /* Enable kernel emulation of all ints except RETURN_TO_32_INT */ memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored)); set_bit(RETURN_TO_32_INT, &context.vm.int_revectored); context.ready = 1;#ifdef ENABLE_MTRR mtrr_fd = open("/dev/cpu/mtrr", O_RDWR, 0); if (mtrr_fd < 0) mtrr_fd = open("/proc/mtrr", O_RDWR, 0);#endif /* Enable I/O permissions to directly access I/O ports. We break the * allocation into two parts, one for the ports from 0-0x3FF and * another for the remaining ports up to 0xFFFF. Standard Linux kernels * only allow the first 0x400 ports to be enabled, so to enable all * 65536 ports you need a patched kernel that will enable the full * 8Kb I/O permissions bitmap. */#ifndef TRACE_IO ioperm(0x0,0x400,1); ioperm(0x400,0x10000-0x400,1);#endif iopl(3);}long PMAPI PM_getOSType(void){ return _OS_LINUX; }int PMAPI PM_getModeType(void){ return PM_386; }void PMAPI PM_backslash(char *s){ uint pos = strlen(s); if (s[pos-1] != '/') { s[pos] = '/'; s[pos+1] = '\0'; }}void PMAPI PM_setFatalErrorCleanup( void (PMAPIP cleanup)(void)){ fatalErrorCleanup = cleanup;}void PMAPI PM_fatalError(const char *msg){ if (fatalErrorCleanup) fatalErrorCleanup(); fprintf(stderr,"%s\n", msg); fflush(stderr); exit(1);}static void ExitVBEBuf(void){ if (VESABuf_ptr) PM_freeRealSeg(VESABuf_ptr); VESABuf_ptr = 0;}void * PMAPI PM_getVESABuf(uint *len,uint *rseg,uint *roff){ if (!VESABuf_ptr) { /* Allocate a global buffer for communicating with the VESA VBE */ if ((VESABuf_ptr = PM_allocRealSeg(VESABuf_len, &VESABuf_rseg, &VESABuf_roff)) == NULL) return NULL; atexit(ExitVBEBuf); } *len = VESABuf_len; *rseg = VESABuf_rseg; *roff = VESABuf_roff; return VESABuf_ptr;}/* New raw console based getch and kbhit functions */#define KB_CAPS LED_CAP /* 4 */#define KB_NUMLOCK LED_NUM /* 2 */#define KB_SCROLL LED_SCR /* 1 */#define KB_SHIFT 8#define KB_CONTROL 16#define KB_ALT 32/* Structure used to save the keyboard mode to disk. We save it to disk * so that we can properly restore the mode later if the program crashed. */typedef struct { struct termios termios; int kb_mode; int leds; int flags; int startup_vc; } keyboard_mode;/* Name of the file used to save keyboard mode information */#define KBMODE_DAT "kbmode.dat"/****************************************************************************REMARKS:Open the keyboard mode file on disk.****************************************************************************/static FILE *open_kb_mode( char *mode, char *path){ if (!PM_findBPD("graphics.bpd",path)) return NULL; PM_backslash(path); strcat(path,KBMODE_DAT); return fopen(path,mode);}/****************************************************************************REMARKS:Restore the keyboard to normal mode****************************************************************************/void _PM_restore_kb_mode(void){ FILE *kbmode; keyboard_mode mode; char path[PM_MAX_PATH]; if (_PM_console_fd != -1 && (kbmode = open_kb_mode("rb",path)) != NULL) { if (fread(&mode,1,sizeof(mode),kbmode) == sizeof(mode)) { if (mode.startup_vc > 0) ioctl(_PM_console_fd, VT_ACTIVATE, mode.startup_vc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -