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