ReactOS  0.4.15-dev-2961-gecb0c09
int10.c
Go to the documentation of this file.
1 /*
2  * VideoPort driver
3  *
4  * Copyright (C) 2002, 2003, 2004 ReactOS Team
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  */
21 
22 #include "videoprt.h"
23 
24 #include <ndk/kefuncs.h>
25 #include <ndk/halfuncs.h>
26 #include <ndk/mmfuncs.h>
27 
28 #define NDEBUG
29 #include <debug.h>
30 
31 /* PRIVATE FUNCTIONS **********************************************************/
32 
33 #define IsLowV86Mem(_Seg, _Off) ((((_Seg) << 4) + (_Off)) < (0xa0000))
34 
35 /* Those two functions below are there so that CSRSS can't access low mem.
36  * Expecially, MAKE IT CRASH ON NULL ACCESS */
37 static
38 VOID
40 {
41  /* We pass a non-NULL address so that ZwAllocateVirtualMemory really does it
42  * And we truncate one page to get the right range spanned. */
43  PVOID BaseAddress = (PVOID)1;
45  SIZE_T ViewSize = 0xa0000 - PAGE_SIZE;
46 
47  /* We should only do that for CSRSS. */
49 
50  /* Commit (again) the pages, but with PAGE_NOACCESS protection */
51  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
52  &BaseAddress,
53  0,
54  &ViewSize,
55  MEM_COMMIT,
58 }
59 
60 static
61 VOID
63 {
64  /* We pass a non-NULL address so that ZwAllocateVirtualMemory really does it
65  * And we truncate one page to get the right range spanned. */
66  PVOID BaseAddress = (PVOID)1;
68  SIZE_T ViewSize = 0xa0000 - PAGE_SIZE;
69 
70  /* We should only do that for CSRSS, for the v86 address space */
72 
73  /* Commit (again) the pages, but with PAGE_READWRITE protection */
74  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
75  &BaseAddress,
76  0,
77  &ViewSize,
78  MEM_COMMIT,
81 }
82 
83 #if defined(_M_IX86) || defined(_M_AMD64)
85 NTAPI
87 {
89  UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
91  HANDLE PhysMemHandle;
95 #ifdef _M_IX86
96  CHAR IVTAndBda[1024 + 256];
97 #endif // _M_IX86
98 
99  /* Free the 1MB pre-reserved region. In reality, ReactOS should simply support us mapping the view into the reserved area, but it doesn't. */
100  BaseAddress = 0;
101  ViewSize = 1024 * 1024;
102  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
103  &BaseAddress,
104  &ViewSize,
105  MEM_RELEASE);
106  if (!NT_SUCCESS(Status))
107  {
108  DPRINT1("Couldn't unmap reserved memory (%x)\n", Status);
109  return 0;
110  }
111 
112  /* Open the physical memory section */
114  &PhysMemName,
116  NULL,
117  NULL);
118  Status = ZwOpenSection(&PhysMemHandle,
121  if (!NT_SUCCESS(Status))
122  {
123  DPRINT1("Couldn't open \\Device\\PhysicalMemory\n");
124  return Status;
125  }
126 
127  /* Map the BIOS and device registers into the address space */
128  Offset.QuadPart = 0xa0000;
129  ViewSize = 0x100000 - 0xa0000;
130  BaseAddress = (PVOID)0xa0000;
131  Status = ZwMapViewOfSection(PhysMemHandle,
133  &BaseAddress,
134  0,
135  ViewSize,
136  &Offset,
137  &ViewSize,
138  ViewUnmap,
139  0,
141  if (!NT_SUCCESS(Status))
142  {
143  DPRINT1("Couldn't map physical memory (%x)\n", Status);
144  ZwClose(PhysMemHandle);
145  return Status;
146  }
147 
148  /* Close physical memory section handle */
149  ZwClose(PhysMemHandle);
150 
151  if (BaseAddress != (PVOID)0xa0000)
152  {
153  DPRINT1("Couldn't map physical memory at the right address (was %x)\n",
154  BaseAddress);
155  return STATUS_UNSUCCESSFUL;
156  }
157 
158  /* Allocate some low memory to use for the non-BIOS
159  * parts of the v86 mode address space
160  */
161  BaseAddress = (PVOID)0x1;
162  ViewSize = 0xa0000 - 0x1000;
163  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
164  &BaseAddress,
165  0,
166  &ViewSize,
169  if (!NT_SUCCESS(Status))
170  {
171  DPRINT1("Failed to allocate virtual memory (Status %x)\n", Status);
172  return Status;
173  }
174  if (BaseAddress != (PVOID)0x0)
175  {
176  DPRINT1("Failed to allocate virtual memory at right address (was %x)\n",
177  BaseAddress);
178  return 0;
179  }
180 
181 #ifdef _M_IX86
182  /* Get the real mode IVT and BDA from the kernel */
183  Status = NtVdmControl(VdmInitialize, IVTAndBda);
184  if (!NT_SUCCESS(Status))
185  {
186  DPRINT1("NtVdmControl failed (status %x)\n", Status);
187  return Status;
188  }
189 #endif // _M_IX86
190 
191  /* Protect the V86 address space after this */
193 
194  /* Return success */
195  return STATUS_SUCCESS;
196 }
197 #else
198 NTSTATUS
199 NTAPI
201 {
203  NT_ASSERT(FALSE);
204  return STATUS_NOT_IMPLEMENTED;
205 }
206 #endif
207 
208 VP_STATUS
209 NTAPI
211  IN PVOID Context,
212  OUT PUSHORT Seg,
213  OUT PUSHORT Off,
215 {
217 #ifdef _M_IX86
218  PVOID MemoryAddress;
219  PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
221  SIZE_T Size;
222 
223  TRACE_(VIDEOPRT, "IntInt10AllocateBuffer\n");
224 
225  IntAttachToCSRSS(&CallingProcess, &ApcState);
226 
227  Size = *Length;
228  MemoryAddress = (PVOID)0x20000;
229 
230  Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
231  &MemoryAddress,
232  0,
233  &Size,
234  MEM_COMMIT,
236  if (!NT_SUCCESS(Status))
237  {
238  WARN_(VIDEOPRT, "- ZwAllocateVirtualMemory failed\n");
239  IntDetachFromCSRSS(&CallingProcess, &ApcState);
241  }
242 
243  if (MemoryAddress > (PVOID)(0x100000 - Size))
244  {
245  ZwFreeVirtualMemory(NtCurrentProcess(),
246  &MemoryAddress,
247  &Size,
248  MEM_RELEASE);
249  WARN_(VIDEOPRT, "- Unacceptable memory allocated\n");
250  IntDetachFromCSRSS(&CallingProcess, &ApcState);
252  }
253 
254  *Length = (ULONG)Size;
255  *Seg = (USHORT)((ULONG_PTR)MemoryAddress >> 4);
256  *Off = (USHORT)((ULONG_PTR)MemoryAddress & 0xF);
257 
258  INFO_(VIDEOPRT, "- Segment: %x\n", (ULONG_PTR)MemoryAddress >> 4);
259  INFO_(VIDEOPRT, "- Offset: %x\n", (ULONG_PTR)MemoryAddress & 0xF);
260  INFO_(VIDEOPRT, "- Length: %x\n", *Length);
261 
262  IntDetachFromCSRSS(&CallingProcess, &ApcState);
263 
264  return NO_ERROR;
265 #else
266  Status = x86BiosAllocateBuffer(Length, Seg, Off);
268 #endif
269 }
270 
271 VP_STATUS
272 NTAPI
274  IN PVOID Context,
275  IN USHORT Seg,
276  IN USHORT Off)
277 {
279 #ifdef _M_IX86
280  PVOID MemoryAddress = (PVOID)((ULONG_PTR)(Seg << 4) | Off);
281  PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
283  SIZE_T Size = 0;
284 
285  TRACE_(VIDEOPRT, "IntInt10FreeBuffer\n");
286  INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
287  INFO_(VIDEOPRT, "- Offset: %x\n", Off);
288 
289  IntAttachToCSRSS(&CallingProcess, &ApcState);
290  Status = ZwFreeVirtualMemory(NtCurrentProcess(),
291  &MemoryAddress,
292  &Size,
293  MEM_RELEASE);
294 
295  IntDetachFromCSRSS(&CallingProcess, &ApcState);
296 
297  return Status;
298 #else
299  Status = x86BiosFreeBuffer(Seg, Off);
301 #endif
302 }
303 
304 VP_STATUS
305 NTAPI
307  IN PVOID Context,
308  IN USHORT Seg,
309  IN USHORT Off,
310  OUT PVOID Buffer,
311  IN ULONG Length)
312 {
313 #ifdef _M_IX86
314  PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
316 
317  TRACE_(VIDEOPRT, "IntInt10ReadMemory\n");
318  INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
319  INFO_(VIDEOPRT, "- Offset: %x\n", Off);
320  INFO_(VIDEOPRT, "- Buffer: %x\n", Buffer);
321  INFO_(VIDEOPRT, "- Length: %x\n", Length);
322 
323  IntAttachToCSRSS(&CallingProcess, &ApcState);
324 
325  if (IsLowV86Mem(Seg, Off))
327  RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)(Seg << 4) | Off), Length);
328  if (IsLowV86Mem(Seg, Off))
330 
331  IntDetachFromCSRSS(&CallingProcess, &ApcState);
332 
333  return NO_ERROR;
334 #else
336 
337  Status = x86BiosReadMemory(Seg, Off, Buffer, Length);
339 #endif
340 }
341 
342 VP_STATUS
343 NTAPI
345  IN PVOID Context,
346  IN USHORT Seg,
347  IN USHORT Off,
348  IN PVOID Buffer,
349  IN ULONG Length)
350 {
351 #ifdef _M_IX86
352  PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
354 
355  TRACE_(VIDEOPRT, "IntInt10WriteMemory\n");
356  INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
357  INFO_(VIDEOPRT, "- Offset: %x\n", Off);
358  INFO_(VIDEOPRT, "- Buffer: %x\n", Buffer);
359  INFO_(VIDEOPRT, "- Length: %x\n", Length);
360 
361  IntAttachToCSRSS(&CallingProcess, &ApcState);
362  if (IsLowV86Mem(Seg, Off))
364  RtlCopyMemory((PVOID)((ULONG_PTR)(Seg << 4) | Off), Buffer, Length);
365  if (IsLowV86Mem(Seg, Off))
367  IntDetachFromCSRSS(&CallingProcess, &ApcState);
368 
369  return NO_ERROR;
370 #else
372 
373  Status = x86BiosWriteMemory(Seg, Off, Buffer, Length);
375 #endif
376 }
377 
378 VP_STATUS
379 NTAPI
381  IN PVOID Context,
382  IN OUT PINT10_BIOS_ARGUMENTS BiosArguments)
383 {
384 #ifdef _M_AMD64
385  X86_BIOS_REGISTERS BiosContext;
386 #else
388 #endif
390  PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
392 
393  /* Attach to CSRSS */
394  IntAttachToCSRSS(&CallingProcess, &ApcState);
395 
396  /* Clear the context */
398 
399  /* Fill out the bios arguments */
400  BiosContext.Eax = BiosArguments->Eax;
401  BiosContext.Ebx = BiosArguments->Ebx;
402  BiosContext.Ecx = BiosArguments->Ecx;
403  BiosContext.Edx = BiosArguments->Edx;
404  BiosContext.Esi = BiosArguments->Esi;
405  BiosContext.Edi = BiosArguments->Edi;
406  BiosContext.Ebp = BiosArguments->Ebp;
407  BiosContext.SegDs = BiosArguments->SegDs;
408  BiosContext.SegEs = BiosArguments->SegEs;
409 
410  /* Do the ROM BIOS call */
412  Executive,
413  KernelMode,
414  FALSE,
415  NULL);
416 
417  /* The kernel needs access here */
419 #ifdef _M_AMD64
421 #else
422  Status = Ke386CallBios(0x10, &BiosContext);
423 #endif
425 
427 
428  /* Return the arguments */
429  BiosArguments->Eax = BiosContext.Eax;
430  BiosArguments->Ebx = BiosContext.Ebx;
431  BiosArguments->Ecx = BiosContext.Ecx;
432  BiosArguments->Edx = BiosContext.Edx;
433  BiosArguments->Esi = BiosContext.Esi;
434  BiosArguments->Edi = BiosContext.Edi;
435  BiosArguments->Ebp = BiosContext.Ebp;
436  BiosArguments->SegDs = (USHORT)BiosContext.SegDs;
437  BiosArguments->SegEs = (USHORT)BiosContext.SegEs;
438 
439  /* Detach and return status */
440  IntDetachFromCSRSS(&CallingProcess, &ApcState);
441 
442  if (NT_SUCCESS(Status))
443  {
444  return NO_ERROR;
445  }
446 
448 }
449 
450 /* PUBLIC FUNCTIONS ***********************************************************/
451 
452 /*
453  * @implemented
454  */
455 VP_STATUS
456 NTAPI
458  IN PVOID HwDeviceExtension,
459  IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments)
460 {
461  INT10_BIOS_ARGUMENTS Int10BiosArguments;
463 
464  if (!CsrProcess)
465  {
467  }
468 
469  /* Copy arguments to other format */
470  RtlCopyMemory(&Int10BiosArguments, BiosArguments, sizeof(*BiosArguments));
471  Int10BiosArguments.SegDs = 0;
472  Int10BiosArguments.SegEs = 0;
473 
474  /* Do the BIOS call */
475  Status = IntInt10CallBios(NULL, &Int10BiosArguments);
476 
477  /* Copy results back */
478  RtlCopyMemory(BiosArguments, &Int10BiosArguments, sizeof(*BiosArguments));
479 
480  return Status;
481 }
NTSTATUS NTAPI NtVdmControl(IN ULONG ControlCode, IN PVOID ControlData)
Definition: stubs.c:422
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define IN
Definition: typedefs.h:39
KAPC_STATE
Definition: ketypes.h:1280
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
VP_STATUS NTAPI IntInt10AllocateBuffer(IN PVOID Context, OUT PUSHORT Seg, OUT PUSHORT Off, IN OUT PULONG Length)
Definition: int10.c:210
#define INFO_(ch,...)
Definition: debug.h:159
GLint x0
Definition: linetemp.h:95
#define KeWaitForMutexObject
Definition: kefuncs.h:555
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
char CHAR
Definition: xmlstorage.h:175
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
LONG NTSTATUS
Definition: precomp.h:26
static VOID ProtectLowV86Mem(VOID)
Definition: int10.c:39
KMUTEX VideoPortInt10Mutex
Definition: videoprt.c:41
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
PKPROCESS CsrProcess
Definition: videoprt.c:39
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
#define NO_ERROR
Definition: dderror.h:5
#define MEM_COMMIT
Definition: nt_native.h:1313
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
uint32_t ULONG_PTR
Definition: typedefs.h:65
VP_STATUS NTAPI IntInt10ReadMemory(IN PVOID Context, IN USHORT Seg, IN USHORT Off, OUT PVOID Buffer, IN ULONG Length)
Definition: int10.c:306
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
return STATUS_NOT_IMPLEMENTED
NTSTATUS NTAPI x86BiosFreeBuffer(_In_ USHORT Segment, _In_ USHORT Offset)
Definition: x86bios.c:181
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define IsLowV86Mem(_Seg, _Off)
Definition: int10.c:33
#define MEM_RESERVE
Definition: nt_native.h:1314
NTSTATUS NTAPI x86BiosAllocateBuffer(_In_ ULONG *Size, _In_ USHORT *Segment, _In_ USHORT *Offset)
Definition: x86bios.c:152
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define PAGE_NOACCESS
Definition: nt_native.h:1302
Definition: bufpool.h:45
NTSTATUS NTAPI IntInitializeVideoAddressSpace(VOID)
Definition: int10.c:200
void * PVOID
Definition: retypes.h:9
NTSTATUS NTAPI x86BiosReadMemory(_In_ USHORT Segment, _In_ USHORT Offset, _Out_writes_bytes_(Size) PVOID Buffer, _In_ ULONG Size)
Definition: x86bios.c:205
VP_STATUS NTAPI IntInt10WriteMemory(IN PVOID Context, IN USHORT Seg, IN USHORT Off, IN PVOID Buffer, IN ULONG Length)
Definition: int10.c:344
VP_STATUS NTAPI IntInt10CallBios(IN PVOID Context, IN OUT PINT10_BIOS_ARGUMENTS BiosArguments)
Definition: int10.c:380
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
#define TRACE_(x)
Definition: compat.h:76
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
CALLBACK16 BiosContext
Definition: bios32.c:45
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
static const WCHAR L[]
Definition: oid.c:1250
#define PAGE_SIZE
Definition: env_spec_w32.h:49
VP_STATUS NTAPI VideoPortInt10(IN PVOID HwDeviceExtension, IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments)
Definition: int10.c:457
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VP_STATUS NTAPI IntInt10FreeBuffer(IN PVOID Context, IN USHORT Seg, IN USHORT Off)
Definition: int10.c:273
NTSTATUS NTAPI Ke386CallBios(IN ULONG Int, OUT PCONTEXT Context)
Definition: v86vdm.c:614
VOID FASTCALL IntAttachToCSRSS(PKPROCESS *CallingProcess, PKAPC_STATE ApcState)
Definition: videoprt.c:496
unsigned short USHORT
Definition: pedump.c:61
struct _KPROCESS * PKPROCESS
Definition: wdm.template.h:206
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1656
static VOID UnprotectLowV86Mem(VOID)
Definition: int10.c:62
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
#define MEM_RELEASE
Definition: nt_native.h:1316
#define OUT
Definition: typedefs.h:40
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
VOID FASTCALL IntDetachFromCSRSS(PKPROCESS *CallingProcess, PKAPC_STATE ApcState)
Definition: videoprt.c:509
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:115
BOOLEAN NTAPI x86BiosCall(_In_ ULONG InterruptNumber, _Inout_ PX86_BIOS_REGISTERS Registers)
Definition: x86bios.c:405
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
LONG VP_STATUS
Definition: video.h:153
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSYSAPI NTSTATUS NTAPI ZwOpenSection(_Out_ PHANDLE SectionHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
#define WARN_(ch,...)
Definition: debug.h:157
unsigned short * PUSHORT
Definition: retypes.h:2
NTSTATUS NTAPI x86BiosWriteMemory(_In_ USHORT Segment, _In_ USHORT Offset, _In_reads_bytes_(Size) PVOID Buffer, _In_ ULONG Size)
Definition: x86bios.c:232
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define NT_ASSERT
Definition: rtlfuncs.h:3310