Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

biosc.c File Reference

#include "ki.h"
#include "vdmntos.h"

Go to the source code of this file.

Defines

#define V86_CODE_ADDRESS   0x10000
#define INT_OPCODE   0xcd
#define V86_BOP_OPCODE   0xfec4c4
#define V86_STACK_POINTER   0x1ffe
#define IOPM_OFFSET   FIELD_OFFSET(KTSS, IoMaps[0].IoMap)
#define VDM_TIB_ADDRESS   0x12000
#define INT_10_TEB   0x13000

Functions

VOID Ki386SetupAndExitToV86Code (PVOID ExecutionAddress)
NTSTATUS Ke386CallBios (IN ULONG BiosCommand, IN OUT PCONTEXT BiosArguments)

Variables

PVOID Ki386IopmSaveArea
BOOLEAN BiosInitialized = FALSE


Define Documentation

#define INT_10_TEB   0x13000
 

Definition at line 45 of file biosc.c.

Referenced by Ke386CallBios().

#define INT_OPCODE   0xcd
 

Definition at line 40 of file biosc.c.

Referenced by Ke386CallBios().

#define IOPM_OFFSET   FIELD_OFFSET(KTSS, IoMaps[0].IoMap)
 

Definition at line 43 of file biosc.c.

Referenced by Ke386CallBios().

#define V86_BOP_OPCODE   0xfec4c4
 

Definition at line 41 of file biosc.c.

Referenced by Ke386CallBios().

#define V86_CODE_ADDRESS   0x10000
 

Definition at line 39 of file biosc.c.

Referenced by Ke386CallBios().

#define V86_STACK_POINTER   0x1ffe
 

Definition at line 42 of file biosc.c.

#define VDM_TIB_ADDRESS   0x12000
 

Definition at line 44 of file biosc.c.

Referenced by Ke386CallBios().


Function Documentation

NTSTATUS Ke386CallBios IN ULONG  BiosCommand,
IN OUT PCONTEXT  BiosArguments
 

Definition at line 60 of file biosc.c.

References _KTHREAD::ApcState, ASSERT, BiosInitialized, CONTEXT_FULL, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), INT_10_TEB, INT_OPCODE, IOPM_OFFSET, KeGetCurrentThread, KeGetPcr, KeRevertToUserAffinityThread(), KeSetSystemAffinityThread(), Ki386IopmSaveArea, Ki386SetupAndExitToV86Code(), NonPagedPool, NTSTATUS(), NULL, PAGE_SIZE, _KAPC_STATE::Process, PsGetCurrentProcess, PVDM_TIB, _Vdm_Tib::Size, Status, USHORT, V86_BOP_OPCODE, V86_CODE_ADDRESS, VDM_TIB, VDM_TIB_ADDRESS, and _Vdm_Tib::VdmContext.

00067 : 00068 00069 This function invokes specified ROM BIOS code by executing 00070 "INT BiosCommand." Before executing the BIOS code, this function 00071 will setup VDM context, change stack pointer ...etc. If for some reason 00072 the operation fails, a status code will be returned. Otherwise, this 00073 function always returns success reguardless of the result of the BIOS 00074 call. 00075 00076 N.B. This implementation relies on the fact that the direct 00077 I/O access operations between apps are serialized by win user. 00078 00079 Arguments: 00080 00081 BiosCommand - specifies which ROM BIOS function to invoke. 00082 00083 BiosArguments - specifies a pointer to the context which will be used 00084 to invoke ROM BIOS. 00085 00086 Return Value: 00087 00088 NTSTATUS code to specify the failure. 00089 00090 --*/ 00091 00092 { 00093 00094 NTSTATUS Status = STATUS_SUCCESS; 00095 PVDM_TIB VdmTib; 00096 PUCHAR BaseAddress = (PUCHAR)V86_CODE_ADDRESS; 00097 PTEB UserInt10Teb = (PTEB)INT_10_TEB; 00098 PKTSS Tss; 00099 PKPROCESS Process; 00100 PKTHREAD Thread; 00101 USHORT OldIopmOffset, OldIoMapBase; 00102 PVDM_PROCESS_OBJECTS VdmObjects; 00103 ULONG ContextLength; 00104 00105 // KIRQL OldIrql; 00106 //#if DBG 00107 // PULONG IdtAddress; 00108 // ULONG RegionSize; 00109 // ULONG OldProtect; 00110 //#endif 00111 00112 // 00113 // Map in ROM BIOS area to perform the int 10 code 00114 // 00115 00116 if (!BiosInitialized) { 00117 RtlZeroMemory(UserInt10Teb, sizeof(TEB)); 00118 } 00119 00120 //#if DBG 00121 // IdtAddress = 0; 00122 // RegionSize = 0x1000; 00123 // ZwProtectVirtualMemory ( NtCurrentProcess(), 00124 // &IdtAddress, 00125 // &RegionSize, 00126 // PAGE_READWRITE, 00127 // &OldProtect 00128 // ); 00129 //#endif 00130 00131 try { 00132 00133 // 00134 // Write "Int BiosCommand; bop" to reserved user space (0x1000). 00135 // Later control will transfer to the user space to execute 00136 // these two instructions. 00137 // 00138 00139 *BaseAddress++ = INT_OPCODE; 00140 *BaseAddress++ = (UCHAR)BiosCommand; 00141 *(PULONG)BaseAddress = V86_BOP_OPCODE; 00142 00143 // 00144 // Set up Vdm(v86) context to execute the int BiosCommand 00145 // instruction by copying user supplied context to VdmContext 00146 // and updating the control registers to predefined values. 00147 // 00148 00149 // 00150 // We want to use a constant number for the int10. 00151 // 00152 // 00153 // Create a fake TEB so we can switch the thread to it while we 00154 // do an int10 00155 // 00156 00157 UserInt10Teb->Vdm = (PVOID)VDM_TIB_ADDRESS; 00158 VdmTib = (PVDM_TIB)VDM_TIB_ADDRESS; 00159 RtlZeroMemory(VdmTib, sizeof(VDM_TIB)); 00160 VdmTib->Size = sizeof(VDM_TIB); 00161 *pNtVDMState = 0; 00162 00163 // 00164 // extended registers are never going to matter to 00165 // an Int10 call, so only copy the old part of the 00166 // context record. 00167 // 00168 ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters); 00169 RtlMoveMemory(&(VdmTib->VdmContext), BiosArguments, ContextLength); 00170 VdmTib->VdmContext.SegCs = (ULONG)BaseAddress >> 4; 00171 VdmTib->VdmContext.SegSs = (ULONG)BaseAddress >> 4; 00172 VdmTib->VdmContext.Eip = 0; 00173 VdmTib->VdmContext.Esp = 2 * PAGE_SIZE - sizeof(ULONG); 00174 VdmTib->VdmContext.EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK; 00175 VdmTib->VdmContext.ContextFlags = CONTEXT_FULL; 00176 00177 } except (EXCEPTION_EXECUTE_HANDLER) { 00178 00179 Status = GetExceptionCode(); 00180 } 00181 00182 // 00183 // The vdm kernel code finds the Tib by looking at a pointer cached in 00184 // kernel memory, which was probed at Vdm creation time. Since the 00185 // creation semantics for this vdm are peculiar, we do something similar 00186 // here. 00187 // 00188 00189 try { 00190 00191 // 00192 // We never get here on a process that is a real vdm. If we do, 00193 // bad things will happen (pool leak, failure to execute dos and windows apps) 00194 // 00195 ASSERT(PsGetCurrentProcess()->VdmObjects == NULL); 00196 VdmObjects = ExAllocatePoolWithTag( 00197 NonPagedPool, 00198 sizeof(VDM_PROCESS_OBJECTS), 00199 ' eK' 00200 ); 00201 00202 00203 // 00204 // Since we are doing this on behalf of CSR not a user process, we aren't 00205 // charging quota. 00206 // 00207 if (VdmObjects == NULL) { 00208 Status = STATUS_NO_MEMORY; 00209 } else { 00210 00211 // 00212 // We are only initializing the VdmTib pointer, because that's the only 00213 // part of the VdmObjects we use for ROM calls. We aren't set up 00214 // to simulate interrupts, or any of the other stuff that would be done 00215 // in a conventional vdm 00216 // 00217 RtlZeroMemory( VdmObjects, sizeof(VDM_PROCESS_OBJECTS)); 00218 00219 VdmObjects->VdmTib = VdmTib; 00220 00221 PsGetCurrentProcess()->VdmObjects = VdmObjects; 00222 } 00223 } except (EXCEPTION_EXECUTE_HANDLER) { 00224 00225 Status = GetExceptionCode(); 00226 } 00227 00228 if (Status == STATUS_SUCCESS) { 00229 00230 // 00231 // Since we are going to v86 mode and accessing some I/O ports, we 00232 // need to make sure the IopmOffset is set correctly across context 00233 // swap and the I/O bit map has all the bits cleared. 00234 // N.B. This implementation assumes that there is only one full 00235 // screen DOS app and the io access between full screen DOS 00236 // app and the server code is serialized by win user. That 00237 // means even we change the IOPM, the full screen dos app won't 00238 // be able to run on this IOPM. 00239 // * In another words, IF THERE IS 00240 // * MORE THAN ONE FULL SCREEN DOS APPS, THIS CODE IS BROKEN.* 00241 // 00242 // NOTE This code works on the assumption that winuser serializes 00243 // direct I/O access operations. 00244 // 00245 00246 // 00247 // Call the bios from the processor which booted the machine. 00248 // 00249 00250 Thread = KeGetCurrentThread(); 00251 KeSetSystemAffinityThread(1); 00252 Tss = KeGetPcr()->TSS; 00253 00254 // 00255 // Save away the original IOPM bit map and clear all the IOPM bits 00256 // to allow v86 int 10 code to access ALL the io ports. 00257 // 00258 00259 // 00260 // Make sure there are at least 2 IOPM maps. 00261 // 00262 00263 ASSERT(KeGetPcr()->GDT[KGDT_TSS / 8].LimitLow >= (0x2000 + IOPM_OFFSET - 1)); 00264 RtlMoveMemory (Ki386IopmSaveArea, 00265 (PVOID)&Tss->IoMaps[0].IoMap, 00266 PAGE_SIZE * 2 00267 ); 00268 RtlZeroMemory ((PVOID)&Tss->IoMaps[0].IoMap, PAGE_SIZE * 2); 00269 00270 Process = Thread->ApcState.Process; 00271 OldIopmOffset = Process->IopmOffset; 00272 OldIoMapBase = Tss->IoMapBase; 00273 Process->IopmOffset = (USHORT)(IOPM_OFFSET); // Set Process IoPmOffset before 00274 Tss->IoMapBase = (USHORT)(IOPM_OFFSET); // updating Tss IoMapBase 00275 00276 // 00277 // Call ASM routine to switch stack to exit to v86 mode to 00278 // run Int BiosCommand. 00279 // 00280 00281 Ki386SetupAndExitToV86Code(UserInt10Teb); 00282 00283 // 00284 // After we return from v86 mode, the control comes here. 00285 // 00286 // Restore old IOPM 00287 // 00288 00289 RtlMoveMemory ((PVOID)&Tss->IoMaps[0].IoMap, 00290 Ki386IopmSaveArea, 00291 PAGE_SIZE * 2 00292 ); 00293 00294 Process->IopmOffset = OldIopmOffset; 00295 Tss->IoMapBase = OldIoMapBase; 00296 00297 // 00298 // Restore old affinity for current thread. 00299 // 00300 00301 KeRevertToUserAffinityThread(); 00302 00303 // 00304 // Copy 16 bit vdm context back to caller. 00305 // 00306 // Extended register state is not going to matter, 00307 // so copy only the old part of the context record. 00308 // 00309 ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters); 00310 RtlMoveMemory(BiosArguments, &(VdmTib->VdmContext), ContextLength); 00311 BiosArguments->ContextFlags = CONTEXT_FULL; 00312 00313 // 00314 // Free the pool used for the VdmTib pointer 00315 // 00316 ExFreePool(PsGetCurrentProcess()->VdmObjects); 00317 PsGetCurrentProcess()->VdmObjects = NULL; 00318 00319 } 00320 00321 //#if DBG 00322 // IdtAddress = 0; 00323 // RegionSize = 0x1000; 00324 // ZwProtectVirtualMemory ( NtCurrentProcess(), 00325 // &IdtAddress, 00326 // &RegionSize, 00327 // PAGE_NOACCESS, 00328 // &OldProtect 00329 // ); 00330 //#endif 00331 00332 return(Status); 00333 } }

VOID Ki386SetupAndExitToV86Code PVOID  ExecutionAddress  ) 
 

Referenced by Ke386CallBios().


Variable Documentation

BOOLEAN BiosInitialized = FALSE
 

Definition at line 52 of file biosc.c.

Referenced by Ke386CallBios().

PVOID Ki386IopmSaveArea
 

Definition at line 51 of file biosc.c.

Referenced by Ke386CallBios(), and KiInitializeKernel().


Generated on Sat May 15 19:42:57 2004 for test by doxygen 1.3.7