1 2 INT10 X86 Real Mode executor 3 ============================= 4 5 PRELIMINARY 6 7INT10 is a XFree86 module for soft-booting and executing real mode 8int10 BIOS calls. The BIOS call code is largely untested, yet. 9 101. Usage 11======== 12 13To use the int10 module in a driver the header file 14xfree86/os-support/int10/xf86int10.h must be included. 15 16 a. Initialization 17 ----------------- 18 19The int10-executer gets initialized by calling: 20 21 xf86Int10InfoPtr xf86InitInt10(int entityIndex); 22 23The function will soft-boot any non-primary device and return a 24pointer to a xf86Int10InfoRec on success. If anything fails or if 25int10 execution is disabled by an option in the device section NULL 26will be returned. The driver should store this pointer for later 27calls to other int10 module functions. 28 29 b. Memory allocation 30 -------------------- 31 32To allocate memory in the real mode execution environment 33 34 void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off); 35 36can be called. It allocates num consecutive pagesize chunks. It 37returns the address of the allocated area. off is set to its offset in 38the real mode memory space. 39 40 void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num); 41 42Is used to free num pages beginning at pbase. 43 44 c. Doing int10 BIOS calls 45 ------------------------- 46 47The BIOS call is executed by calling: 48 49 void xf86ExecX86int10(xf86Int10InfoPtr pInt); 50 51The number of the interrupt (normally 10) and the initial values of 52the ax, bx, cx, dx, si, di and es x86-CPU registers can be set in the 53xf86Int10InfoRec passed to the function. On return this structure 54contains the exit values of the registers listed above and the CPU 55flag register. 56 57 d. De-initializing 58 ----------------- 59 60If no further int10 calls are required for a certain chipset 61the driver should call: 62 63 void xf86FreeInt10(xf86Int10InfoPtr pInt); 64 65to free the memory allocated for real mode int10 calls. 66 67 682. Porting issues 69================= 70 71The int10 real mode executor is designed to run on top of various x86 72CPU emulators as well as in vm86 mode of a real x86 CPU. If used with 73a CPU emulator the emulator and CPU specific interfaces can be held 74separate thus requiring minimal efforts to port the int10 module to 75new platforms. Currently an interface to the x86emu real mode 76emulator is provided. Since details of setting up and running the 77vm86 mode is platform dependent both the platform dependent 78environment and the emulation layer have to be ported. Several helper 79functions are provided for that. 80 81A CPU emulator should meet certain requirements to be usable 82for the INT10 executor: 83 841. It must trap calls to intXX instructions and pass execution to an 85 external function which is allowed to modify CPU registers 86 including the instruction pointer (IP) before returning to the 87 emulator for continuing execution. When the external function is 88 called the IP must point to the instruction past the intXX call. 89 902. The emulator should use externally provided functions to handle 91 PIO. 92 933. The emulator should be able to use externally provided functions 94 to access memory from the real mode memory environment. Note, that 95 the vm86 mode usually requires one hunk of consecutive memory 96 starting at address 0 in the process virtual memory space. Thus if 97 this mode is to be used, the OS environment has to be able to provide 98 that, ie. it must be able to remap the processes virtual memory space 99 onto itself. If the emulator is able to handle memory access through 100 externally provided functions the real mode process memory can be 101 located anywhere in the processes virtual memory. It does not even 102 have to be consecutive. 103 1044. The executor should terminate on encountering a 'hlt' instruction. 105 106 107Functions to implement: 108 109To simplify development the code has been split into a general setup 110part and an emulator specific one. A generic setup code is provided in 111generic.c. It should be usable with any emulator satisfying the 112conditions mentioned above. Therefore the following section on int10 113setup may be skipped when porting int10 to new emulator. 114 115If the vm86() is to be used no memory access functions can be used. 116Therefore the layout of the real mode memory image has to meet certain 117requirements. Therefore when porting to other platforms a new setup 118code may have to be designed, too. The following section will give 119guidelines how this may be done. A sample implementation using SysV 120IPC to map the appropriate real mode memory image to address 0 in 121virtual address space just prior to execution may be found in 122xfree86/os-support/linux/int10/linux.c. 123 124On non-PC like platforms emulation of certain PC features such as 125initialization of BIOS int vectors, sys_BIOS constants or PCI config 126method 1 can be turned on by defining _PC. 127 128I. Setup Code 129------------- 130 131This sets up the real mode memory image, calls the emulator to POST 132the chipset if required and maintains memory allocations in real mode 133address space. 134 1351. xf86Int10InfoPtr xf86InitInt10(int entityIndex); 136 137This function should first find the screen assigned to the entity 138carrying entitiyIndex and then call 139 140 Bool int10skip(ScrnInfoPtr pScrn) 141 142to find out if the user has requested not to initialize int10. If so 143xf86InitInt10() should return NULL. Otherwise an xf86Int10InfoRec 144should be allocated. This structure contains the following fields: 145 146 a. int entityIndex - index of the entity whose BIOS is to be 147 executed. 148 b. int scrnIndex - index of the screen assigned the entity. 149 c. pointer cpuRegs - pointer to a emulator/vm86-mode private 150 structure. May hold cpu register values 151 for the emulator. 152 d. CARD16 BIOSseg - Video BIOS segment address. 153 e. pointer private - pointer to a os specific data structure. 154 f. struct _int10Mem* - pointer to a structure to hold the memory 155 access functions for use by an emulator. 156 g. int num - number of the int to be called. 157 h. int ax..es,flags - CPU register values to pass to int-call. 158 159The Init function should initialize a-f. To initialize the emulator 160specific execute environment the function 161 162 Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt) 163 164should be called. If this function returns FALSE any already allocated 165memory should be freed and xf86Int10Init(0 should exit returning NULL. 166 167If the platform has a PC like system BIOS it may be copied to or 168mapped into memory locations SYS_BIOS to SYS_SIZE-1 of the real mode 169memory environment of this process. Otherwise the helper function: 170 171int setup_system_bios(CARD32 base_addr); 172 173may be called to set up a rudimentary system BIOS sufficient to be 174used to boot video BIOSes. base_addr specifies the virtual address 175corresponding to SYS_BIOS in the real mode environment. If a PC-like 176int vector and BIOS data area is available it should be copied to 0 to 177LOW_PAGE_SIZE of the entities real mode environment. In this case the 178video interrupt related entries should be reset for all non-primary 179cards by calling: 180 181void reset_int_vect(xf86Int10InfoPtr pInt); To initialize the 182 183correct video BIOS entry points the BIOS must be warm-booted. If no 184PC-like int vector is available one can be set up by calling 185 186void setup_int_vect(xf86Int10InfoPtr pInt); 187 188In this case the video BIOS has to be warm-booted always. If the 189video BIOS for this entity has been installed during boot it may be 190mapped (or copied) directly to the correct address in the real mode 191memory environment. Otherwise 192 193int mapPciRom(xf86Int10InfoPtr pInt, unsigned char * address); 194 195should be called to copy the BIOS image from PCI ROM. 'address' 196specifies the address this image should be copied to. Sufficient space 197to hold an entire BIOS image should be allocated prior to calling 198mapPciRom(). This function will return the size of the BIOS image in 199bytes if it was able to successfully copy the image and 0 200otherwise. To create a well defined point to exit the softbooter 201 202void set_return_trap(xf86Int10Ptr pInt); 203 204may be called. It sets up a 'hlt' instruction in the emulator memory 205just above the BIOS variable area. Before entering real mode execution 206this address will be pushed onto the return stack. If the BIOS needs 207to be warm-booted this should be done before leaving xf86InitInt10() 208by setting num in the xf86Int10InfoRec to 0xe6 and calling 209 210void xf86ExecX86int10(xf86Int10IfoPtr pInt); 211 212The implementation of this function will be discussed below. This 213function should be wrapped by calls to void LockLegacyVGA(screen, 214legacyVGAPtr vga); and void UnlockLegacyVGA(screen, legacyVGAPtr vga); 215The struct vga is used to hold the state of the legacy VGA access 216registers if a legacy VGA device exists. xf86InitInt10() should 217return a pointer to the xf86Int10InfoRec allocated. 218 2192. Bool MapCurrentInt10(xf86Int10InfoPtr pInt); 220 221In case a platform specific mapping has to be performed to map the 222memory allocated for the real mode memory environment into a specific 223location prior to executing the x86 real mode code a function 224 225 Bool MapCurrentInt10(xf86Int10InfoPtr pInt); 226 227has to be provided. It will be called by a helper function whenever 228the active entity changes. If the vm86 mode is used it is most likely 229that the 1MB real mode memory space located somewhere in the processes 230virtual memory will have to be remapped to address 0 of the virtual 231memory space. 232 2333. void xf86FreeInt10(xf86Int10InfoPtr pInt); 234 235To free all memory allocated for video BIOS calls of a specific entity 236the function 237 238 void xf86FreeInt10(xf86Int10InfoPtr pInt); 239 240should be provided. If the entity to be freed was mapped by 241MapCurrentInt10() this mapping needs to be undone also. 242 2434. 244 void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off) 245 void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num) 246 247xf86Int10AllocPages() should allocate 'num' consecutive page-size 248chunks of memory. In real mode memory space this range needs to occupy 249consecutive addresses, too. The function must return the address of 250this memory. The offset in real mode memory needs to be returned in 251'off'. If no block of 'num' pages are available the function should 252return NULL. 253 254xf86Int10FreePages() will free the 'num' pages starting at 'pbase'. 255'num' is equal to the number of pages allocated by a single 256xf86Int10AllocatePages() call. 'pbase' is the address of the range 257previously returned by xf86Int10AllocatePages(). 258 259II. Emulator specific functions 260------------------------------- 261 2621. Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt); 263 264This function will be called from xf86InitInt10(). It may be used to 265set up the static emulator specific part of the real mode 266environment. On success it should return TRUE. 267 2682. xf86ExecX86int10(xf86Int10InfoPtr pInt); 269 270This function gets called to execute an int call. It may call the 271helper function: 272 273 void setup_int(xf86Int10InfoPrt pInt); 274 275to copy the register values to the emulator specific locations and to 276set up the non-static real mode execution environment. On return from 277setup_int() 'Int10Current' holds a pointer to the current 278xf86Int10InfoRec. 279 280It should start execution by calling 281 282 Bool int_handler(xf86Int10InfoPtr pInt); 283 284and if this function returns TRUE it should call whatever necessary to 285continue execution until a 'hlt' instruction is encountered. To copy 286the resulting register values back to the xf86Int10InfoRec structure 287 288 void finish_int(xf86Int10InfoPtr pInt); 289 290should be called. 291 292Helper functions are provided to aid the implementation of a vm86 293call: 294 295 Bool vm86_GP_fault(xf86Int10InfoPtr pInt); 296 297This function handles instructions which cause a vm86 call to 298trap. PIO access is handled by the in/out calls as defined in 299compiler.h. Optionally the PIO instructions can be logged by defining 300PRINT_PORT in xf86int10.h. This is meant for debugging purposes. 301 302Unknown instructions and 'hlt' cause vm86_GP_fault() to return 303FALSE. Otherwise TRUE is returned. 304 305Note: This function is currently based on the Linux vm86 call. It 306might have to be modified or even rewritten for other OS. So your 307mileage may vary. 308 309Functions to dump memory, code, xf86 CPU register values and stack are 310also provided. Take a look at helper.c To view a memory range the 311function 312 313 void dprint(unsigned long start, unsigned long size) 314 315is provided. The use should be self explanatory. 316 317Register and memory access functions are provided in helper_mem.c. 318The PIO register access functions can trap access to PCI config space 319access register (config method 1) if _PC is not defined. 320 321A header file 'defines.h' is required to define OS/emulator specific 322ways to access memory and xf86 CPU registers: Defines need to be 323provided for memory byte/work/long read/write access 324(MEM_RB(name,addr),MEM_RW(name,addr),MEM_RL(name,addr), 325MEM_WB(name,addr,val),MEM_WL(name,addr,val),MEM_WL(name,addr,val)) of 326the real mode memory environment. 'name' will contain a pointer to the 327current xf86Int10InfoRec. Currently defines are available for 328vm86-mode under Linux and x86emu. They may be activated by defining 329_X86EMU or _VM86_LINUX respectively. 330 331Note: Emulators usually are not able to pass this pointer when calling 332memory access functions. In this case a global variable should be 333defined which can hold this pointer. This variable can be set in 334MapCurrentInt10(). It also must be set in xf86InitInt10() if this 335function calls the memory access functions either directly or by 336calling xf86ExecX86int10(pInt). Defines to access the emulator 337specific xf86 CPU register locations are also required: 338X86_EAX,...,X86_EFLAGS for access of the full 32 bit registers, 339X86_AX...X86_FLAGS for access of the 16 bit registers and 340XF86_AL,XF86_BL,XF86_CL,XF86_DL to access the lower byte of the 341AX,BX,CX and DX register. 342 343 344$XFree86: xc/programs/Xserver/hw/xfree86/int10/INT10.HOWTO,v 1.2 2000/02/08 13:13:22 eich Exp $ 345