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

iopm.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 00005 Module Name: 00006 00007 iopm.c 00008 00009 Abstract: 00010 00011 This module implements interfaces that support manipulation of i386 00012 i/o access maps (IOPMs). 00013 00014 These entry points only exist on i386 and IA64 machines. 00015 00016 Author: 00017 00018 Bryan M. Willman (bryanwi) 18-Sep-91 00019 00020 Environment: 00021 00022 Kernel mode only. 00023 00024 Revision History: 00025 00026 Charles Spirakis (intel): 25 Jul 1996 - Don't have TSS anymore, 00027 so don't need TSS handling or any synchronization of the TSS. 00028 00029 --*/ 00030 00031 #include "ki.h" 00032 00033 BOOLEAN KiIA32SetPortMemory(PKPROCESS Process); 00034 00035 // 00036 // For IA64, only need to worry about synchronization for SetIoAccessMap 00037 // since there is no longer a TSS and no worry about partial TSS states 00038 // (and no need for any IPI's to do updates...) 00039 // 00040 00041 // 00042 // Holds all of the possible IO maps (currently 1) 00043 // 00044 static PKIO_ACCESS_MAP VdmIoMaps[IOPM_COUNT]; 00045 00046 00047 BOOLEAN 00048 KeIA32SetIoAccessMap ( 00049 ULONG MapNumber, 00050 PKIO_ACCESS_MAP IoAccessMap 00051 ) 00052 00053 /*++ 00054 00055 Routine Description: 00056 00057 The specified i/o access map will be set to match the 00058 definition specified by IoAccessMap (i.e. enable/disable 00059 those ports) before the call returns. The change will take 00060 effect on all processors. 00061 00062 KeIA32SetIoAccessMap does not give any process enhanced I/O 00063 access, it merely defines a particular access map. 00064 00065 Arguments: 00066 00067 MapNumber - Number of access map to set. Map 0 is fixed. 00068 00069 IoAccessMap - Pointer to bitvector (64K bits, 8K bytes) which 00070 defines the specified access map. Must be in 00071 non-paged pool. 00072 00073 Return Value: 00074 00075 TRUE if successful. FALSE if failure (attempt to set a map 00076 which does not exist, attempt to set map 0) 00077 00078 --*/ 00079 00080 { 00081 00082 PKPROCESS CurrentProcess; 00083 KIRQL OldIrql; 00084 PVOID pt; 00085 PUCHAR p; 00086 ULONG i; 00087 BOOLEAN res; 00088 00089 // 00090 // Reject illegal requests 00091 // 00092 00093 if ((MapNumber > IOPM_COUNT) || (MapNumber == IO_ACCESS_MAP_NONE)) { 00094 return FALSE; 00095 } 00096 00097 // 00098 // If the map N hasn't been allocated, then allocate it now. 00099 // Don't need to ever free this since it is a system wide 00100 // resource... Once allocated, stays till reboot. 00101 // This implies we might want to allocate it early, but we can 00102 // deal with that later... 00103 // 00104 00105 if (VdmIoMaps[MapNumber - 1] == NULL) { 00106 // Allocate a little extra to handle wrap-around... 00107 p = (PUCHAR) ExAllocatePool(NonPagedPool, PIOPM_SIZE); 00108 if (p == NULL) { 00109 return FALSE; 00110 } 00111 00112 // 00113 // And set it all to "no-access" 00114 // (and don't forget the little extra) 00115 // 00116 RtlFillMemory((PVOID) p, PIOPM_SIZE, 0x0ff); 00117 00118 VdmIoMaps[MapNumber - 1] = p; 00119 } 00120 00121 // 00122 // Acquire the context swap lock so a context switch will not occur. 00123 // 00124 // BUGBUG: Is this really needed? 00125 // 00126 00127 KiLockContextSwap(&OldIrql); 00128 00129 // 00130 // Copy the IOPM map and load the map for the current process. 00131 // 00132 00133 pt = VdmIoMaps[MapNumber-1]; 00134 RtlMoveMemory(pt, (PVOID)IoAccessMap, IOPM_SIZE); 00135 CurrentProcess = PsGetCurrentProcess(); 00136 00137 CurrentProcess->IOCurMap = MapNumber; 00138 00139 // 00140 // BUGBUG: Need to set the EFLAGS.iopl to 3 for this process 00141 // and all threads in the process as well? 00142 // 00143 00144 res = KiIA32SetPortMemory(CurrentProcess); 00145 00146 // 00147 // Restore IRQL and unlock the context swap lock. 00148 // 00149 00150 KiUnlockContextSwap(OldIrql); 00151 return res; 00152 } 00153 00154 00155 BOOLEAN 00156 KeIA32QueryIoAccessMap ( 00157 ULONG MapNumber, 00158 PKIO_ACCESS_MAP IoAccessMap 00159 ) 00160 00161 /*++ 00162 00163 Routine Description: 00164 00165 The specified i/o access map will be dumped into the buffer. 00166 map 0 is a constant, but will be dumped anyway. 00167 00168 Arguments: 00169 00170 MapNumber - Number of access map to set. map 0 is fixed. 00171 00172 IoAccessMap - Pointer to buffer (64K bits, 8K bytes) which 00173 is to receive the definition of the access map. 00174 Must be in non-paged pool. 00175 00176 Return Value: 00177 00178 TRUE if successful. FALSE if failure (attempt to query a map 00179 which does not exist) 00180 00181 --*/ 00182 00183 { 00184 PVOID Map; 00185 KIRQL OldIrql; 00186 00187 // 00188 // Reject illegal requests 00189 // 00190 00191 if (MapNumber > IOPM_COUNT) { 00192 return FALSE; 00193 } 00194 00195 // 00196 // BUGBUG: Do we care if a context switch occurs? What if someone 00197 // else is modifying map N? (just an issue with MP systems...) 00198 // 00199 00200 // 00201 // Copy out the map 00202 // 00203 00204 if (MapNumber == IO_ACCESS_MAP_NONE) { 00205 00206 // 00207 // no access case, simply return a map of all 1s 00208 // 00209 RtlFillMemory((PVOID) IoAccessMap, IOPM_SIZE, 0x0ff); 00210 00211 } else { 00212 00213 // 00214 // normal case, just copy the bits 00215 // 00216 00217 Map = VdmIoMaps[MapNumber-1]; 00218 ASSERT(Map != NULL); 00219 RtlMoveMemory((PVOID)IoAccessMap, Map, IOPM_SIZE); 00220 } 00221 00222 return TRUE; 00223 } 00224 00225 00226 BOOLEAN 00227 KeIA32IoSetAccessProcess ( 00228 PKPROCESS Process, 00229 ULONG MapNumber 00230 ) 00231 /*++ 00232 00233 Routine Description: 00234 00235 Set the i/o access map which controls user mode i/o access 00236 for a particular process. 00237 00238 Arguments: 00239 00240 Process - Pointer to kernel process object describing the 00241 process which for which a map is to be set. 00242 00243 MapNumber - Number of the map to set. Value of map is 00244 defined by KeIA32IoSetAccessProcess. Setting MapNumber 00245 to IO_ACCESS_MAP_NONE will disallow any user mode i/o 00246 access from the process. 00247 00248 Return Value: 00249 00250 TRUE if success, FALSE if failure (illegal MapNumber) 00251 00252 --*/ 00253 00254 { 00255 // 00256 // Reject illegal requests 00257 // 00258 00259 if (MapNumber > IOPM_COUNT) { 00260 return FALSE; 00261 } 00262 00263 // 00264 // Store new offset in process object, compute current set of 00265 // active processors for process, if this cpu is one, set IOPM. 00266 // 00267 00268 Process->IOCurMap = MapNumber; 00269 if (Process->IOCurMap == IO_ACCESS_MAP_NONE) { 00270 // 00271 // BUGBUG: Need to set the EFLAGS.iopl back to 0 for this process 00272 // And all its threads? 00273 // 00274 } 00275 else { 00276 // 00277 // BUGBUG: Need to set the EFLAGS.iopl to 3 for this process 00278 // And all its threads? 00279 // 00280 } 00281 00282 return (KiIA32SetPortMemory(Process)); 00283 } 00284 00285 00286 BOOLEAN 00287 KeIA32PortIsAccessable( 00288 PKPROCESS Process, 00289 ULONG Port, 00290 ULONG Size 00291 ) 00292 /*++ 00293 00294 Routine Description: 00295 00296 Checks to see if a particular port is accessable by a particular process 00297 00298 Arguments: 00299 00300 Process - Pointer to kernel process object 00301 00302 Port - port number to check 00303 00304 Size - size of access (1, 2 or 4 bytes) 00305 00306 Return Value: 00307 00308 TRUE if port is accessable, false if port is not 00309 00310 --*/ 00311 { 00312 ULONG byte; 00313 ULONG bit; 00314 ULONG val; 00315 ULONG ToTest; 00316 PUCHAR ioBits; 00317 00318 if (Process->IOCurMap == IO_ACCESS_MAP_NONE) { 00319 return FALSE; 00320 } 00321 00322 // 00323 // Make sure everything is legit... 00324 // 00325 ASSERT (Process->IOCurMap <= IOPM_COUNT); 00326 ASSERT (Port < (64 * 1024)); 00327 ASSERT((Size == 1) || (Size == 2) || (Size == 4)); 00328 00329 ioBits = VdmIoMaps[Process->IOCurMap - 1]; 00330 00331 // 00332 // Get the byte to be tested 00333 // 00334 byte = Port >> 3; 00335 00336 // 00337 // This handles boundary conditions... 00338 // 00339 ToTest = ioBits[byte] | (ioBits[byte + 1] << 8); 00340 00341 // 00342 // And get the specific bit 00343 // 00344 bit = Port & 0x07; 00345 00346 // 00347 // Really want Size to be 1, 2, or 3 so we can use it for shifting and 00348 // we want val to be a mask for the port access 00349 // (2^Size -1 == mask for size of port access)... 00350 // 00351 if (Size == 4) { 00352 val = 7 << bit; 00353 } 00354 else { 00355 val = ((1 << Size) - 1) << bit; 00356 } 00357 00358 return (! (ToTest & val)); 00359 } 00360 00361 00362 BOOLEAN 00363 KiIA32SetPortMemory( 00364 PKPROCESS Process 00365 ) 00366 /*++ 00367 00368 Routine Description: 00369 00370 Based on the IO access allowed for a particular process, set the memory 00371 map accordingly... 00372 00373 Arguments: 00374 00375 Process - Pointer to kernel process object 00376 00377 Return Value: 00378 00379 TRUE if able to setup the memory pages 00380 00381 Notes: 00382 It would be a lot faster to use a bit searching algorithm 00383 looking for the first 0 bit (accessible) instead of 00384 doing 8192 calls to the memory system... Of course, we may 00385 do this infrequently enough that it may not matter... 00386 00387 --*/ 00388 { 00389 PUCHAR ioBits; 00390 ULONG i; 00391 PVOID VirtualPort; 00392 00393 if (Process->IOCurMap == IO_ACCESS_MAP_NONE) { 00394 // Unmap all of the IOBASE memory? 00395 // Or set them all as Inaccesable? 00396 00397 return TRUE; 00398 } 00399 00400 ioBits = VdmIoMaps[Process->IOCurMap - 1]; 00401 00402 for (i = 0; i < IOPM_SIZE; i++) { 00403 // VirtualPort = (i << SHIFT_8K) + IOBASE; 00404 if ((*ioBits & 0x000f) == 0) { 00405 // These four ports can be set read/writable 00406 // Call memory manager to set read/writable + IO special 00407 } 00408 else { 00409 // Call memory manager to set as inaccessable/unmap 00410 } 00411 00412 // VirtualPort = (i << SHIFT_8K) + IOBASE + (4K_PAGE); 00413 if ((*ioBits++ & 0x00f0) == 0) { 00414 // These four ports can be set read/writable 00415 // Call memory manager to set read/writable + IO special 00416 } 00417 else { 00418 // Call memory manager to set as inaccessable/unmap 00419 } 00420 } 00421 00422 return TRUE; 00423 }

Generated on Sat May 15 19:40:30 2004 for test by doxygen 1.3.7