105b261ecSmrg 205b261ecSmrg INT10 X86 Real Mode executor 305b261ecSmrg ============================= 405b261ecSmrg 505b261ecSmrg PRELIMINARY 605b261ecSmrg 705b261ecSmrgINT10 is a XFree86 module for soft-booting and executing real mode 805b261ecSmrgint10 BIOS calls. The BIOS call code is largely untested, yet. 905b261ecSmrg 1005b261ecSmrg1. Usage 1105b261ecSmrg======== 1205b261ecSmrg 1305b261ecSmrgTo use the int10 module in a driver the header file 1405b261ecSmrgxfree86/os-support/int10/xf86int10.h must be included. 1505b261ecSmrg 1605b261ecSmrg a. Initialization 1705b261ecSmrg ----------------- 1805b261ecSmrg 1905b261ecSmrgThe int10-executer gets initialized by calling: 2005b261ecSmrg 2105b261ecSmrg xf86Int10InfoPtr xf86InitInt10(int entityIndex); 2205b261ecSmrg 2305b261ecSmrgThe function will soft-boot any non-primary device and return a 2405b261ecSmrgpointer to a xf86Int10InfoRec on success. If anything fails or if 2505b261ecSmrgint10 execution is disabled by an option in the device section NULL 2605b261ecSmrgwill be returned. The driver should store this pointer for later 2705b261ecSmrgcalls to other int10 module functions. 2805b261ecSmrg 2905b261ecSmrg b. Memory allocation 3005b261ecSmrg -------------------- 3105b261ecSmrg 3205b261ecSmrgTo allocate memory in the real mode execution environment 3305b261ecSmrg 3405b261ecSmrg void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off); 3505b261ecSmrg 3605b261ecSmrgcan be called. It allocates num consecutive pagesize chunks. It 3705b261ecSmrgreturns the address of the allocated area. off is set to its offset in 3805b261ecSmrgthe real mode memory space. 3905b261ecSmrg 4005b261ecSmrg void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num); 4105b261ecSmrg 4205b261ecSmrgIs used to free num pages beginning at pbase. 4305b261ecSmrg 4405b261ecSmrg c. Doing int10 BIOS calls 4505b261ecSmrg ------------------------- 4605b261ecSmrg 4705b261ecSmrgThe BIOS call is executed by calling: 4805b261ecSmrg 4905b261ecSmrg void xf86ExecX86int10(xf86Int10InfoPtr pInt); 5005b261ecSmrg 5105b261ecSmrgThe number of the interrupt (normally 10) and the initial values of 5205b261ecSmrgthe ax, bx, cx, dx, si, di and es x86-CPU registers can be set in the 5305b261ecSmrgxf86Int10InfoRec passed to the function. On return this structure 5405b261ecSmrgcontains the exit values of the registers listed above and the CPU 5505b261ecSmrgflag register. 5605b261ecSmrg 5705b261ecSmrg d. De-initializing 5805b261ecSmrg ----------------- 5905b261ecSmrg 6005b261ecSmrgIf no further int10 calls are required for a certain chipset 6105b261ecSmrgthe driver should call: 6205b261ecSmrg 6305b261ecSmrg void xf86FreeInt10(xf86Int10InfoPtr pInt); 6405b261ecSmrg 6505b261ecSmrgto free the memory allocated for real mode int10 calls. 6605b261ecSmrg 6705b261ecSmrg 6805b261ecSmrg2. Porting issues 6905b261ecSmrg================= 7005b261ecSmrg 7105b261ecSmrgThe int10 real mode executor is designed to run on top of various x86 7205b261ecSmrgCPU emulators as well as in vm86 mode of a real x86 CPU. If used with 7305b261ecSmrga CPU emulator the emulator and CPU specific interfaces can be held 7405b261ecSmrgseparate thus requiring minimal efforts to port the int10 module to 7505b261ecSmrgnew platforms. Currently an interface to the x86emu real mode 7605b261ecSmrgemulator is provided. Since details of setting up and running the 7705b261ecSmrgvm86 mode is platform dependent both the platform dependent 7805b261ecSmrgenvironment and the emulation layer have to be ported. Several helper 7905b261ecSmrgfunctions are provided for that. 8005b261ecSmrg 8105b261ecSmrgA CPU emulator should meet certain requirements to be usable 8205b261ecSmrgfor the INT10 executor: 8305b261ecSmrg 8405b261ecSmrg1. It must trap calls to intXX instructions and pass execution to an 8505b261ecSmrg external function which is allowed to modify CPU registers 8605b261ecSmrg including the instruction pointer (IP) before returning to the 8705b261ecSmrg emulator for continuing execution. When the external function is 8805b261ecSmrg called the IP must point to the instruction past the intXX call. 8905b261ecSmrg 9005b261ecSmrg2. The emulator should use externally provided functions to handle 9105b261ecSmrg PIO. 9205b261ecSmrg 9305b261ecSmrg3. The emulator should be able to use externally provided functions 9405b261ecSmrg to access memory from the real mode memory environment. Note, that 9505b261ecSmrg the vm86 mode usually requires one hunk of consecutive memory 9605b261ecSmrg starting at address 0 in the process virtual memory space. Thus if 9705b261ecSmrg this mode is to be used, the OS environment has to be able to provide 9805b261ecSmrg that, ie. it must be able to remap the processes virtual memory space 99ed6184dfSmrg onto itself. If the emulator is able to handle memory access through 10005b261ecSmrg externally provided functions the real mode process memory can be 10105b261ecSmrg located anywhere in the processes virtual memory. It does not even 10205b261ecSmrg have to be consecutive. 10305b261ecSmrg 10405b261ecSmrg4. The executor should terminate on encountering a 'hlt' instruction. 10505b261ecSmrg 10605b261ecSmrg 10705b261ecSmrgFunctions to implement: 10805b261ecSmrg 10905b261ecSmrgTo simplify development the code has been split into a general setup 11005b261ecSmrgpart and an emulator specific one. A generic setup code is provided in 11105b261ecSmrggeneric.c. It should be usable with any emulator satisfying the 11205b261ecSmrgconditions mentioned above. Therefore the following section on int10 11305b261ecSmrgsetup may be skipped when porting int10 to new emulator. 11405b261ecSmrg 11505b261ecSmrgIf the vm86() is to be used no memory access functions can be used. 11605b261ecSmrgTherefore the layout of the real mode memory image has to meet certain 11705b261ecSmrgrequirements. Therefore when porting to other platforms a new setup 11805b261ecSmrgcode may have to be designed, too. The following section will give 11905b261ecSmrgguidelines how this may be done. A sample implementation using SysV 12005b261ecSmrgIPC to map the appropriate real mode memory image to address 0 in 12105b261ecSmrgvirtual address space just prior to execution may be found in 12205b261ecSmrgxfree86/os-support/linux/int10/linux.c. 12305b261ecSmrg 12405b261ecSmrgOn non-PC like platforms emulation of certain PC features such as 12505b261ecSmrginitialization of BIOS int vectors, sys_BIOS constants or PCI config 12605b261ecSmrgmethod 1 can be turned on by defining _PC. 12705b261ecSmrg 12805b261ecSmrgI. Setup Code 12905b261ecSmrg------------- 13005b261ecSmrg 13105b261ecSmrgThis sets up the real mode memory image, calls the emulator to POST 13205b261ecSmrgthe chipset if required and maintains memory allocations in real mode 13305b261ecSmrgaddress space. 13405b261ecSmrg 13505b261ecSmrg1. xf86Int10InfoPtr xf86InitInt10(int entityIndex); 13605b261ecSmrg 13705b261ecSmrgThis function should first find the screen assigned to the entity 13805b261ecSmrgcarrying entitiyIndex and then call 13905b261ecSmrg 14005b261ecSmrg Bool int10skip(ScrnInfoPtr pScrn) 14105b261ecSmrg 14205b261ecSmrgto find out if the user has requested not to initialize int10. If so 14305b261ecSmrgxf86InitInt10() should return NULL. Otherwise an xf86Int10InfoRec 14405b261ecSmrgshould be allocated. This structure contains the following fields: 14505b261ecSmrg 14605b261ecSmrg a. int entityIndex - index of the entity whose BIOS is to be 14705b261ecSmrg executed. 14805b261ecSmrg b. int scrnIndex - index of the screen assigned the entity. 14905b261ecSmrg c. pointer cpuRegs - pointer to a emulator/vm86-mode private 15005b261ecSmrg structure. May hold cpu register values 15105b261ecSmrg for the emulator. 15205b261ecSmrg d. CARD16 BIOSseg - Video BIOS segment address. 15305b261ecSmrg e. pointer private - pointer to a os specific data structure. 15405b261ecSmrg f. struct _int10Mem* - pointer to a structure to hold the memory 15505b261ecSmrg access functions for use by an emulator. 15605b261ecSmrg g. int num - number of the int to be called. 15705b261ecSmrg h. int ax..es,flags - CPU register values to pass to int-call. 15805b261ecSmrg 15905b261ecSmrgThe Init function should initialize a-f. To initialize the emulator 16005b261ecSmrgspecific execute environment the function 16105b261ecSmrg 16205b261ecSmrg Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt) 16305b261ecSmrg 16405b261ecSmrgshould be called. If this function returns FALSE any already allocated 16505b261ecSmrgmemory should be freed and xf86Int10Init(0 should exit returning NULL. 16605b261ecSmrg 16705b261ecSmrgIf the platform has a PC like system BIOS it may be copied to or 16805b261ecSmrgmapped into memory locations SYS_BIOS to SYS_SIZE-1 of the real mode 16905b261ecSmrgmemory environment of this process. Otherwise the helper function: 17005b261ecSmrg 17105b261ecSmrgint setup_system_bios(CARD32 base_addr); 17205b261ecSmrg 17305b261ecSmrgmay be called to set up a rudimentary system BIOS sufficient to be 17405b261ecSmrgused to boot video BIOSes. base_addr specifies the virtual address 17505b261ecSmrgcorresponding to SYS_BIOS in the real mode environment. If a PC-like 17605b261ecSmrgint vector and BIOS data area is available it should be copied to 0 to 17705b261ecSmrgLOW_PAGE_SIZE of the entities real mode environment. In this case the 17805b261ecSmrgvideo interrupt related entries should be reset for all non-primary 17905b261ecSmrgcards by calling: 18005b261ecSmrg 18105b261ecSmrgvoid reset_int_vect(xf86Int10InfoPtr pInt); To initialize the 18205b261ecSmrg 18305b261ecSmrgcorrect video BIOS entry points the BIOS must be warm-booted. If no 18405b261ecSmrgPC-like int vector is available one can be set up by calling 18505b261ecSmrg 18605b261ecSmrgvoid setup_int_vect(xf86Int10InfoPtr pInt); 18705b261ecSmrg 18805b261ecSmrgIn this case the video BIOS has to be warm-booted always. If the 18905b261ecSmrgvideo BIOS for this entity has been installed during boot it may be 19005b261ecSmrgmapped (or copied) directly to the correct address in the real mode 19105b261ecSmrgmemory environment. Otherwise 19205b261ecSmrg 19305b261ecSmrgint mapPciRom(xf86Int10InfoPtr pInt, unsigned char * address); 19405b261ecSmrg 19505b261ecSmrgshould be called to copy the BIOS image from PCI ROM. 'address' 19605b261ecSmrgspecifies the address this image should be copied to. Sufficient space 19705b261ecSmrgto hold an entire BIOS image should be allocated prior to calling 19805b261ecSmrgmapPciRom(). This function will return the size of the BIOS image in 19905b261ecSmrgbytes if it was able to successfully copy the image and 0 20005b261ecSmrgotherwise. To create a well defined point to exit the softbooter 20105b261ecSmrg 20205b261ecSmrgvoid set_return_trap(xf86Int10Ptr pInt); 20305b261ecSmrg 20405b261ecSmrgmay be called. It sets up a 'hlt' instruction in the emulator memory 20505b261ecSmrgjust above the BIOS variable area. Before entering real mode execution 20605b261ecSmrgthis address will be pushed onto the return stack. If the BIOS needs 20705b261ecSmrgto be warm-booted this should be done before leaving xf86InitInt10() 20805b261ecSmrgby setting num in the xf86Int10InfoRec to 0xe6 and calling 20905b261ecSmrg 21005b261ecSmrgvoid xf86ExecX86int10(xf86Int10IfoPtr pInt); 21105b261ecSmrg 21205b261ecSmrgThe implementation of this function will be discussed below. This 21305b261ecSmrgfunction should be wrapped by calls to void LockLegacyVGA(screen, 21405b261ecSmrglegacyVGAPtr vga); and void UnlockLegacyVGA(screen, legacyVGAPtr vga); 21505b261ecSmrgThe struct vga is used to hold the state of the legacy VGA access 21605b261ecSmrgregisters if a legacy VGA device exists. xf86InitInt10() should 21705b261ecSmrgreturn a pointer to the xf86Int10InfoRec allocated. 21805b261ecSmrg 21905b261ecSmrg2. Bool MapCurrentInt10(xf86Int10InfoPtr pInt); 22005b261ecSmrg 22105b261ecSmrgIn case a platform specific mapping has to be performed to map the 22205b261ecSmrgmemory allocated for the real mode memory environment into a specific 22305b261ecSmrglocation prior to executing the x86 real mode code a function 22405b261ecSmrg 22505b261ecSmrg Bool MapCurrentInt10(xf86Int10InfoPtr pInt); 22605b261ecSmrg 22705b261ecSmrghas to be provided. It will be called by a helper function whenever 22805b261ecSmrgthe active entity changes. If the vm86 mode is used it is most likely 22905b261ecSmrgthat the 1MB real mode memory space located somewhere in the processes 23005b261ecSmrgvirtual memory will have to be remapped to address 0 of the virtual 23105b261ecSmrgmemory space. 23205b261ecSmrg 23305b261ecSmrg3. void xf86FreeInt10(xf86Int10InfoPtr pInt); 23405b261ecSmrg 23505b261ecSmrgTo free all memory allocated for video BIOS calls of a specific entity 23605b261ecSmrgthe function 23705b261ecSmrg 23805b261ecSmrg void xf86FreeInt10(xf86Int10InfoPtr pInt); 23905b261ecSmrg 24005b261ecSmrgshould be provided. If the entity to be freed was mapped by 24105b261ecSmrgMapCurrentInt10() this mapping needs to be undone also. 24205b261ecSmrg 24305b261ecSmrg4. 24405b261ecSmrg void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off) 24505b261ecSmrg void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num) 24605b261ecSmrg 24705b261ecSmrgxf86Int10AllocPages() should allocate 'num' consecutive page-size 24805b261ecSmrgchunks of memory. In real mode memory space this range needs to occupy 24905b261ecSmrgconsecutive addresses, too. The function must return the address of 25005b261ecSmrgthis memory. The offset in real mode memory needs to be returned in 25105b261ecSmrg'off'. If no block of 'num' pages are available the function should 25205b261ecSmrgreturn NULL. 25305b261ecSmrg 25405b261ecSmrgxf86Int10FreePages() will free the 'num' pages starting at 'pbase'. 25505b261ecSmrg'num' is equal to the number of pages allocated by a single 25605b261ecSmrgxf86Int10AllocatePages() call. 'pbase' is the address of the range 25705b261ecSmrgpreviously returned by xf86Int10AllocatePages(). 25805b261ecSmrg 25905b261ecSmrgII. Emulator specific functions 26005b261ecSmrg------------------------------- 26105b261ecSmrg 26205b261ecSmrg1. Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt); 26305b261ecSmrg 26405b261ecSmrgThis function will be called from xf86InitInt10(). It may be used to 26505b261ecSmrgset up the static emulator specific part of the real mode 26605b261ecSmrgenvironment. On success it should return TRUE. 26705b261ecSmrg 26805b261ecSmrg2. xf86ExecX86int10(xf86Int10InfoPtr pInt); 26905b261ecSmrg 27005b261ecSmrgThis function gets called to execute an int call. It may call the 27105b261ecSmrghelper function: 27205b261ecSmrg 27305b261ecSmrg void setup_int(xf86Int10InfoPrt pInt); 27405b261ecSmrg 27505b261ecSmrgto copy the register values to the emulator specific locations and to 27605b261ecSmrgset up the non-static real mode execution environment. On return from 27705b261ecSmrgsetup_int() 'Int10Current' holds a pointer to the current 27805b261ecSmrgxf86Int10InfoRec. 27905b261ecSmrg 28005b261ecSmrgIt should start execution by calling 28105b261ecSmrg 28205b261ecSmrg Bool int_handler(xf86Int10InfoPtr pInt); 28305b261ecSmrg 28405b261ecSmrgand if this function returns TRUE it should call whatever necessary to 28505b261ecSmrgcontinue execution until a 'hlt' instruction is encountered. To copy 28605b261ecSmrgthe resulting register values back to the xf86Int10InfoRec structure 28705b261ecSmrg 28805b261ecSmrg void finish_int(xf86Int10InfoPtr pInt); 28905b261ecSmrg 29005b261ecSmrgshould be called. 29105b261ecSmrg 29205b261ecSmrgHelper functions are provided to aid the implementation of a vm86 29305b261ecSmrgcall: 29405b261ecSmrg 29505b261ecSmrg Bool vm86_GP_fault(xf86Int10InfoPtr pInt); 29605b261ecSmrg 29705b261ecSmrgThis function handles instructions which cause a vm86 call to 29805b261ecSmrgtrap. PIO access is handled by the in/out calls as defined in 29905b261ecSmrgcompiler.h. Optionally the PIO instructions can be logged by defining 30005b261ecSmrgPRINT_PORT in xf86int10.h. This is meant for debugging purposes. 30105b261ecSmrg 30205b261ecSmrgUnknown instructions and 'hlt' cause vm86_GP_fault() to return 30305b261ecSmrgFALSE. Otherwise TRUE is returned. 30405b261ecSmrg 30505b261ecSmrgNote: This function is currently based on the Linux vm86 call. It 30605b261ecSmrgmight have to be modified or even rewritten for other OS. So your 307ed6184dfSmrgmileage may vary. 30805b261ecSmrg 30905b261ecSmrgFunctions to dump memory, code, xf86 CPU register values and stack are 31005b261ecSmrgalso provided. Take a look at helper.c To view a memory range the 31105b261ecSmrgfunction 31205b261ecSmrg 31305b261ecSmrg void dprint(unsigned long start, unsigned long size) 31405b261ecSmrg 31505b261ecSmrgis provided. The use should be self explanatory. 31605b261ecSmrg 31705b261ecSmrgRegister and memory access functions are provided in helper_mem.c. 31805b261ecSmrgThe PIO register access functions can trap access to PCI config space 31905b261ecSmrgaccess register (config method 1) if _PC is not defined. 32005b261ecSmrg 32105b261ecSmrgA header file 'defines.h' is required to define OS/emulator specific 32205b261ecSmrgways to access memory and xf86 CPU registers: Defines need to be 32305b261ecSmrgprovided for memory byte/work/long read/write access 32405b261ecSmrg(MEM_RB(name,addr),MEM_RW(name,addr),MEM_RL(name,addr), 32505b261ecSmrgMEM_WB(name,addr,val),MEM_WL(name,addr,val),MEM_WL(name,addr,val)) of 32605b261ecSmrgthe real mode memory environment. 'name' will contain a pointer to the 32705b261ecSmrgcurrent xf86Int10InfoRec. Currently defines are available for 32805b261ecSmrgvm86-mode under Linux and x86emu. They may be activated by defining 32905b261ecSmrg_X86EMU or _VM86_LINUX respectively. 33005b261ecSmrg 33105b261ecSmrgNote: Emulators usually are not able to pass this pointer when calling 33205b261ecSmrgmemory access functions. In this case a global variable should be 33305b261ecSmrgdefined which can hold this pointer. This variable can be set in 33405b261ecSmrgMapCurrentInt10(). It also must be set in xf86InitInt10() if this 33505b261ecSmrgfunction calls the memory access functions either directly or by 33605b261ecSmrgcalling xf86ExecX86int10(pInt). Defines to access the emulator 33705b261ecSmrgspecific xf86 CPU register locations are also required: 33805b261ecSmrgX86_EAX,...,X86_EFLAGS for access of the full 32 bit registers, 33905b261ecSmrgX86_AX...X86_FLAGS for access of the 16 bit registers and 34005b261ecSmrgXF86_AL,XF86_BL,XF86_CL,XF86_DL to access the lower byte of the 34105b261ecSmrgAX,BX,CX and DX register. 34205b261ecSmrg 34305b261ecSmrg 34405b261ecSmrg$XFree86: xc/programs/Xserver/hw/xfree86/int10/INT10.HOWTO,v 1.2 2000/02/08 13:13:22 eich Exp $ 345