1706f2543Smrg 2706f2543Smrg INT10 X86 Real Mode executor 3706f2543Smrg ============================= 4706f2543Smrg 5706f2543Smrg PRELIMINARY 6706f2543Smrg 7706f2543SmrgINT10 is a XFree86 module for soft-booting and executing real mode 8706f2543Smrgint10 BIOS calls. The BIOS call code is largely untested, yet. 9706f2543Smrg 10706f2543Smrg1. Usage 11706f2543Smrg======== 12706f2543Smrg 13706f2543SmrgTo use the int10 module in a driver the header file 14706f2543Smrgxfree86/os-support/int10/xf86int10.h must be included. 15706f2543Smrg 16706f2543Smrg a. Initialization 17706f2543Smrg ----------------- 18706f2543Smrg 19706f2543SmrgThe int10-executer gets initialized by calling: 20706f2543Smrg 21706f2543Smrg xf86Int10InfoPtr xf86InitInt10(int entityIndex); 22706f2543Smrg 23706f2543SmrgThe function will soft-boot any non-primary device and return a 24706f2543Smrgpointer to a xf86Int10InfoRec on success. If anything fails or if 25706f2543Smrgint10 execution is disabled by an option in the device section NULL 26706f2543Smrgwill be returned. The driver should store this pointer for later 27706f2543Smrgcalls to other int10 module functions. 28706f2543Smrg 29706f2543Smrg b. Memory allocation 30706f2543Smrg -------------------- 31706f2543Smrg 32706f2543SmrgTo allocate memory in the real mode execution environment 33706f2543Smrg 34706f2543Smrg void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off); 35706f2543Smrg 36706f2543Smrgcan be called. It allocates num consecutive pagesize chunks. It 37706f2543Smrgreturns the address of the allocated area. off is set to its offset in 38706f2543Smrgthe real mode memory space. 39706f2543Smrg 40706f2543Smrg void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num); 41706f2543Smrg 42706f2543SmrgIs used to free num pages beginning at pbase. 43706f2543Smrg 44706f2543Smrg c. Doing int10 BIOS calls 45706f2543Smrg ------------------------- 46706f2543Smrg 47706f2543SmrgThe BIOS call is executed by calling: 48706f2543Smrg 49706f2543Smrg void xf86ExecX86int10(xf86Int10InfoPtr pInt); 50706f2543Smrg 51706f2543SmrgThe number of the interrupt (normally 10) and the initial values of 52706f2543Smrgthe ax, bx, cx, dx, si, di and es x86-CPU registers can be set in the 53706f2543Smrgxf86Int10InfoRec passed to the function. On return this structure 54706f2543Smrgcontains the exit values of the registers listed above and the CPU 55706f2543Smrgflag register. 56706f2543Smrg 57706f2543Smrg d. De-initializing 58706f2543Smrg ----------------- 59706f2543Smrg 60706f2543SmrgIf no further int10 calls are required for a certain chipset 61706f2543Smrgthe driver should call: 62706f2543Smrg 63706f2543Smrg void xf86FreeInt10(xf86Int10InfoPtr pInt); 64706f2543Smrg 65706f2543Smrgto free the memory allocated for real mode int10 calls. 66706f2543Smrg 67706f2543Smrg 68706f2543Smrg2. Porting issues 69706f2543Smrg================= 70706f2543Smrg 71706f2543SmrgThe int10 real mode executor is designed to run on top of various x86 72706f2543SmrgCPU emulators as well as in vm86 mode of a real x86 CPU. If used with 73706f2543Smrga CPU emulator the emulator and CPU specific interfaces can be held 74706f2543Smrgseparate thus requiring minimal efforts to port the int10 module to 75706f2543Smrgnew platforms. Currently an interface to the x86emu real mode 76706f2543Smrgemulator is provided. Since details of setting up and running the 77706f2543Smrgvm86 mode is platform dependent both the platform dependent 78706f2543Smrgenvironment and the emulation layer have to be ported. Several helper 79706f2543Smrgfunctions are provided for that. 80706f2543Smrg 81706f2543SmrgA CPU emulator should meet certain requirements to be usable 82706f2543Smrgfor the INT10 executor: 83706f2543Smrg 84706f2543Smrg1. It must trap calls to intXX instructions and pass execution to an 85706f2543Smrg external function which is allowed to modify CPU registers 86706f2543Smrg including the instruction pointer (IP) before returning to the 87706f2543Smrg emulator for continuing execution. When the external function is 88706f2543Smrg called the IP must point to the instruction past the intXX call. 89706f2543Smrg 90706f2543Smrg2. The emulator should use externally provided functions to handle 91706f2543Smrg PIO. 92706f2543Smrg 93706f2543Smrg3. The emulator should be able to use externally provided functions 94706f2543Smrg to access memory from the real mode memory environment. Note, that 95706f2543Smrg the vm86 mode usually requires one hunk of consecutive memory 96706f2543Smrg starting at address 0 in the process virtual memory space. Thus if 97706f2543Smrg this mode is to be used, the OS environment has to be able to provide 98706f2543Smrg that, ie. it must be able to remap the processes virtual memory space 99706f2543Smrg onto itself. If the emulator is able to handle memory access thru 100706f2543Smrg externally provided functions the real mode process memory can be 101706f2543Smrg located anywhere in the processes virtual memory. It does not even 102706f2543Smrg have to be consecutive. 103706f2543Smrg 104706f2543Smrg4. The executor should terminate on encountering a 'hlt' instruction. 105706f2543Smrg 106706f2543Smrg 107706f2543SmrgFunctions to implement: 108706f2543Smrg 109706f2543SmrgTo simplify development the code has been split into a general setup 110706f2543Smrgpart and an emulator specific one. A generic setup code is provided in 111706f2543Smrggeneric.c. It should be usable with any emulator satisfying the 112706f2543Smrgconditions mentioned above. Therefore the following section on int10 113706f2543Smrgsetup may be skipped when porting int10 to new emulator. 114706f2543Smrg 115706f2543SmrgIf the vm86() is to be used no memory access functions can be used. 116706f2543SmrgTherefore the layout of the real mode memory image has to meet certain 117706f2543Smrgrequirements. Therefore when porting to other platforms a new setup 118706f2543Smrgcode may have to be designed, too. The following section will give 119706f2543Smrgguidelines how this may be done. A sample implementation using SysV 120706f2543SmrgIPC to map the appropriate real mode memory image to address 0 in 121706f2543Smrgvirtual address space just prior to execution may be found in 122706f2543Smrgxfree86/os-support/linux/int10/linux.c. 123706f2543Smrg 124706f2543SmrgOn non-PC like platforms emulation of certain PC features such as 125706f2543Smrginitialization of BIOS int vectors, sys_BIOS constants or PCI config 126706f2543Smrgmethod 1 can be turned on by defining _PC. 127706f2543Smrg 128706f2543SmrgI. Setup Code 129706f2543Smrg------------- 130706f2543Smrg 131706f2543SmrgThis sets up the real mode memory image, calls the emulator to POST 132706f2543Smrgthe chipset if required and maintains memory allocations in real mode 133706f2543Smrgaddress space. 134706f2543Smrg 135706f2543Smrg1. xf86Int10InfoPtr xf86InitInt10(int entityIndex); 136706f2543Smrg 137706f2543SmrgThis function should first find the screen assigned to the entity 138706f2543Smrgcarrying entitiyIndex and then call 139706f2543Smrg 140706f2543Smrg Bool int10skip(ScrnInfoPtr pScrn) 141706f2543Smrg 142706f2543Smrgto find out if the user has requested not to initialize int10. If so 143706f2543Smrgxf86InitInt10() should return NULL. Otherwise an xf86Int10InfoRec 144706f2543Smrgshould be allocated. This structure contains the following fields: 145706f2543Smrg 146706f2543Smrg a. int entityIndex - index of the entity whose BIOS is to be 147706f2543Smrg executed. 148706f2543Smrg b. int scrnIndex - index of the screen assigned the entity. 149706f2543Smrg c. pointer cpuRegs - pointer to a emulator/vm86-mode private 150706f2543Smrg structure. May hold cpu register values 151706f2543Smrg for the emulator. 152706f2543Smrg d. CARD16 BIOSseg - Video BIOS segment address. 153706f2543Smrg e. pointer private - pointer to a os specific data structure. 154706f2543Smrg f. struct _int10Mem* - pointer to a structure to hold the memory 155706f2543Smrg access functions for use by an emulator. 156706f2543Smrg g. int num - number of the int to be called. 157706f2543Smrg h. int ax..es,flags - CPU register values to pass to int-call. 158706f2543Smrg 159706f2543SmrgThe Init function should initialize a-f. To initialize the emulator 160706f2543Smrgspecific execute environment the function 161706f2543Smrg 162706f2543Smrg Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt) 163706f2543Smrg 164706f2543Smrgshould be called. If this function returns FALSE any already allocated 165706f2543Smrgmemory should be freed and xf86Int10Init(0 should exit returning NULL. 166706f2543Smrg 167706f2543SmrgIf the platform has a PC like system BIOS it may be copied to or 168706f2543Smrgmapped into memory locations SYS_BIOS to SYS_SIZE-1 of the real mode 169706f2543Smrgmemory environment of this process. Otherwise the helper function: 170706f2543Smrg 171706f2543Smrgint setup_system_bios(CARD32 base_addr); 172706f2543Smrg 173706f2543Smrgmay be called to set up a rudimentary system BIOS sufficient to be 174706f2543Smrgused to boot video BIOSes. base_addr specifies the virtual address 175706f2543Smrgcorresponding to SYS_BIOS in the real mode environment. If a PC-like 176706f2543Smrgint vector and BIOS data area is available it should be copied to 0 to 177706f2543SmrgLOW_PAGE_SIZE of the entities real mode environment. In this case the 178706f2543Smrgvideo interrupt related entries should be reset for all non-primary 179706f2543Smrgcards by calling: 180706f2543Smrg 181706f2543Smrgvoid reset_int_vect(xf86Int10InfoPtr pInt); To initialize the 182706f2543Smrg 183706f2543Smrgcorrect video BIOS entry points the BIOS must be warm-booted. If no 184706f2543SmrgPC-like int vector is available one can be set up by calling 185706f2543Smrg 186706f2543Smrgvoid setup_int_vect(xf86Int10InfoPtr pInt); 187706f2543Smrg 188706f2543SmrgIn this case the video BIOS has to be warm-booted always. If the 189706f2543Smrgvideo BIOS for this entity has been installed during boot it may be 190706f2543Smrgmapped (or copied) directly to the correct address in the real mode 191706f2543Smrgmemory environment. Otherwise 192706f2543Smrg 193706f2543Smrgint mapPciRom(xf86Int10InfoPtr pInt, unsigned char * address); 194706f2543Smrg 195706f2543Smrgshould be called to copy the BIOS image from PCI ROM. 'address' 196706f2543Smrgspecifies the address this image should be copied to. Sufficient space 197706f2543Smrgto hold an entire BIOS image should be allocated prior to calling 198706f2543SmrgmapPciRom(). This function will return the size of the BIOS image in 199706f2543Smrgbytes if it was able to successfully copy the image and 0 200706f2543Smrgotherwise. To create a well defined point to exit the softbooter 201706f2543Smrg 202706f2543Smrgvoid set_return_trap(xf86Int10Ptr pInt); 203706f2543Smrg 204706f2543Smrgmay be called. It sets up a 'hlt' instruction in the emulator memory 205706f2543Smrgjust above the BIOS variable area. Before entering real mode execution 206706f2543Smrgthis address will be pushed onto the return stack. If the BIOS needs 207706f2543Smrgto be warm-booted this should be done before leaving xf86InitInt10() 208706f2543Smrgby setting num in the xf86Int10InfoRec to 0xe6 and calling 209706f2543Smrg 210706f2543Smrgvoid xf86ExecX86int10(xf86Int10IfoPtr pInt); 211706f2543Smrg 212706f2543SmrgThe implementation of this function will be discussed below. This 213706f2543Smrgfunction should be wrapped by calls to void LockLegacyVGA(screen, 214706f2543SmrglegacyVGAPtr vga); and void UnlockLegacyVGA(screen, legacyVGAPtr vga); 215706f2543SmrgThe struct vga is used to hold the state of the legacy VGA access 216706f2543Smrgregisters if a legacy VGA device exists. xf86InitInt10() should 217706f2543Smrgreturn a pointer to the xf86Int10InfoRec allocated. 218706f2543Smrg 219706f2543Smrg2. Bool MapCurrentInt10(xf86Int10InfoPtr pInt); 220706f2543Smrg 221706f2543SmrgIn case a platform specific mapping has to be performed to map the 222706f2543Smrgmemory allocated for the real mode memory environment into a specific 223706f2543Smrglocation prior to executing the x86 real mode code a function 224706f2543Smrg 225706f2543Smrg Bool MapCurrentInt10(xf86Int10InfoPtr pInt); 226706f2543Smrg 227706f2543Smrghas to be provided. It will be called by a helper function whenever 228706f2543Smrgthe active entity changes. If the vm86 mode is used it is most likely 229706f2543Smrgthat the 1MB real mode memory space located somewhere in the processes 230706f2543Smrgvirtual memory will have to be remapped to address 0 of the virtual 231706f2543Smrgmemory space. 232706f2543Smrg 233706f2543Smrg3. void xf86FreeInt10(xf86Int10InfoPtr pInt); 234706f2543Smrg 235706f2543SmrgTo free all memory allocated for video BIOS calls of a specific entity 236706f2543Smrgthe function 237706f2543Smrg 238706f2543Smrg void xf86FreeInt10(xf86Int10InfoPtr pInt); 239706f2543Smrg 240706f2543Smrgshould be provided. If the entity to be freed was mapped by 241706f2543SmrgMapCurrentInt10() this mapping needs to be undone also. 242706f2543Smrg 243706f2543Smrg4. 244706f2543Smrg void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off) 245706f2543Smrg void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num) 246706f2543Smrg 247706f2543Smrgxf86Int10AllocPages() should allocate 'num' consecutive page-size 248706f2543Smrgchunks of memory. In real mode memory space this range needs to occupy 249706f2543Smrgconsecutive addresses, too. The function must return the address of 250706f2543Smrgthis memory. The offset in real mode memory needs to be returned in 251706f2543Smrg'off'. If no block of 'num' pages are available the function should 252706f2543Smrgreturn NULL. 253706f2543Smrg 254706f2543Smrgxf86Int10FreePages() will free the 'num' pages starting at 'pbase'. 255706f2543Smrg'num' is equal to the number of pages allocated by a single 256706f2543Smrgxf86Int10AllocatePages() call. 'pbase' is the address of the range 257706f2543Smrgpreviously returned by xf86Int10AllocatePages(). 258706f2543Smrg 259706f2543SmrgII. Emulator specific functions 260706f2543Smrg------------------------------- 261706f2543Smrg 262706f2543Smrg1. Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt); 263706f2543Smrg 264706f2543SmrgThis function will be called from xf86InitInt10(). It may be used to 265706f2543Smrgset up the static emulator specific part of the real mode 266706f2543Smrgenvironment. On success it should return TRUE. 267706f2543Smrg 268706f2543Smrg2. xf86ExecX86int10(xf86Int10InfoPtr pInt); 269706f2543Smrg 270706f2543SmrgThis function gets called to execute an int call. It may call the 271706f2543Smrghelper function: 272706f2543Smrg 273706f2543Smrg void setup_int(xf86Int10InfoPrt pInt); 274706f2543Smrg 275706f2543Smrgto copy the register values to the emulator specific locations and to 276706f2543Smrgset up the non-static real mode execution environment. On return from 277706f2543Smrgsetup_int() 'Int10Current' holds a pointer to the current 278706f2543Smrgxf86Int10InfoRec. 279706f2543Smrg 280706f2543SmrgIt should start execution by calling 281706f2543Smrg 282706f2543Smrg Bool int_handler(xf86Int10InfoPtr pInt); 283706f2543Smrg 284706f2543Smrgand if this function returns TRUE it should call whatever necessary to 285706f2543Smrgcontinue execution until a 'hlt' instruction is encountered. To copy 286706f2543Smrgthe resulting register values back to the xf86Int10InfoRec structure 287706f2543Smrg 288706f2543Smrg void finish_int(xf86Int10InfoPtr pInt); 289706f2543Smrg 290706f2543Smrgshould be called. 291706f2543Smrg 292706f2543SmrgHelper functions are provided to aid the implementation of a vm86 293706f2543Smrgcall: 294706f2543Smrg 295706f2543Smrg Bool vm86_GP_fault(xf86Int10InfoPtr pInt); 296706f2543Smrg 297706f2543SmrgThis function handles instructions which cause a vm86 call to 298706f2543Smrgtrap. PIO access is handled by the in/out calls as defined in 299706f2543Smrgcompiler.h. Optionally the PIO instructions can be logged by defining 300706f2543SmrgPRINT_PORT in xf86int10.h. This is meant for debugging purposes. 301706f2543Smrg 302706f2543SmrgUnknown instructions and 'hlt' cause vm86_GP_fault() to return 303706f2543SmrgFALSE. Otherwise TRUE is returned. 304706f2543Smrg 305706f2543SmrgNote: This function is currently based on the Linux vm86 call. It 306706f2543Smrgmight have to be modified or even rewritten for other OS. So your 307706f2543Smrgmilage may vary. 308706f2543Smrg 309706f2543SmrgFunctions to dump memory, code, xf86 CPU register values and stack are 310706f2543Smrgalso provided. Take a look at helper.c To view a memory range the 311706f2543Smrgfunction 312706f2543Smrg 313706f2543Smrg void dprint(unsigned long start, unsigned long size) 314706f2543Smrg 315706f2543Smrgis provided. The use should be self explanatory. 316706f2543Smrg 317706f2543SmrgRegister and memory access functions are provided in helper_mem.c. 318706f2543SmrgThe PIO register access functions can trap access to PCI config space 319706f2543Smrgaccess register (config method 1) if _PC is not defined. 320706f2543Smrg 321706f2543SmrgA header file 'defines.h' is required to define OS/emulator specific 322706f2543Smrgways to access memory and xf86 CPU registers: Defines need to be 323706f2543Smrgprovided for memory byte/work/long read/write access 324706f2543Smrg(MEM_RB(name,addr),MEM_RW(name,addr),MEM_RL(name,addr), 325706f2543SmrgMEM_WB(name,addr,val),MEM_WL(name,addr,val),MEM_WL(name,addr,val)) of 326706f2543Smrgthe real mode memory environment. 'name' will contain a pointer to the 327706f2543Smrgcurrent xf86Int10InfoRec. Currently defines are available for 328706f2543Smrgvm86-mode under Linux and x86emu. They may be activated by defining 329706f2543Smrg_X86EMU or _VM86_LINUX respectively. 330706f2543Smrg 331706f2543SmrgNote: Emulators usually are not able to pass this pointer when calling 332706f2543Smrgmemory access functions. In this case a global variable should be 333706f2543Smrgdefined which can hold this pointer. This variable can be set in 334706f2543SmrgMapCurrentInt10(). It also must be set in xf86InitInt10() if this 335706f2543Smrgfunction calls the memory access functions either directly or by 336706f2543Smrgcalling xf86ExecX86int10(pInt). Defines to access the emulator 337706f2543Smrgspecific xf86 CPU register locations are also required: 338706f2543SmrgX86_EAX,...,X86_EFLAGS for access of the full 32 bit registers, 339706f2543SmrgX86_AX...X86_FLAGS for access of the 16 bit registers and 340706f2543SmrgXF86_AL,XF86_BL,XF86_CL,XF86_DL to access the lower byte of the 341706f2543SmrgAX,BX,CX and DX register. 342706f2543Smrg 343706f2543Smrg 344706f2543Smrg$XFree86: xc/programs/Xserver/hw/xfree86/int10/INT10.HOWTO,v 1.2 2000/02/08 13:13:22 eich Exp $ 345