1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker * The PCI Library -- Physical memory mapping for Windows systems
3*c2e0c6b5SAndroid Build Coastguard Worker *
4*c2e0c6b5SAndroid Build Coastguard Worker * Copyright (c) 2023 Pali Rohár <[email protected]>
5*c2e0c6b5SAndroid Build Coastguard Worker *
6*c2e0c6b5SAndroid Build Coastguard Worker * Can be freely distributed and used under the terms of the GNU GPL v2+
7*c2e0c6b5SAndroid Build Coastguard Worker *
8*c2e0c6b5SAndroid Build Coastguard Worker * SPDX-License-Identifier: GPL-2.0-or-later
9*c2e0c6b5SAndroid Build Coastguard Worker */
10*c2e0c6b5SAndroid Build Coastguard Worker
11*c2e0c6b5SAndroid Build Coastguard Worker #include "internal.h"
12*c2e0c6b5SAndroid Build Coastguard Worker
13*c2e0c6b5SAndroid Build Coastguard Worker #include <windows.h>
14*c2e0c6b5SAndroid Build Coastguard Worker #include <errno.h>
15*c2e0c6b5SAndroid Build Coastguard Worker #include <stdlib.h>
16*c2e0c6b5SAndroid Build Coastguard Worker
17*c2e0c6b5SAndroid Build Coastguard Worker #include "physmem.h"
18*c2e0c6b5SAndroid Build Coastguard Worker #include "win32-helpers.h"
19*c2e0c6b5SAndroid Build Coastguard Worker
20*c2e0c6b5SAndroid Build Coastguard Worker #ifndef NTSTATUS
21*c2e0c6b5SAndroid Build Coastguard Worker #define NTSTATUS LONG
22*c2e0c6b5SAndroid Build Coastguard Worker #endif
23*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_HANDLE
24*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_HANDLE ((NTSTATUS)0xC0000008)
25*c2e0c6b5SAndroid Build Coastguard Worker #endif
26*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_PARAMETER
27*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000D)
28*c2e0c6b5SAndroid Build Coastguard Worker #endif
29*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_CONFLICTING_ADDRESSES
30*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS)0xC0000018)
31*c2e0c6b5SAndroid Build Coastguard Worker #endif
32*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_NOT_MAPPED_VIEW
33*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_NOT_MAPPED_VIEW ((NTSTATUS)0xC0000019)
34*c2e0c6b5SAndroid Build Coastguard Worker #endif
35*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_VIEW_SIZE
36*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_VIEW_SIZE ((NTSTATUS)0xC000001F)
37*c2e0c6b5SAndroid Build Coastguard Worker #endif
38*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_ACCESS_DENIED
39*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022)
40*c2e0c6b5SAndroid Build Coastguard Worker #endif
41*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_OBJECT_NAME_NOT_FOUND
42*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034)
43*c2e0c6b5SAndroid Build Coastguard Worker #endif
44*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_PAGE_PROTECTION
45*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS)0xC0000045)
46*c2e0c6b5SAndroid Build Coastguard Worker #endif
47*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_SECTION_PROTECTION
48*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_SECTION_PROTECTION ((NTSTATUS)0xC000004E)
49*c2e0c6b5SAndroid Build Coastguard Worker #endif
50*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INSUFFICIENT_RESOURCES
51*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009A)
52*c2e0c6b5SAndroid Build Coastguard Worker #endif
53*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_PARAMETER_3
54*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_PARAMETER_3 ((NTSTATUS)0xC00000F1)
55*c2e0c6b5SAndroid Build Coastguard Worker #endif
56*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_PARAMETER_4
57*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_PARAMETER_4 ((NTSTATUS)0xC00000F2)
58*c2e0c6b5SAndroid Build Coastguard Worker #endif
59*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_PARAMETER_5
60*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_PARAMETER_5 ((NTSTATUS)0xC00000F3)
61*c2e0c6b5SAndroid Build Coastguard Worker #endif
62*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_PARAMETER_8
63*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_PARAMETER_8 ((NTSTATUS)0xC00000F6)
64*c2e0c6b5SAndroid Build Coastguard Worker #endif
65*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_INVALID_PARAMETER_9
66*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_INVALID_PARAMETER_9 ((NTSTATUS)0xC00000F7)
67*c2e0c6b5SAndroid Build Coastguard Worker #endif
68*c2e0c6b5SAndroid Build Coastguard Worker #ifndef STATUS_MAPPED_ALIGNMENT
69*c2e0c6b5SAndroid Build Coastguard Worker #define STATUS_MAPPED_ALIGNMENT ((NTSTATUS)0xC0000220)
70*c2e0c6b5SAndroid Build Coastguard Worker #endif
71*c2e0c6b5SAndroid Build Coastguard Worker
72*c2e0c6b5SAndroid Build Coastguard Worker #ifndef OBJ_CASE_INSENSITIVE
73*c2e0c6b5SAndroid Build Coastguard Worker #define OBJ_CASE_INSENSITIVE 0x00000040L
74*c2e0c6b5SAndroid Build Coastguard Worker #endif
75*c2e0c6b5SAndroid Build Coastguard Worker
76*c2e0c6b5SAndroid Build Coastguard Worker #ifndef SECTION_INHERIT
77*c2e0c6b5SAndroid Build Coastguard Worker #define SECTION_INHERIT ULONG
78*c2e0c6b5SAndroid Build Coastguard Worker #endif
79*c2e0c6b5SAndroid Build Coastguard Worker #ifndef ViewUnmap
80*c2e0c6b5SAndroid Build Coastguard Worker #define ViewUnmap ((SECTION_INHERIT)2)
81*c2e0c6b5SAndroid Build Coastguard Worker #endif
82*c2e0c6b5SAndroid Build Coastguard Worker
83*c2e0c6b5SAndroid Build Coastguard Worker #ifndef IMAGE_NT_OPTIONAL_HDR_MAGIC
84*c2e0c6b5SAndroid Build Coastguard Worker #ifdef _WIN64
85*c2e0c6b5SAndroid Build Coastguard Worker #define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x20b
86*c2e0c6b5SAndroid Build Coastguard Worker #else
87*c2e0c6b5SAndroid Build Coastguard Worker #define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
88*c2e0c6b5SAndroid Build Coastguard Worker #endif
89*c2e0c6b5SAndroid Build Coastguard Worker #endif
90*c2e0c6b5SAndroid Build Coastguard Worker
91*c2e0c6b5SAndroid Build Coastguard Worker #ifndef EOVERFLOW
92*c2e0c6b5SAndroid Build Coastguard Worker #define EOVERFLOW 132
93*c2e0c6b5SAndroid Build Coastguard Worker #endif
94*c2e0c6b5SAndroid Build Coastguard Worker
95*c2e0c6b5SAndroid Build Coastguard Worker #if _WIN32_WINNT < 0x0500
96*c2e0c6b5SAndroid Build Coastguard Worker typedef ULONG ULONG_PTR;
97*c2e0c6b5SAndroid Build Coastguard Worker typedef ULONG_PTR SIZE_T, *PSIZE_T;
98*c2e0c6b5SAndroid Build Coastguard Worker #endif
99*c2e0c6b5SAndroid Build Coastguard Worker
100*c2e0c6b5SAndroid Build Coastguard Worker #ifndef __UNICODE_STRING_DEFINED
101*c2e0c6b5SAndroid Build Coastguard Worker #define __UNICODE_STRING_DEFINED
102*c2e0c6b5SAndroid Build Coastguard Worker typedef struct _UNICODE_STRING {
103*c2e0c6b5SAndroid Build Coastguard Worker USHORT Length;
104*c2e0c6b5SAndroid Build Coastguard Worker USHORT MaximumLength;
105*c2e0c6b5SAndroid Build Coastguard Worker PWSTR Buffer;
106*c2e0c6b5SAndroid Build Coastguard Worker } UNICODE_STRING, *PUNICODE_STRING;
107*c2e0c6b5SAndroid Build Coastguard Worker #endif
108*c2e0c6b5SAndroid Build Coastguard Worker
109*c2e0c6b5SAndroid Build Coastguard Worker #ifndef __OBJECT_ATTRIBUTES_DEFINED
110*c2e0c6b5SAndroid Build Coastguard Worker #define __OBJECT_ATTRIBUTES_DEFINED
111*c2e0c6b5SAndroid Build Coastguard Worker typedef struct _OBJECT_ATTRIBUTES {
112*c2e0c6b5SAndroid Build Coastguard Worker ULONG Length;
113*c2e0c6b5SAndroid Build Coastguard Worker HANDLE RootDirectory;
114*c2e0c6b5SAndroid Build Coastguard Worker PUNICODE_STRING ObjectName;
115*c2e0c6b5SAndroid Build Coastguard Worker ULONG Attributes;
116*c2e0c6b5SAndroid Build Coastguard Worker PVOID SecurityDescriptor;
117*c2e0c6b5SAndroid Build Coastguard Worker PVOID SecurityQualityOfService;
118*c2e0c6b5SAndroid Build Coastguard Worker } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
119*c2e0c6b5SAndroid Build Coastguard Worker #endif
120*c2e0c6b5SAndroid Build Coastguard Worker
121*c2e0c6b5SAndroid Build Coastguard Worker #ifndef InitializeObjectAttributes
122*c2e0c6b5SAndroid Build Coastguard Worker #define InitializeObjectAttributes(p, n, a, r, s) \
123*c2e0c6b5SAndroid Build Coastguard Worker { \
124*c2e0c6b5SAndroid Build Coastguard Worker (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
125*c2e0c6b5SAndroid Build Coastguard Worker (p)->RootDirectory = (r); \
126*c2e0c6b5SAndroid Build Coastguard Worker (p)->Attributes = (a); \
127*c2e0c6b5SAndroid Build Coastguard Worker (p)->ObjectName = (n); \
128*c2e0c6b5SAndroid Build Coastguard Worker (p)->SecurityDescriptor = (s); \
129*c2e0c6b5SAndroid Build Coastguard Worker (p)->SecurityQualityOfService = NULL; \
130*c2e0c6b5SAndroid Build Coastguard Worker }
131*c2e0c6b5SAndroid Build Coastguard Worker #endif
132*c2e0c6b5SAndroid Build Coastguard Worker
133*c2e0c6b5SAndroid Build Coastguard Worker #ifndef RtlInitUnicodeString
134*c2e0c6b5SAndroid Build Coastguard Worker #define RtlInitUnicodeString(d, s) \
135*c2e0c6b5SAndroid Build Coastguard Worker { \
136*c2e0c6b5SAndroid Build Coastguard Worker (d)->Length = wcslen(s) * sizeof(WCHAR); \
137*c2e0c6b5SAndroid Build Coastguard Worker (d)->MaximumLength = (d)->Length + sizeof(WCHAR); \
138*c2e0c6b5SAndroid Build Coastguard Worker (d)->Buffer = (PWCHAR)(s); \
139*c2e0c6b5SAndroid Build Coastguard Worker }
140*c2e0c6b5SAndroid Build Coastguard Worker #endif
141*c2e0c6b5SAndroid Build Coastguard Worker
142*c2e0c6b5SAndroid Build Coastguard Worker #define VWIN32_DEVICE_ID 0x0002A /* from vmm.h */
143*c2e0c6b5SAndroid Build Coastguard Worker #define WIN32_SERVICE_ID(device, function) (((device) << 16) | (function))
144*c2e0c6b5SAndroid Build Coastguard Worker #define VWIN32_Int31Dispatch WIN32_SERVICE_ID(VWIN32_DEVICE_ID, 0x29)
145*c2e0c6b5SAndroid Build Coastguard Worker #define DPMI_PHYSICAL_ADDRESS_MAPPING 0x0800
146*c2e0c6b5SAndroid Build Coastguard Worker
147*c2e0c6b5SAndroid Build Coastguard Worker struct physmem {
148*c2e0c6b5SAndroid Build Coastguard Worker HMODULE ntdll;
149*c2e0c6b5SAndroid Build Coastguard Worker HANDLE section_handle;
150*c2e0c6b5SAndroid Build Coastguard Worker NTSTATUS (NTAPI *NtOpenSection)(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
151*c2e0c6b5SAndroid Build Coastguard Worker NTSTATUS (NTAPI *NtMapViewOfSection)(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Win32Protect);
152*c2e0c6b5SAndroid Build Coastguard Worker NTSTATUS (NTAPI *NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);
153*c2e0c6b5SAndroid Build Coastguard Worker ULONG (NTAPI *RtlNtStatusToDosError)(NTSTATUS Status);
154*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__i386__) || defined(_M_IX86)
155*c2e0c6b5SAndroid Build Coastguard Worker DWORD (WINAPI *VxDCall2)(DWORD Service, DWORD Arg1, DWORD Arg2);
156*c2e0c6b5SAndroid Build Coastguard Worker LPVOID w32skrnl_dpmi_lcall_ptr;
157*c2e0c6b5SAndroid Build Coastguard Worker DWORD base_addr_offset;
158*c2e0c6b5SAndroid Build Coastguard Worker #endif
159*c2e0c6b5SAndroid Build Coastguard Worker };
160*c2e0c6b5SAndroid Build Coastguard Worker
161*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__i386__) || defined(_M_IX86)
162*c2e0c6b5SAndroid Build Coastguard Worker
163*c2e0c6b5SAndroid Build Coastguard Worker static BOOL
w32skrnl_physical_address_mapping(struct physmem * physmem,DWORD phys_addr,DWORD size,DWORD * virt_addr)164*c2e0c6b5SAndroid Build Coastguard Worker w32skrnl_physical_address_mapping(struct physmem *physmem, DWORD phys_addr, DWORD size, DWORD *virt_addr)
165*c2e0c6b5SAndroid Build Coastguard Worker {
166*c2e0c6b5SAndroid Build Coastguard Worker DWORD address_hi = phys_addr >> 16;
167*c2e0c6b5SAndroid Build Coastguard Worker DWORD address_lo = phys_addr & 0xffff;
168*c2e0c6b5SAndroid Build Coastguard Worker DWORD size_hi = size >> 16;
169*c2e0c6b5SAndroid Build Coastguard Worker DWORD size_lo = size & 0xffff;
170*c2e0c6b5SAndroid Build Coastguard Worker BYTE failed;
171*c2e0c6b5SAndroid Build Coastguard Worker
172*c2e0c6b5SAndroid Build Coastguard Worker /*
173*c2e0c6b5SAndroid Build Coastguard Worker * Physical address mapping via w32skrnl.dll on Windows maps physical memory
174*c2e0c6b5SAndroid Build Coastguard Worker * and translates it to the virtual space of the current process memory.
175*c2e0c6b5SAndroid Build Coastguard Worker * Works only for aligned address / length and first 1 MB cannot be mapped
176*c2e0c6b5SAndroid Build Coastguard Worker * by this method. Expect that first 1 MB is already 1:1 mapped by the OS.
177*c2e0c6b5SAndroid Build Coastguard Worker * So accept request for physical memory range which is whole below 1 MB
178*c2e0c6b5SAndroid Build Coastguard Worker * without error and return virtual address same as the physical one.
179*c2e0c6b5SAndroid Build Coastguard Worker */
180*c2e0c6b5SAndroid Build Coastguard Worker if (phys_addr < 1*1024*1024UL)
181*c2e0c6b5SAndroid Build Coastguard Worker {
182*c2e0c6b5SAndroid Build Coastguard Worker if ((u64)phys_addr + size > 1*1024*1024UL)
183*c2e0c6b5SAndroid Build Coastguard Worker {
184*c2e0c6b5SAndroid Build Coastguard Worker errno = ENXIO;
185*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
186*c2e0c6b5SAndroid Build Coastguard Worker }
187*c2e0c6b5SAndroid Build Coastguard Worker
188*c2e0c6b5SAndroid Build Coastguard Worker *virt_addr = phys_addr;
189*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
190*c2e0c6b5SAndroid Build Coastguard Worker }
191*c2e0c6b5SAndroid Build Coastguard Worker
192*c2e0c6b5SAndroid Build Coastguard Worker /*
193*c2e0c6b5SAndroid Build Coastguard Worker * Unfortunately w32skrnl.dll provides only 48-bit fword pointer to physical
194*c2e0c6b5SAndroid Build Coastguard Worker * address mapping function and such pointer type is not supported by GCC,
195*c2e0c6b5SAndroid Build Coastguard Worker * nor by MSVC and therefore it is not possible call this function in C code.
196*c2e0c6b5SAndroid Build Coastguard Worker * So call this function with all parameters passed via inline assembly.
197*c2e0c6b5SAndroid Build Coastguard Worker */
198*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__GNUC__)
199*c2e0c6b5SAndroid Build Coastguard Worker asm volatile (
200*c2e0c6b5SAndroid Build Coastguard Worker "stc\n\t"
201*c2e0c6b5SAndroid Build Coastguard Worker "lcall *(%3)\n\t"
202*c2e0c6b5SAndroid Build Coastguard Worker "setc %0\n\t"
203*c2e0c6b5SAndroid Build Coastguard Worker : "=qm" (failed), "+b" (address_hi), "+c" (address_lo)
204*c2e0c6b5SAndroid Build Coastguard Worker : "r" (physmem->w32skrnl_dpmi_lcall_ptr), "a" (DPMI_PHYSICAL_ADDRESS_MAPPING), "S" (size_hi), "D" (size_lo)
205*c2e0c6b5SAndroid Build Coastguard Worker : "cc", "memory"
206*c2e0c6b5SAndroid Build Coastguard Worker );
207*c2e0c6b5SAndroid Build Coastguard Worker #elif defined(_MSC_VER)
208*c2e0c6b5SAndroid Build Coastguard Worker __asm {
209*c2e0c6b5SAndroid Build Coastguard Worker mov esi, size_hi
210*c2e0c6b5SAndroid Build Coastguard Worker mov edi, size_lo
211*c2e0c6b5SAndroid Build Coastguard Worker mov ebx, address_hi
212*c2e0c6b5SAndroid Build Coastguard Worker mov ecx, address_lo
213*c2e0c6b5SAndroid Build Coastguard Worker mov eax, DPMI_PHYSICAL_ADDRESS_MAPPING
214*c2e0c6b5SAndroid Build Coastguard Worker stc
215*c2e0c6b5SAndroid Build Coastguard Worker mov edx, physmem
216*c2e0c6b5SAndroid Build Coastguard Worker mov edx, [edx]physmem.w32skrnl_dpmi_lcall_ptr
217*c2e0c6b5SAndroid Build Coastguard Worker call fword ptr [edx]
218*c2e0c6b5SAndroid Build Coastguard Worker setc failed
219*c2e0c6b5SAndroid Build Coastguard Worker mov address_hi, ebx
220*c2e0c6b5SAndroid Build Coastguard Worker mov address_lo, ecx
221*c2e0c6b5SAndroid Build Coastguard Worker }
222*c2e0c6b5SAndroid Build Coastguard Worker #else
223*c2e0c6b5SAndroid Build Coastguard Worker #error "Unsupported compiler"
224*c2e0c6b5SAndroid Build Coastguard Worker #endif
225*c2e0c6b5SAndroid Build Coastguard Worker
226*c2e0c6b5SAndroid Build Coastguard Worker /*
227*c2e0c6b5SAndroid Build Coastguard Worker * Windows does not provide any error code when this function call fails.
228*c2e0c6b5SAndroid Build Coastguard Worker * So set errno just to the generic EACCES value.
229*c2e0c6b5SAndroid Build Coastguard Worker */
230*c2e0c6b5SAndroid Build Coastguard Worker if (failed)
231*c2e0c6b5SAndroid Build Coastguard Worker {
232*c2e0c6b5SAndroid Build Coastguard Worker errno = EACCES;
233*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
234*c2e0c6b5SAndroid Build Coastguard Worker }
235*c2e0c6b5SAndroid Build Coastguard Worker
236*c2e0c6b5SAndroid Build Coastguard Worker *virt_addr = ((address_hi & 0xffff) << 16) | (address_lo & 0xffff);
237*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
238*c2e0c6b5SAndroid Build Coastguard Worker }
239*c2e0c6b5SAndroid Build Coastguard Worker
240*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4)) && (__GNUC__ <= 11)
241*c2e0c6b5SAndroid Build Coastguard Worker /*
242*c2e0c6b5SAndroid Build Coastguard Worker * GCC versions 4.8 - 11 are buggy and throw error "'asm' operand has impossible
243*c2e0c6b5SAndroid Build Coastguard Worker * constraints" for inline assembly when optimizations (O1+) are enabled. So for
244*c2e0c6b5SAndroid Build Coastguard Worker * these GCC versions disable buggy optimizations by enforcing O0 optimize flag
245*c2e0c6b5SAndroid Build Coastguard Worker * affecting just this one function.
246*c2e0c6b5SAndroid Build Coastguard Worker */
247*c2e0c6b5SAndroid Build Coastguard Worker __attribute__((optimize("O0")))
248*c2e0c6b5SAndroid Build Coastguard Worker #endif
249*c2e0c6b5SAndroid Build Coastguard Worker static BOOL
vdxcall_physical_address_mapping(struct physmem * physmem,DWORD phys_addr,DWORD size,DWORD * virt_addr)250*c2e0c6b5SAndroid Build Coastguard Worker vdxcall_physical_address_mapping(struct physmem *physmem, DWORD phys_addr, DWORD size, DWORD *virt_addr)
251*c2e0c6b5SAndroid Build Coastguard Worker {
252*c2e0c6b5SAndroid Build Coastguard Worker DWORD address_hi = phys_addr >> 16;
253*c2e0c6b5SAndroid Build Coastguard Worker DWORD address_lo = phys_addr & 0xffff;
254*c2e0c6b5SAndroid Build Coastguard Worker DWORD size_hi = size >> 16;
255*c2e0c6b5SAndroid Build Coastguard Worker DWORD size_lo = size & 0xffff;
256*c2e0c6b5SAndroid Build Coastguard Worker BYTE failed;
257*c2e0c6b5SAndroid Build Coastguard Worker
258*c2e0c6b5SAndroid Build Coastguard Worker /*
259*c2e0c6b5SAndroid Build Coastguard Worker * Physical address mapping via VxDCall2() on Windows maps physical memory
260*c2e0c6b5SAndroid Build Coastguard Worker * and translates it to the virtual space of the current process memory.
261*c2e0c6b5SAndroid Build Coastguard Worker * There are no restrictions for aligning or physical address ranges.
262*c2e0c6b5SAndroid Build Coastguard Worker * Works with any (unaligned) address or length, including low 1MB range.
263*c2e0c6b5SAndroid Build Coastguard Worker */
264*c2e0c6b5SAndroid Build Coastguard Worker
265*c2e0c6b5SAndroid Build Coastguard Worker /*
266*c2e0c6b5SAndroid Build Coastguard Worker * Function VxDCall2() has strange calling convention. First 3 arguments are
267*c2e0c6b5SAndroid Build Coastguard Worker * passed on stack, which callee pops (same as stdcall convention) but rest
268*c2e0c6b5SAndroid Build Coastguard Worker * of the function arguments are passed in ESI, EDI and EBX registers. And
269*c2e0c6b5SAndroid Build Coastguard Worker * return value is in carry flag (CF) and AX, BX and CX registers. GCC and
270*c2e0c6b5SAndroid Build Coastguard Worker * neither MSVC do not support this strange calling convention, so call this
271*c2e0c6b5SAndroid Build Coastguard Worker * function via inline assembly.
272*c2e0c6b5SAndroid Build Coastguard Worker *
273*c2e0c6b5SAndroid Build Coastguard Worker * Pseudocode with stdcall calling convention of that function looks like:
274*c2e0c6b5SAndroid Build Coastguard Worker * ESI = size_hi
275*c2e0c6b5SAndroid Build Coastguard Worker * EDI = size_lo
276*c2e0c6b5SAndroid Build Coastguard Worker * EBX = address_hi
277*c2e0c6b5SAndroid Build Coastguard Worker * VxDCall2(VWIN32_Int31Dispatch, DPMI_PHYSICAL_ADDRESS_MAPPING, address_lo)
278*c2e0c6b5SAndroid Build Coastguard Worker * failed = CF
279*c2e0c6b5SAndroid Build Coastguard Worker * address_hi = BX (if not failed)
280*c2e0c6b5SAndroid Build Coastguard Worker * address_lo = CX (if not failed)
281*c2e0c6b5SAndroid Build Coastguard Worker */
282*c2e0c6b5SAndroid Build Coastguard Worker
283*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__GNUC__)
284*c2e0c6b5SAndroid Build Coastguard Worker asm volatile (
285*c2e0c6b5SAndroid Build Coastguard Worker "pushl %6\n\t"
286*c2e0c6b5SAndroid Build Coastguard Worker "pushl %5\n\t"
287*c2e0c6b5SAndroid Build Coastguard Worker "pushl %4\n\t"
288*c2e0c6b5SAndroid Build Coastguard Worker "stc\n\t"
289*c2e0c6b5SAndroid Build Coastguard Worker "call *%P3\n\t"
290*c2e0c6b5SAndroid Build Coastguard Worker "setc %0\n\t"
291*c2e0c6b5SAndroid Build Coastguard Worker : "=qm" (failed), "+b" (address_hi), "=c" (address_lo)
292*c2e0c6b5SAndroid Build Coastguard Worker : "rmi" (physmem->VxDCall2), "rmi" (VWIN32_Int31Dispatch), "rmi" (DPMI_PHYSICAL_ADDRESS_MAPPING),
293*c2e0c6b5SAndroid Build Coastguard Worker "rmi" (address_lo), "S" (size_hi), "D" (size_lo)
294*c2e0c6b5SAndroid Build Coastguard Worker /* Specify all call clobbered scratch registers for stdcall calling convention. */
295*c2e0c6b5SAndroid Build Coastguard Worker : "eax", "edx",
296*c2e0c6b5SAndroid Build Coastguard Worker /*
297*c2e0c6b5SAndroid Build Coastguard Worker * Since GCC version 4.9.0 it is possible to specify x87 registers as clobbering
298*c2e0c6b5SAndroid Build Coastguard Worker * if they are not disabled by -mno-80387 switch (which defines _SOFT_FLOAT).
299*c2e0c6b5SAndroid Build Coastguard Worker */
300*c2e0c6b5SAndroid Build Coastguard Worker #if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || (__GNUC__ > 4)) && !defined(_SOFT_FLOAT)
301*c2e0c6b5SAndroid Build Coastguard Worker "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
302*c2e0c6b5SAndroid Build Coastguard Worker #endif
303*c2e0c6b5SAndroid Build Coastguard Worker #ifdef __MMX__
304*c2e0c6b5SAndroid Build Coastguard Worker "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm6",
305*c2e0c6b5SAndroid Build Coastguard Worker #endif
306*c2e0c6b5SAndroid Build Coastguard Worker #ifdef __SSE__
307*c2e0c6b5SAndroid Build Coastguard Worker "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
308*c2e0c6b5SAndroid Build Coastguard Worker #endif
309*c2e0c6b5SAndroid Build Coastguard Worker "cc", "memory"
310*c2e0c6b5SAndroid Build Coastguard Worker );
311*c2e0c6b5SAndroid Build Coastguard Worker #elif defined(_MSC_VER)
312*c2e0c6b5SAndroid Build Coastguard Worker __asm {
313*c2e0c6b5SAndroid Build Coastguard Worker mov esi, size_hi
314*c2e0c6b5SAndroid Build Coastguard Worker mov edi, size_lo
315*c2e0c6b5SAndroid Build Coastguard Worker mov ebx, address_hi
316*c2e0c6b5SAndroid Build Coastguard Worker push address_lo
317*c2e0c6b5SAndroid Build Coastguard Worker push DPMI_PHYSICAL_ADDRESS_MAPPING
318*c2e0c6b5SAndroid Build Coastguard Worker push VWIN32_Int31Dispatch
319*c2e0c6b5SAndroid Build Coastguard Worker stc
320*c2e0c6b5SAndroid Build Coastguard Worker mov eax, physmem
321*c2e0c6b5SAndroid Build Coastguard Worker call [eax]physmem.VxDCall2
322*c2e0c6b5SAndroid Build Coastguard Worker setc failed
323*c2e0c6b5SAndroid Build Coastguard Worker mov address_hi, ebx
324*c2e0c6b5SAndroid Build Coastguard Worker mov address_lo, ecx
325*c2e0c6b5SAndroid Build Coastguard Worker }
326*c2e0c6b5SAndroid Build Coastguard Worker #else
327*c2e0c6b5SAndroid Build Coastguard Worker #error "Unsupported compiler"
328*c2e0c6b5SAndroid Build Coastguard Worker #endif
329*c2e0c6b5SAndroid Build Coastguard Worker
330*c2e0c6b5SAndroid Build Coastguard Worker /*
331*c2e0c6b5SAndroid Build Coastguard Worker * Windows does not provide any error code when this function call fails.
332*c2e0c6b5SAndroid Build Coastguard Worker * So set errno just to the generic EACCES value.
333*c2e0c6b5SAndroid Build Coastguard Worker */
334*c2e0c6b5SAndroid Build Coastguard Worker if (failed)
335*c2e0c6b5SAndroid Build Coastguard Worker {
336*c2e0c6b5SAndroid Build Coastguard Worker errno = EACCES;
337*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
338*c2e0c6b5SAndroid Build Coastguard Worker }
339*c2e0c6b5SAndroid Build Coastguard Worker
340*c2e0c6b5SAndroid Build Coastguard Worker *virt_addr = ((address_hi & 0xffff) << 16) | (address_lo & 0xffff);
341*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
342*c2e0c6b5SAndroid Build Coastguard Worker }
343*c2e0c6b5SAndroid Build Coastguard Worker
344*c2e0c6b5SAndroid Build Coastguard Worker static BOOL
win32_get_physmem_offset(DWORD * offset)345*c2e0c6b5SAndroid Build Coastguard Worker win32_get_physmem_offset(DWORD *offset)
346*c2e0c6b5SAndroid Build Coastguard Worker {
347*c2e0c6b5SAndroid Build Coastguard Worker WORD DSsel;
348*c2e0c6b5SAndroid Build Coastguard Worker LDT_ENTRY DSentry;
349*c2e0c6b5SAndroid Build Coastguard Worker
350*c2e0c6b5SAndroid Build Coastguard Worker /*
351*c2e0c6b5SAndroid Build Coastguard Worker * Read DS selector. For this purpose there is WinAPI function and when called
352*c2e0c6b5SAndroid Build Coastguard Worker * as GetThreadContext(GetCurrentThread(), ...) with CONTEXT_SEGMENTS param,
353*c2e0c6b5SAndroid Build Coastguard Worker * it fills SegDs value. But on some Windows versions, GetThreadContext() can
354*c2e0c6b5SAndroid Build Coastguard Worker * be called only for threads attached to debugger. Hence we cannot use it for
355*c2e0c6b5SAndroid Build Coastguard Worker * our current thread. So instead read DS selector directly from ds register
356*c2e0c6b5SAndroid Build Coastguard Worker * via inline assembly code.
357*c2e0c6b5SAndroid Build Coastguard Worker */
358*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__GNUC__)
359*c2e0c6b5SAndroid Build Coastguard Worker asm ("movw %%ds, %w0" : "=rm" (DSsel));
360*c2e0c6b5SAndroid Build Coastguard Worker #elif defined(_MSC_VER)
361*c2e0c6b5SAndroid Build Coastguard Worker __asm { mov DSsel, ds }
362*c2e0c6b5SAndroid Build Coastguard Worker #else
363*c2e0c6b5SAndroid Build Coastguard Worker #error "Unsupported compiler"
364*c2e0c6b5SAndroid Build Coastguard Worker #endif
365*c2e0c6b5SAndroid Build Coastguard Worker
366*c2e0c6b5SAndroid Build Coastguard Worker if (!GetThreadSelectorEntry(GetCurrentThread(), DSsel, &DSentry))
367*c2e0c6b5SAndroid Build Coastguard Worker return FALSE;
368*c2e0c6b5SAndroid Build Coastguard Worker
369*c2e0c6b5SAndroid Build Coastguard Worker *offset = DSentry.BaseLow | (DSentry.HighWord.Bytes.BaseMid << 0x10) | (DSentry.HighWord.Bytes.BaseHi << 0x18);
370*c2e0c6b5SAndroid Build Coastguard Worker return TRUE;
371*c2e0c6b5SAndroid Build Coastguard Worker }
372*c2e0c6b5SAndroid Build Coastguard Worker
373*c2e0c6b5SAndroid Build Coastguard Worker static BYTE *
win32_get_baseaddr_from_hmodule(HMODULE module)374*c2e0c6b5SAndroid Build Coastguard Worker win32_get_baseaddr_from_hmodule(HMODULE module)
375*c2e0c6b5SAndroid Build Coastguard Worker {
376*c2e0c6b5SAndroid Build Coastguard Worker WORD (WINAPI *ImteFromHModule)(HMODULE);
377*c2e0c6b5SAndroid Build Coastguard Worker BYTE *(WINAPI *BaseAddrFromImte)(WORD);
378*c2e0c6b5SAndroid Build Coastguard Worker HMODULE w32skrnl;
379*c2e0c6b5SAndroid Build Coastguard Worker WORD imte;
380*c2e0c6b5SAndroid Build Coastguard Worker
381*c2e0c6b5SAndroid Build Coastguard Worker if ((GetVersion() & 0xC0000000) != 0x80000000)
382*c2e0c6b5SAndroid Build Coastguard Worker return (BYTE *)module;
383*c2e0c6b5SAndroid Build Coastguard Worker
384*c2e0c6b5SAndroid Build Coastguard Worker w32skrnl = GetModuleHandleA("w32skrnl.dll");
385*c2e0c6b5SAndroid Build Coastguard Worker if (!w32skrnl)
386*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
387*c2e0c6b5SAndroid Build Coastguard Worker
388*c2e0c6b5SAndroid Build Coastguard Worker ImteFromHModule = (LPVOID)GetProcAddress(w32skrnl, "_ImteFromHModule@4");
389*c2e0c6b5SAndroid Build Coastguard Worker BaseAddrFromImte = (LPVOID)GetProcAddress(w32skrnl, "_BaseAddrFromImte@4");
390*c2e0c6b5SAndroid Build Coastguard Worker if (!ImteFromHModule || !BaseAddrFromImte)
391*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
392*c2e0c6b5SAndroid Build Coastguard Worker
393*c2e0c6b5SAndroid Build Coastguard Worker imte = ImteFromHModule(module);
394*c2e0c6b5SAndroid Build Coastguard Worker if (imte == 0xffff)
395*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
396*c2e0c6b5SAndroid Build Coastguard Worker
397*c2e0c6b5SAndroid Build Coastguard Worker return BaseAddrFromImte(imte);
398*c2e0c6b5SAndroid Build Coastguard Worker }
399*c2e0c6b5SAndroid Build Coastguard Worker
400*c2e0c6b5SAndroid Build Coastguard Worker static FARPROC
win32_get_proc_address_by_ordinal(HMODULE module,DWORD ordinal,BOOL must_be_without_name)401*c2e0c6b5SAndroid Build Coastguard Worker win32_get_proc_address_by_ordinal(HMODULE module, DWORD ordinal, BOOL must_be_without_name)
402*c2e0c6b5SAndroid Build Coastguard Worker {
403*c2e0c6b5SAndroid Build Coastguard Worker BYTE *baseaddr;
404*c2e0c6b5SAndroid Build Coastguard Worker IMAGE_DOS_HEADER *dos_header;
405*c2e0c6b5SAndroid Build Coastguard Worker IMAGE_NT_HEADERS *nt_header;
406*c2e0c6b5SAndroid Build Coastguard Worker DWORD export_dir_offset, export_dir_size;
407*c2e0c6b5SAndroid Build Coastguard Worker IMAGE_EXPORT_DIRECTORY *export_dir;
408*c2e0c6b5SAndroid Build Coastguard Worker DWORD base_ordinal, func_count;
409*c2e0c6b5SAndroid Build Coastguard Worker DWORD *func_addrs;
410*c2e0c6b5SAndroid Build Coastguard Worker FARPROC func_ptr;
411*c2e0c6b5SAndroid Build Coastguard Worker DWORD names_count, i;
412*c2e0c6b5SAndroid Build Coastguard Worker USHORT *names_idxs;
413*c2e0c6b5SAndroid Build Coastguard Worker UINT prev_error_mode;
414*c2e0c6b5SAndroid Build Coastguard Worker char module_name[MAX_PATH];
415*c2e0c6b5SAndroid Build Coastguard Worker DWORD module_name_len;
416*c2e0c6b5SAndroid Build Coastguard Worker char *export_name;
417*c2e0c6b5SAndroid Build Coastguard Worker char *endptr;
418*c2e0c6b5SAndroid Build Coastguard Worker long num;
419*c2e0c6b5SAndroid Build Coastguard Worker
420*c2e0c6b5SAndroid Build Coastguard Worker baseaddr = win32_get_baseaddr_from_hmodule(module);
421*c2e0c6b5SAndroid Build Coastguard Worker if (!baseaddr)
422*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
423*c2e0c6b5SAndroid Build Coastguard Worker
424*c2e0c6b5SAndroid Build Coastguard Worker dos_header = (IMAGE_DOS_HEADER *)baseaddr;
425*c2e0c6b5SAndroid Build Coastguard Worker if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
426*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
427*c2e0c6b5SAndroid Build Coastguard Worker
428*c2e0c6b5SAndroid Build Coastguard Worker nt_header = (IMAGE_NT_HEADERS *)((BYTE *)dos_header + dos_header->e_lfanew);
429*c2e0c6b5SAndroid Build Coastguard Worker if (nt_header->Signature != IMAGE_NT_SIGNATURE)
430*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
431*c2e0c6b5SAndroid Build Coastguard Worker
432*c2e0c6b5SAndroid Build Coastguard Worker if (nt_header->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
433*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
434*c2e0c6b5SAndroid Build Coastguard Worker
435*c2e0c6b5SAndroid Build Coastguard Worker if (nt_header->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT)
436*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
437*c2e0c6b5SAndroid Build Coastguard Worker
438*c2e0c6b5SAndroid Build Coastguard Worker export_dir_offset = nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
439*c2e0c6b5SAndroid Build Coastguard Worker export_dir_size = nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
440*c2e0c6b5SAndroid Build Coastguard Worker
441*c2e0c6b5SAndroid Build Coastguard Worker if (!export_dir_offset || !export_dir_size)
442*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
443*c2e0c6b5SAndroid Build Coastguard Worker
444*c2e0c6b5SAndroid Build Coastguard Worker export_dir = (IMAGE_EXPORT_DIRECTORY *)(baseaddr + export_dir_offset);
445*c2e0c6b5SAndroid Build Coastguard Worker base_ordinal = export_dir->Base;
446*c2e0c6b5SAndroid Build Coastguard Worker func_count = export_dir->NumberOfFunctions;
447*c2e0c6b5SAndroid Build Coastguard Worker func_addrs = (DWORD *)(baseaddr + (DWORD)export_dir->AddressOfFunctions);
448*c2e0c6b5SAndroid Build Coastguard Worker
449*c2e0c6b5SAndroid Build Coastguard Worker if (ordinal < base_ordinal || ordinal - base_ordinal > func_count)
450*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
451*c2e0c6b5SAndroid Build Coastguard Worker
452*c2e0c6b5SAndroid Build Coastguard Worker if (must_be_without_name)
453*c2e0c6b5SAndroid Build Coastguard Worker {
454*c2e0c6b5SAndroid Build Coastguard Worker /* Check that function with ordinal number does not have any name. */
455*c2e0c6b5SAndroid Build Coastguard Worker names_count = export_dir->NumberOfNames;
456*c2e0c6b5SAndroid Build Coastguard Worker names_idxs = (USHORT *)(baseaddr + (DWORD)export_dir->AddressOfNameOrdinals);
457*c2e0c6b5SAndroid Build Coastguard Worker for (i = 0; i < names_count; i++)
458*c2e0c6b5SAndroid Build Coastguard Worker {
459*c2e0c6b5SAndroid Build Coastguard Worker if (names_idxs[i] == ordinal - base_ordinal)
460*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
461*c2e0c6b5SAndroid Build Coastguard Worker }
462*c2e0c6b5SAndroid Build Coastguard Worker }
463*c2e0c6b5SAndroid Build Coastguard Worker
464*c2e0c6b5SAndroid Build Coastguard Worker func_ptr = (FARPROC)(baseaddr + func_addrs[ordinal - base_ordinal]);
465*c2e0c6b5SAndroid Build Coastguard Worker if ((BYTE *)func_ptr >= (BYTE *)export_dir && (BYTE *)func_ptr < (BYTE *)export_dir + export_dir_size)
466*c2e0c6b5SAndroid Build Coastguard Worker {
467*c2e0c6b5SAndroid Build Coastguard Worker /*
468*c2e0c6b5SAndroid Build Coastguard Worker * We need to locate the _last_ dot character (separator of library name
469*c2e0c6b5SAndroid Build Coastguard Worker * and export symbol name) because library name may contain dot character
470*c2e0c6b5SAndroid Build Coastguard Worker * (used when specifying file name with explicit extension). For example
471*c2e0c6b5SAndroid Build Coastguard Worker * wine is using this kind of strange symbol redirection to different
472*c2e0c6b5SAndroid Build Coastguard Worker * library with non-standard file name extension (different than .dll).
473*c2e0c6b5SAndroid Build Coastguard Worker */
474*c2e0c6b5SAndroid Build Coastguard Worker export_name = strrchr((char *)func_ptr, '.');
475*c2e0c6b5SAndroid Build Coastguard Worker if (!export_name)
476*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
477*c2e0c6b5SAndroid Build Coastguard Worker export_name++;
478*c2e0c6b5SAndroid Build Coastguard Worker
479*c2e0c6b5SAndroid Build Coastguard Worker module_name_len = export_name - 1 - (char *)func_ptr;
480*c2e0c6b5SAndroid Build Coastguard Worker if (module_name_len >= sizeof(module_name))
481*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
482*c2e0c6b5SAndroid Build Coastguard Worker
483*c2e0c6b5SAndroid Build Coastguard Worker memcpy(module_name, func_ptr, module_name_len);
484*c2e0c6b5SAndroid Build Coastguard Worker module_name[module_name_len] = 0;
485*c2e0c6b5SAndroid Build Coastguard Worker
486*c2e0c6b5SAndroid Build Coastguard Worker prev_error_mode = win32_change_error_mode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
487*c2e0c6b5SAndroid Build Coastguard Worker module = LoadLibraryA(module_name);
488*c2e0c6b5SAndroid Build Coastguard Worker win32_change_error_mode(prev_error_mode);
489*c2e0c6b5SAndroid Build Coastguard Worker if (!module)
490*c2e0c6b5SAndroid Build Coastguard Worker {
491*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(module);
492*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
493*c2e0c6b5SAndroid Build Coastguard Worker }
494*c2e0c6b5SAndroid Build Coastguard Worker
495*c2e0c6b5SAndroid Build Coastguard Worker if (*export_name == '#')
496*c2e0c6b5SAndroid Build Coastguard Worker {
497*c2e0c6b5SAndroid Build Coastguard Worker export_name++;
498*c2e0c6b5SAndroid Build Coastguard Worker errno = 0;
499*c2e0c6b5SAndroid Build Coastguard Worker num = strtol(export_name, &endptr, 10);
500*c2e0c6b5SAndroid Build Coastguard Worker if (*export_name < '0' || *export_name > '9' || errno || *endptr || num < 0 || (unsigned long)num >= ((DWORD)-1)/2)
501*c2e0c6b5SAndroid Build Coastguard Worker {
502*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(module);
503*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
504*c2e0c6b5SAndroid Build Coastguard Worker }
505*c2e0c6b5SAndroid Build Coastguard Worker ordinal = num;
506*c2e0c6b5SAndroid Build Coastguard Worker func_ptr = win32_get_proc_address_by_ordinal(module, ordinal, FALSE);
507*c2e0c6b5SAndroid Build Coastguard Worker }
508*c2e0c6b5SAndroid Build Coastguard Worker else
509*c2e0c6b5SAndroid Build Coastguard Worker {
510*c2e0c6b5SAndroid Build Coastguard Worker func_ptr = GetProcAddress(module, export_name);
511*c2e0c6b5SAndroid Build Coastguard Worker }
512*c2e0c6b5SAndroid Build Coastguard Worker
513*c2e0c6b5SAndroid Build Coastguard Worker if (!func_ptr)
514*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(module);
515*c2e0c6b5SAndroid Build Coastguard Worker }
516*c2e0c6b5SAndroid Build Coastguard Worker
517*c2e0c6b5SAndroid Build Coastguard Worker return func_ptr;
518*c2e0c6b5SAndroid Build Coastguard Worker }
519*c2e0c6b5SAndroid Build Coastguard Worker
520*c2e0c6b5SAndroid Build Coastguard Worker static int
init_physmem_w32skrnl(struct physmem * physmem,struct pci_access * a)521*c2e0c6b5SAndroid Build Coastguard Worker init_physmem_w32skrnl(struct physmem *physmem, struct pci_access *a)
522*c2e0c6b5SAndroid Build Coastguard Worker {
523*c2e0c6b5SAndroid Build Coastguard Worker HMODULE w32skrnl;
524*c2e0c6b5SAndroid Build Coastguard Worker LPVOID (WINAPI *GetThunkBuff)(VOID);
525*c2e0c6b5SAndroid Build Coastguard Worker OSVERSIONINFOA version;
526*c2e0c6b5SAndroid Build Coastguard Worker LPVOID buf_ptr;
527*c2e0c6b5SAndroid Build Coastguard Worker
528*c2e0c6b5SAndroid Build Coastguard Worker a->debug("resolving DPMI function via GetThunkBuff() function from w32skrnl.dll...");
529*c2e0c6b5SAndroid Build Coastguard Worker w32skrnl = GetModuleHandleA("w32skrnl.dll");
530*c2e0c6b5SAndroid Build Coastguard Worker if (!w32skrnl)
531*c2e0c6b5SAndroid Build Coastguard Worker {
532*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: library not present.");
533*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
534*c2e0c6b5SAndroid Build Coastguard Worker return 0;
535*c2e0c6b5SAndroid Build Coastguard Worker }
536*c2e0c6b5SAndroid Build Coastguard Worker
537*c2e0c6b5SAndroid Build Coastguard Worker GetThunkBuff = (LPVOID)GetProcAddress(w32skrnl, "_GetThunkBuff@0");
538*c2e0c6b5SAndroid Build Coastguard Worker if (!GetThunkBuff)
539*c2e0c6b5SAndroid Build Coastguard Worker {
540*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: symbol not found.");
541*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
542*c2e0c6b5SAndroid Build Coastguard Worker return 0;
543*c2e0c6b5SAndroid Build Coastguard Worker }
544*c2e0c6b5SAndroid Build Coastguard Worker
545*c2e0c6b5SAndroid Build Coastguard Worker version.dwOSVersionInfoSize = sizeof(version);
546*c2e0c6b5SAndroid Build Coastguard Worker if (!GetVersionExA(&version))
547*c2e0c6b5SAndroid Build Coastguard Worker {
548*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: cannot detect version.");
549*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
550*c2e0c6b5SAndroid Build Coastguard Worker return 0;
551*c2e0c6b5SAndroid Build Coastguard Worker }
552*c2e0c6b5SAndroid Build Coastguard Worker
553*c2e0c6b5SAndroid Build Coastguard Worker /* Versions before 1.1 (1.1.88) are not supported. */
554*c2e0c6b5SAndroid Build Coastguard Worker if (version.dwMajorVersion < 1 || (version.dwMajorVersion == 1 && version.dwMinorVersion < 1))
555*c2e0c6b5SAndroid Build Coastguard Worker {
556*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: found old incompatible version.");
557*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
558*c2e0c6b5SAndroid Build Coastguard Worker return 0;
559*c2e0c6b5SAndroid Build Coastguard Worker }
560*c2e0c6b5SAndroid Build Coastguard Worker
561*c2e0c6b5SAndroid Build Coastguard Worker if (!win32_get_physmem_offset(&physmem->base_addr_offset))
562*c2e0c6b5SAndroid Build Coastguard Worker {
563*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: cannot retrieve physical address offset: %s.", win32_strerror(GetLastError()));
564*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
565*c2e0c6b5SAndroid Build Coastguard Worker return 0;
566*c2e0c6b5SAndroid Build Coastguard Worker }
567*c2e0c6b5SAndroid Build Coastguard Worker
568*c2e0c6b5SAndroid Build Coastguard Worker buf_ptr = GetThunkBuff();
569*c2e0c6b5SAndroid Build Coastguard Worker if (!buf_ptr)
570*c2e0c6b5SAndroid Build Coastguard Worker {
571*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: cannot retrieve DPMI function pointer.");
572*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
573*c2e0c6b5SAndroid Build Coastguard Worker return 0;
574*c2e0c6b5SAndroid Build Coastguard Worker }
575*c2e0c6b5SAndroid Build Coastguard Worker
576*c2e0c6b5SAndroid Build Coastguard Worker /*
577*c2e0c6b5SAndroid Build Coastguard Worker * Versions 1.1 (1.1.88) - 1.15 (1.15.103) have DPMI function at offset 0xa0.
578*c2e0c6b5SAndroid Build Coastguard Worker * Versions 1.15a (1.15.111) - 1.30c (1.30.172) have DPMI function at offset 0xa4.
579*c2e0c6b5SAndroid Build Coastguard Worker */
580*c2e0c6b5SAndroid Build Coastguard Worker if (version.dwMajorVersion > 1 ||
581*c2e0c6b5SAndroid Build Coastguard Worker (version.dwMajorVersion == 1 && version.dwMinorVersion > 15) ||
582*c2e0c6b5SAndroid Build Coastguard Worker (version.dwMajorVersion == 1 && version.dwMinorVersion == 15 && version.dwBuildNumber >= 111))
583*c2e0c6b5SAndroid Build Coastguard Worker physmem->w32skrnl_dpmi_lcall_ptr = (LPVOID)((BYTE *)buf_ptr + 0xa4);
584*c2e0c6b5SAndroid Build Coastguard Worker else
585*c2e0c6b5SAndroid Build Coastguard Worker physmem->w32skrnl_dpmi_lcall_ptr = (LPVOID)((BYTE *)buf_ptr + 0xa0);
586*c2e0c6b5SAndroid Build Coastguard Worker
587*c2e0c6b5SAndroid Build Coastguard Worker a->debug("success.");
588*c2e0c6b5SAndroid Build Coastguard Worker return 1;
589*c2e0c6b5SAndroid Build Coastguard Worker }
590*c2e0c6b5SAndroid Build Coastguard Worker
591*c2e0c6b5SAndroid Build Coastguard Worker static int
init_physmem_vxdcall(struct physmem * physmem,struct pci_access * a)592*c2e0c6b5SAndroid Build Coastguard Worker init_physmem_vxdcall(struct physmem *physmem, struct pci_access *a)
593*c2e0c6b5SAndroid Build Coastguard Worker {
594*c2e0c6b5SAndroid Build Coastguard Worker HMODULE kernel32;
595*c2e0c6b5SAndroid Build Coastguard Worker BOOL success;
596*c2e0c6b5SAndroid Build Coastguard Worker DWORD addr;
597*c2e0c6b5SAndroid Build Coastguard Worker
598*c2e0c6b5SAndroid Build Coastguard Worker a->debug("resolving VxDCall2() function from kernel32.dll...");
599*c2e0c6b5SAndroid Build Coastguard Worker kernel32 = GetModuleHandleA("kernel32.dll");
600*c2e0c6b5SAndroid Build Coastguard Worker if (!kernel32)
601*c2e0c6b5SAndroid Build Coastguard Worker {
602*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: library not present.");
603*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
604*c2e0c6b5SAndroid Build Coastguard Worker return 0;
605*c2e0c6b5SAndroid Build Coastguard Worker }
606*c2e0c6b5SAndroid Build Coastguard Worker
607*c2e0c6b5SAndroid Build Coastguard Worker /*
608*c2e0c6b5SAndroid Build Coastguard Worker * New Windows versions do not export VxDCall2 symbol by name anymore,
609*c2e0c6b5SAndroid Build Coastguard Worker * so try also locating this symbol by its ordinal number, which is 3.
610*c2e0c6b5SAndroid Build Coastguard Worker * Old Windows versions prevents using GetProcAddress() for locating
611*c2e0c6b5SAndroid Build Coastguard Worker * kernel32.dll symbol by ordinal number, so use our own custom function.
612*c2e0c6b5SAndroid Build Coastguard Worker * When locating via ordinal number, check that this ordinal number does
613*c2e0c6b5SAndroid Build Coastguard Worker * not have any name assigned (to ensure that it is really VxDCall2).
614*c2e0c6b5SAndroid Build Coastguard Worker */
615*c2e0c6b5SAndroid Build Coastguard Worker physmem->VxDCall2 = (LPVOID)GetProcAddress(kernel32, "VxDCall2");
616*c2e0c6b5SAndroid Build Coastguard Worker if (!physmem->VxDCall2)
617*c2e0c6b5SAndroid Build Coastguard Worker physmem->VxDCall2 = (LPVOID)win32_get_proc_address_by_ordinal(kernel32, 3, TRUE);
618*c2e0c6b5SAndroid Build Coastguard Worker
619*c2e0c6b5SAndroid Build Coastguard Worker if (!physmem->VxDCall2)
620*c2e0c6b5SAndroid Build Coastguard Worker {
621*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: symbol not found.");
622*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
623*c2e0c6b5SAndroid Build Coastguard Worker return 0;
624*c2e0c6b5SAndroid Build Coastguard Worker }
625*c2e0c6b5SAndroid Build Coastguard Worker
626*c2e0c6b5SAndroid Build Coastguard Worker /*
627*c2e0c6b5SAndroid Build Coastguard Worker * Wine implementation of VxDCall2() does not support physical address
628*c2e0c6b5SAndroid Build Coastguard Worker * mapping but returns success with virtual address same as passed physical
629*c2e0c6b5SAndroid Build Coastguard Worker * address. Detect this broken wine behavior by trying to map zero address
630*c2e0c6b5SAndroid Build Coastguard Worker * of zero range. Broken wine implementation returns NULL pointer. This
631*c2e0c6b5SAndroid Build Coastguard Worker * prevents accessing unmapped memory or dereferencing NULL pointer.
632*c2e0c6b5SAndroid Build Coastguard Worker */
633*c2e0c6b5SAndroid Build Coastguard Worker success = vdxcall_physical_address_mapping(physmem, 0x0, 0x0, &addr);
634*c2e0c6b5SAndroid Build Coastguard Worker if (success && addr == 0x0)
635*c2e0c6b5SAndroid Build Coastguard Worker {
636*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: physical address mapping via VxDCall2() is broken.");
637*c2e0c6b5SAndroid Build Coastguard Worker physmem->VxDCall2 = NULL;
638*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
639*c2e0c6b5SAndroid Build Coastguard Worker return 0;
640*c2e0c6b5SAndroid Build Coastguard Worker }
641*c2e0c6b5SAndroid Build Coastguard Worker else if (!success)
642*c2e0c6b5SAndroid Build Coastguard Worker {
643*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: physical address mapping via VxDCall2() is unsupported.");
644*c2e0c6b5SAndroid Build Coastguard Worker physmem->VxDCall2 = NULL;
645*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
646*c2e0c6b5SAndroid Build Coastguard Worker return 0;
647*c2e0c6b5SAndroid Build Coastguard Worker }
648*c2e0c6b5SAndroid Build Coastguard Worker
649*c2e0c6b5SAndroid Build Coastguard Worker /* Retrieve base address - offset for all addresses returned by VxDCall2(). */
650*c2e0c6b5SAndroid Build Coastguard Worker if (!win32_get_physmem_offset(&physmem->base_addr_offset))
651*c2e0c6b5SAndroid Build Coastguard Worker {
652*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: cannot retrieve physical address offset: %s.", win32_strerror(GetLastError()));
653*c2e0c6b5SAndroid Build Coastguard Worker physmem->VxDCall2 = NULL;
654*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
655*c2e0c6b5SAndroid Build Coastguard Worker return 0;
656*c2e0c6b5SAndroid Build Coastguard Worker }
657*c2e0c6b5SAndroid Build Coastguard Worker
658*c2e0c6b5SAndroid Build Coastguard Worker a->debug("success.");
659*c2e0c6b5SAndroid Build Coastguard Worker return 1;
660*c2e0c6b5SAndroid Build Coastguard Worker }
661*c2e0c6b5SAndroid Build Coastguard Worker
662*c2e0c6b5SAndroid Build Coastguard Worker #endif
663*c2e0c6b5SAndroid Build Coastguard Worker
664*c2e0c6b5SAndroid Build Coastguard Worker static int
init_physmem_ntdll(struct physmem * physmem,struct pci_access * a,const char * filename,int w)665*c2e0c6b5SAndroid Build Coastguard Worker init_physmem_ntdll(struct physmem *physmem, struct pci_access *a, const char *filename, int w)
666*c2e0c6b5SAndroid Build Coastguard Worker {
667*c2e0c6b5SAndroid Build Coastguard Worker wchar_t *wide_filename;
668*c2e0c6b5SAndroid Build Coastguard Worker UNICODE_STRING unicode_filename;
669*c2e0c6b5SAndroid Build Coastguard Worker OBJECT_ATTRIBUTES attributes;
670*c2e0c6b5SAndroid Build Coastguard Worker UINT prev_error_mode;
671*c2e0c6b5SAndroid Build Coastguard Worker NTSTATUS status;
672*c2e0c6b5SAndroid Build Coastguard Worker int len;
673*c2e0c6b5SAndroid Build Coastguard Worker
674*c2e0c6b5SAndroid Build Coastguard Worker a->debug("resolving section functions from ntdll.dll...");
675*c2e0c6b5SAndroid Build Coastguard Worker prev_error_mode = win32_change_error_mode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
676*c2e0c6b5SAndroid Build Coastguard Worker physmem->ntdll = LoadLibrary(TEXT("ntdll.dll"));
677*c2e0c6b5SAndroid Build Coastguard Worker win32_change_error_mode(prev_error_mode);
678*c2e0c6b5SAndroid Build Coastguard Worker if (!physmem->ntdll)
679*c2e0c6b5SAndroid Build Coastguard Worker {
680*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: cannot open ntdll.dll library: %s.", win32_strerror(GetLastError()));
681*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
682*c2e0c6b5SAndroid Build Coastguard Worker return 0;
683*c2e0c6b5SAndroid Build Coastguard Worker }
684*c2e0c6b5SAndroid Build Coastguard Worker
685*c2e0c6b5SAndroid Build Coastguard Worker physmem->RtlNtStatusToDosError = (LPVOID)GetProcAddress(physmem->ntdll, "RtlNtStatusToDosError");
686*c2e0c6b5SAndroid Build Coastguard Worker
687*c2e0c6b5SAndroid Build Coastguard Worker physmem->NtOpenSection = (LPVOID)GetProcAddress(physmem->ntdll, "NtOpenSection");
688*c2e0c6b5SAndroid Build Coastguard Worker if (!physmem->NtOpenSection)
689*c2e0c6b5SAndroid Build Coastguard Worker {
690*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: function NtOpenSection() not found.");
691*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(physmem->ntdll);
692*c2e0c6b5SAndroid Build Coastguard Worker physmem->ntdll = NULL;
693*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
694*c2e0c6b5SAndroid Build Coastguard Worker return 0;
695*c2e0c6b5SAndroid Build Coastguard Worker }
696*c2e0c6b5SAndroid Build Coastguard Worker
697*c2e0c6b5SAndroid Build Coastguard Worker physmem->NtMapViewOfSection = (LPVOID)GetProcAddress(physmem->ntdll, "NtMapViewOfSection");
698*c2e0c6b5SAndroid Build Coastguard Worker if (!physmem->NtMapViewOfSection)
699*c2e0c6b5SAndroid Build Coastguard Worker {
700*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: function NtMapViewOfSection() not found.");
701*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(physmem->ntdll);
702*c2e0c6b5SAndroid Build Coastguard Worker physmem->ntdll = NULL;
703*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
704*c2e0c6b5SAndroid Build Coastguard Worker return 0;
705*c2e0c6b5SAndroid Build Coastguard Worker }
706*c2e0c6b5SAndroid Build Coastguard Worker
707*c2e0c6b5SAndroid Build Coastguard Worker physmem->NtUnmapViewOfSection = (LPVOID)GetProcAddress(physmem->ntdll, "NtUnmapViewOfSection");
708*c2e0c6b5SAndroid Build Coastguard Worker if (!physmem->NtUnmapViewOfSection)
709*c2e0c6b5SAndroid Build Coastguard Worker {
710*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: function NtUnmapViewOfSection() not found.");
711*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(physmem->ntdll);
712*c2e0c6b5SAndroid Build Coastguard Worker physmem->ntdll = NULL;
713*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
714*c2e0c6b5SAndroid Build Coastguard Worker return 0;
715*c2e0c6b5SAndroid Build Coastguard Worker }
716*c2e0c6b5SAndroid Build Coastguard Worker
717*c2e0c6b5SAndroid Build Coastguard Worker a->debug("success.");
718*c2e0c6b5SAndroid Build Coastguard Worker
719*c2e0c6b5SAndroid Build Coastguard Worker /*
720*c2e0c6b5SAndroid Build Coastguard Worker * Note: It is not possible to use WinAPI function OpenFileMappingA() because
721*c2e0c6b5SAndroid Build Coastguard Worker * it takes path relative to the NT base path \\Sessions\\X\\BaseNamedObjects\\
722*c2e0c6b5SAndroid Build Coastguard Worker * and so it does not support to open sections outside that NT directory.
723*c2e0c6b5SAndroid Build Coastguard Worker * NtOpenSection() does not have this restriction and supports specifying any
724*c2e0c6b5SAndroid Build Coastguard Worker * path, including path in absolute format. Unfortunately NtOpenSection()
725*c2e0c6b5SAndroid Build Coastguard Worker * takes path in UNICODE_STRING structure, unlike OpenFileMappingA() which
726*c2e0c6b5SAndroid Build Coastguard Worker * takes path in 8-bit char*. So first it is needed to do conversion from
727*c2e0c6b5SAndroid Build Coastguard Worker * char* string to wchar_t* string via function MultiByteToWideChar() and
728*c2e0c6b5SAndroid Build Coastguard Worker * then fill UNICODE_STRING structure from that wchar_t* string via function
729*c2e0c6b5SAndroid Build Coastguard Worker * RtlInitUnicodeString().
730*c2e0c6b5SAndroid Build Coastguard Worker */
731*c2e0c6b5SAndroid Build Coastguard Worker
732*c2e0c6b5SAndroid Build Coastguard Worker len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
733*c2e0c6b5SAndroid Build Coastguard Worker if (len <= 0)
734*c2e0c6b5SAndroid Build Coastguard Worker {
735*c2e0c6b5SAndroid Build Coastguard Worker a->debug("Option devmem.path '%s' is invalid multibyte string.", filename);
736*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(physmem->ntdll);
737*c2e0c6b5SAndroid Build Coastguard Worker physmem->ntdll = NULL;
738*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
739*c2e0c6b5SAndroid Build Coastguard Worker return 0;
740*c2e0c6b5SAndroid Build Coastguard Worker }
741*c2e0c6b5SAndroid Build Coastguard Worker
742*c2e0c6b5SAndroid Build Coastguard Worker wide_filename = pci_malloc(a, len * sizeof(wchar_t));
743*c2e0c6b5SAndroid Build Coastguard Worker len = MultiByteToWideChar(CP_ACP, 0, filename, -1, wide_filename, len);
744*c2e0c6b5SAndroid Build Coastguard Worker if (len <= 0)
745*c2e0c6b5SAndroid Build Coastguard Worker {
746*c2e0c6b5SAndroid Build Coastguard Worker a->debug("Option devmem.path '%s' is invalid multibyte string.", filename);
747*c2e0c6b5SAndroid Build Coastguard Worker pci_mfree(wide_filename);
748*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(physmem->ntdll);
749*c2e0c6b5SAndroid Build Coastguard Worker physmem->ntdll = NULL;
750*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
751*c2e0c6b5SAndroid Build Coastguard Worker return 0;
752*c2e0c6b5SAndroid Build Coastguard Worker }
753*c2e0c6b5SAndroid Build Coastguard Worker
754*c2e0c6b5SAndroid Build Coastguard Worker RtlInitUnicodeString(&unicode_filename, wide_filename);
755*c2e0c6b5SAndroid Build Coastguard Worker InitializeObjectAttributes(&attributes, &unicode_filename, OBJ_CASE_INSENSITIVE, NULL, NULL);
756*c2e0c6b5SAndroid Build Coastguard Worker
757*c2e0c6b5SAndroid Build Coastguard Worker a->debug("trying to open NT Section %s in %s mode...", filename, w ? "read/write" : "read-only");
758*c2e0c6b5SAndroid Build Coastguard Worker physmem->section_handle = INVALID_HANDLE_VALUE;
759*c2e0c6b5SAndroid Build Coastguard Worker status = physmem->NtOpenSection(&physmem->section_handle, SECTION_MAP_READ | (w ? SECTION_MAP_WRITE : 0), &attributes);
760*c2e0c6b5SAndroid Build Coastguard Worker
761*c2e0c6b5SAndroid Build Coastguard Worker pci_mfree(wide_filename);
762*c2e0c6b5SAndroid Build Coastguard Worker
763*c2e0c6b5SAndroid Build Coastguard Worker if (status < 0 || physmem->section_handle == INVALID_HANDLE_VALUE)
764*c2e0c6b5SAndroid Build Coastguard Worker {
765*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(physmem->ntdll);
766*c2e0c6b5SAndroid Build Coastguard Worker physmem->ntdll = NULL;
767*c2e0c6b5SAndroid Build Coastguard Worker physmem->section_handle = INVALID_HANDLE_VALUE;
768*c2e0c6b5SAndroid Build Coastguard Worker if (status == 0)
769*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed.");
770*c2e0c6b5SAndroid Build Coastguard Worker else if (physmem->RtlNtStatusToDosError)
771*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: %s (0x%lx).", win32_strerror(physmem->RtlNtStatusToDosError(status)), status);
772*c2e0c6b5SAndroid Build Coastguard Worker else
773*c2e0c6b5SAndroid Build Coastguard Worker a->debug("failed: 0x%lx.", status);
774*c2e0c6b5SAndroid Build Coastguard Worker switch (status)
775*c2e0c6b5SAndroid Build Coastguard Worker {
776*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_PARAMETER: /* SectionHandle or ObjectAttributes parameter is invalid */
777*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
778*c2e0c6b5SAndroid Build Coastguard Worker break;
779*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_OBJECT_NAME_NOT_FOUND: /* Section name in ObjectAttributes.ObjectName does not exist */
780*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
781*c2e0c6b5SAndroid Build Coastguard Worker break;
782*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_ACCESS_DENIED: /* No permission to access Section name in ObjectAttributes.ObjectName */
783*c2e0c6b5SAndroid Build Coastguard Worker errno = EACCES;
784*c2e0c6b5SAndroid Build Coastguard Worker break;
785*c2e0c6b5SAndroid Build Coastguard Worker default: /* Other unspecified error */
786*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
787*c2e0c6b5SAndroid Build Coastguard Worker break;
788*c2e0c6b5SAndroid Build Coastguard Worker }
789*c2e0c6b5SAndroid Build Coastguard Worker return 0;
790*c2e0c6b5SAndroid Build Coastguard Worker }
791*c2e0c6b5SAndroid Build Coastguard Worker
792*c2e0c6b5SAndroid Build Coastguard Worker a->debug("success.");
793*c2e0c6b5SAndroid Build Coastguard Worker return 1;
794*c2e0c6b5SAndroid Build Coastguard Worker }
795*c2e0c6b5SAndroid Build Coastguard Worker
796*c2e0c6b5SAndroid Build Coastguard Worker void
physmem_init_config(struct pci_access * a)797*c2e0c6b5SAndroid Build Coastguard Worker physmem_init_config(struct pci_access *a)
798*c2e0c6b5SAndroid Build Coastguard Worker {
799*c2e0c6b5SAndroid Build Coastguard Worker pci_define_param(a, "devmem.path", PCI_PATH_DEVMEM_DEVICE, "NT path to the PhysicalMemory NT Section"
800*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__i386__) || defined(_M_IX86)
801*c2e0c6b5SAndroid Build Coastguard Worker " or \"vxdcall\" or \"w32skrnl\""
802*c2e0c6b5SAndroid Build Coastguard Worker #endif
803*c2e0c6b5SAndroid Build Coastguard Worker );
804*c2e0c6b5SAndroid Build Coastguard Worker }
805*c2e0c6b5SAndroid Build Coastguard Worker
806*c2e0c6b5SAndroid Build Coastguard Worker int
physmem_access(struct pci_access * a,int w)807*c2e0c6b5SAndroid Build Coastguard Worker physmem_access(struct pci_access *a, int w)
808*c2e0c6b5SAndroid Build Coastguard Worker {
809*c2e0c6b5SAndroid Build Coastguard Worker struct physmem *physmem = physmem_open(a, w);
810*c2e0c6b5SAndroid Build Coastguard Worker if (!physmem)
811*c2e0c6b5SAndroid Build Coastguard Worker return -1;
812*c2e0c6b5SAndroid Build Coastguard Worker physmem_close(physmem);
813*c2e0c6b5SAndroid Build Coastguard Worker return 0;
814*c2e0c6b5SAndroid Build Coastguard Worker }
815*c2e0c6b5SAndroid Build Coastguard Worker
816*c2e0c6b5SAndroid Build Coastguard Worker struct physmem *
physmem_open(struct pci_access * a,int w)817*c2e0c6b5SAndroid Build Coastguard Worker physmem_open(struct pci_access *a, int w)
818*c2e0c6b5SAndroid Build Coastguard Worker {
819*c2e0c6b5SAndroid Build Coastguard Worker const char *devmem = pci_get_param(a, "devmem.path");
820*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__i386__) || defined(_M_IX86)
821*c2e0c6b5SAndroid Build Coastguard Worker int force_vxdcall = strcmp(devmem, "vxdcall") == 0;
822*c2e0c6b5SAndroid Build Coastguard Worker int force_w32skrnl = strcmp(devmem, "w32skrnl") == 0;
823*c2e0c6b5SAndroid Build Coastguard Worker #endif
824*c2e0c6b5SAndroid Build Coastguard Worker struct physmem *physmem = pci_malloc(a, sizeof(*physmem));
825*c2e0c6b5SAndroid Build Coastguard Worker
826*c2e0c6b5SAndroid Build Coastguard Worker memset(physmem, 0, sizeof(*physmem));
827*c2e0c6b5SAndroid Build Coastguard Worker physmem->section_handle = INVALID_HANDLE_VALUE;
828*c2e0c6b5SAndroid Build Coastguard Worker
829*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOENT;
830*c2e0c6b5SAndroid Build Coastguard Worker
831*c2e0c6b5SAndroid Build Coastguard Worker if (
832*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__i386__) || defined(_M_IX86)
833*c2e0c6b5SAndroid Build Coastguard Worker !force_vxdcall && !force_w32skrnl &&
834*c2e0c6b5SAndroid Build Coastguard Worker #endif
835*c2e0c6b5SAndroid Build Coastguard Worker init_physmem_ntdll(physmem, a, devmem, w))
836*c2e0c6b5SAndroid Build Coastguard Worker return physmem;
837*c2e0c6b5SAndroid Build Coastguard Worker
838*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__i386__) || defined(_M_IX86)
839*c2e0c6b5SAndroid Build Coastguard Worker if (!force_w32skrnl && init_physmem_vxdcall(physmem, a))
840*c2e0c6b5SAndroid Build Coastguard Worker return physmem;
841*c2e0c6b5SAndroid Build Coastguard Worker
842*c2e0c6b5SAndroid Build Coastguard Worker if (!force_vxdcall && init_physmem_w32skrnl(physmem, a))
843*c2e0c6b5SAndroid Build Coastguard Worker return physmem;
844*c2e0c6b5SAndroid Build Coastguard Worker #endif
845*c2e0c6b5SAndroid Build Coastguard Worker
846*c2e0c6b5SAndroid Build Coastguard Worker a->debug("no windows method for physical memory access.");
847*c2e0c6b5SAndroid Build Coastguard Worker pci_mfree(physmem);
848*c2e0c6b5SAndroid Build Coastguard Worker return NULL;
849*c2e0c6b5SAndroid Build Coastguard Worker }
850*c2e0c6b5SAndroid Build Coastguard Worker
851*c2e0c6b5SAndroid Build Coastguard Worker void
physmem_close(struct physmem * physmem)852*c2e0c6b5SAndroid Build Coastguard Worker physmem_close(struct physmem *physmem)
853*c2e0c6b5SAndroid Build Coastguard Worker {
854*c2e0c6b5SAndroid Build Coastguard Worker if (physmem->section_handle != INVALID_HANDLE_VALUE)
855*c2e0c6b5SAndroid Build Coastguard Worker CloseHandle(physmem->section_handle);
856*c2e0c6b5SAndroid Build Coastguard Worker if (physmem->ntdll)
857*c2e0c6b5SAndroid Build Coastguard Worker FreeLibrary(physmem->ntdll);
858*c2e0c6b5SAndroid Build Coastguard Worker pci_mfree(physmem);
859*c2e0c6b5SAndroid Build Coastguard Worker }
860*c2e0c6b5SAndroid Build Coastguard Worker
861*c2e0c6b5SAndroid Build Coastguard Worker long
physmem_get_pagesize(struct physmem * physmem UNUSED)862*c2e0c6b5SAndroid Build Coastguard Worker physmem_get_pagesize(struct physmem *physmem UNUSED)
863*c2e0c6b5SAndroid Build Coastguard Worker {
864*c2e0c6b5SAndroid Build Coastguard Worker SYSTEM_INFO system_info;
865*c2e0c6b5SAndroid Build Coastguard Worker system_info.dwPageSize = 0;
866*c2e0c6b5SAndroid Build Coastguard Worker GetSystemInfo(&system_info);
867*c2e0c6b5SAndroid Build Coastguard Worker return system_info.dwPageSize;
868*c2e0c6b5SAndroid Build Coastguard Worker }
869*c2e0c6b5SAndroid Build Coastguard Worker
870*c2e0c6b5SAndroid Build Coastguard Worker void *
physmem_map(struct physmem * physmem,u64 addr,size_t length,int w)871*c2e0c6b5SAndroid Build Coastguard Worker physmem_map(struct physmem *physmem, u64 addr, size_t length, int w)
872*c2e0c6b5SAndroid Build Coastguard Worker {
873*c2e0c6b5SAndroid Build Coastguard Worker LARGE_INTEGER section_offset;
874*c2e0c6b5SAndroid Build Coastguard Worker NTSTATUS status;
875*c2e0c6b5SAndroid Build Coastguard Worker SIZE_T view_size;
876*c2e0c6b5SAndroid Build Coastguard Worker VOID *ptr;
877*c2e0c6b5SAndroid Build Coastguard Worker
878*c2e0c6b5SAndroid Build Coastguard Worker if (physmem->section_handle != INVALID_HANDLE_VALUE)
879*c2e0c6b5SAndroid Build Coastguard Worker {
880*c2e0c6b5SAndroid Build Coastguard Worker /*
881*c2e0c6b5SAndroid Build Coastguard Worker * Note: Do not use WinAPI function MapViewOfFile() because it makes memory
882*c2e0c6b5SAndroid Build Coastguard Worker * mapping available also for all child processes that are spawned in the
883*c2e0c6b5SAndroid Build Coastguard Worker * future. NtMapViewOfSection() allows to specify ViewUnmap parameter which
884*c2e0c6b5SAndroid Build Coastguard Worker * creates mapping just for this process and not for future child processes.
885*c2e0c6b5SAndroid Build Coastguard Worker * For security reasons we do not want this physical address mapping to be
886*c2e0c6b5SAndroid Build Coastguard Worker * present also in future spawned processes.
887*c2e0c6b5SAndroid Build Coastguard Worker */
888*c2e0c6b5SAndroid Build Coastguard Worker ptr = NULL;
889*c2e0c6b5SAndroid Build Coastguard Worker section_offset.QuadPart = addr;
890*c2e0c6b5SAndroid Build Coastguard Worker view_size = length;
891*c2e0c6b5SAndroid Build Coastguard Worker status = physmem->NtMapViewOfSection(physmem->section_handle, GetCurrentProcess(), &ptr, 0, 0, §ion_offset, &view_size, ViewUnmap, 0, w ? PAGE_READWRITE : PAGE_READONLY);
892*c2e0c6b5SAndroid Build Coastguard Worker if (status < 0)
893*c2e0c6b5SAndroid Build Coastguard Worker {
894*c2e0c6b5SAndroid Build Coastguard Worker switch (status)
895*c2e0c6b5SAndroid Build Coastguard Worker {
896*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_HANDLE: /* Invalid SectionHandle (physmem->section_handle) */
897*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_PARAMETER_3: /* Invalid BaseAddress parameter (&ptr) */
898*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_CONFLICTING_ADDRESSES: /* Invalid value of BaseAddress pointer (ptr) */
899*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_MAPPED_ALIGNMENT: /* Invalid value of BaseAddress pointer (ptr) or SectionOffset (section_offset) */
900*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_PARAMETER_4: /* Invalid ZeroBits parameter (0) */
901*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_PARAMETER_5: /* Invalid CommitSize parameter (0) */
902*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_PARAMETER_8: /* Invalid InheritDisposition parameter (ViewUnmap) */
903*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_PARAMETER_9: /* Invalid AllocationType parameter (0) */
904*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_SECTION_PROTECTION: /* Invalid Protect parameter (based on w) */
905*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_PAGE_PROTECTION: /* Invalid Protect parameter (based on w) */
906*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
907*c2e0c6b5SAndroid Build Coastguard Worker break;
908*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INVALID_VIEW_SIZE: /* Invalid SectionOffset / ViewSize range (section_offset, view_size) */
909*c2e0c6b5SAndroid Build Coastguard Worker errno = ENXIO;
910*c2e0c6b5SAndroid Build Coastguard Worker break;
911*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_INSUFFICIENT_RESOURCES: /* Quota limit exceeded */
912*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_NO_MEMORY: /* Memory limit exceeded */
913*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOMEM;
914*c2e0c6b5SAndroid Build Coastguard Worker break;
915*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_ACCESS_DENIED: /* No permission to create mapping */
916*c2e0c6b5SAndroid Build Coastguard Worker errno = EPERM;
917*c2e0c6b5SAndroid Build Coastguard Worker break;
918*c2e0c6b5SAndroid Build Coastguard Worker default: /* Other unspecified error */
919*c2e0c6b5SAndroid Build Coastguard Worker errno = EACCES;
920*c2e0c6b5SAndroid Build Coastguard Worker break;
921*c2e0c6b5SAndroid Build Coastguard Worker }
922*c2e0c6b5SAndroid Build Coastguard Worker return (void *)-1;
923*c2e0c6b5SAndroid Build Coastguard Worker }
924*c2e0c6b5SAndroid Build Coastguard Worker
925*c2e0c6b5SAndroid Build Coastguard Worker return ptr;
926*c2e0c6b5SAndroid Build Coastguard Worker }
927*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__i386__) || defined(_M_IX86)
928*c2e0c6b5SAndroid Build Coastguard Worker else if (physmem->VxDCall2 || physmem->w32skrnl_dpmi_lcall_ptr)
929*c2e0c6b5SAndroid Build Coastguard Worker {
930*c2e0c6b5SAndroid Build Coastguard Worker BOOL success;
931*c2e0c6b5SAndroid Build Coastguard Worker DWORD virt;
932*c2e0c6b5SAndroid Build Coastguard Worker
933*c2e0c6b5SAndroid Build Coastguard Worker /*
934*c2e0c6b5SAndroid Build Coastguard Worker * These two methods support mapping only the first 4 GB of physical memory
935*c2e0c6b5SAndroid Build Coastguard Worker * and mapped memory is always read/write. There is no way to create
936*c2e0c6b5SAndroid Build Coastguard Worker * read-only mapping, so argument "w" is ignored.
937*c2e0c6b5SAndroid Build Coastguard Worker */
938*c2e0c6b5SAndroid Build Coastguard Worker if (addr >= 0xffffffffUL || addr + length > 0xffffffffUL)
939*c2e0c6b5SAndroid Build Coastguard Worker {
940*c2e0c6b5SAndroid Build Coastguard Worker errno = EOVERFLOW;
941*c2e0c6b5SAndroid Build Coastguard Worker return (void *)-1;
942*c2e0c6b5SAndroid Build Coastguard Worker }
943*c2e0c6b5SAndroid Build Coastguard Worker
944*c2e0c6b5SAndroid Build Coastguard Worker if (physmem->VxDCall2)
945*c2e0c6b5SAndroid Build Coastguard Worker success = vdxcall_physical_address_mapping(physmem, (DWORD)addr, length, &virt);
946*c2e0c6b5SAndroid Build Coastguard Worker else
947*c2e0c6b5SAndroid Build Coastguard Worker success = w32skrnl_physical_address_mapping(physmem, (DWORD)addr, length, &virt);
948*c2e0c6b5SAndroid Build Coastguard Worker
949*c2e0c6b5SAndroid Build Coastguard Worker /* Both above functions set errno on failure. */
950*c2e0c6b5SAndroid Build Coastguard Worker if (!success)
951*c2e0c6b5SAndroid Build Coastguard Worker return (void *)-1;
952*c2e0c6b5SAndroid Build Coastguard Worker
953*c2e0c6b5SAndroid Build Coastguard Worker /* Virtual address from our view is calculated from the base offset. */
954*c2e0c6b5SAndroid Build Coastguard Worker ptr = (VOID *)(virt - physmem->base_addr_offset);
955*c2e0c6b5SAndroid Build Coastguard Worker return ptr;
956*c2e0c6b5SAndroid Build Coastguard Worker }
957*c2e0c6b5SAndroid Build Coastguard Worker #endif
958*c2e0c6b5SAndroid Build Coastguard Worker
959*c2e0c6b5SAndroid Build Coastguard Worker
960*c2e0c6b5SAndroid Build Coastguard Worker /* invalid physmem parameter */
961*c2e0c6b5SAndroid Build Coastguard Worker errno = EBADF;
962*c2e0c6b5SAndroid Build Coastguard Worker return (void *)-1;
963*c2e0c6b5SAndroid Build Coastguard Worker }
964*c2e0c6b5SAndroid Build Coastguard Worker
965*c2e0c6b5SAndroid Build Coastguard Worker int
physmem_unmap(struct physmem * physmem,void * ptr,size_t length)966*c2e0c6b5SAndroid Build Coastguard Worker physmem_unmap(struct physmem *physmem, void *ptr, size_t length)
967*c2e0c6b5SAndroid Build Coastguard Worker {
968*c2e0c6b5SAndroid Build Coastguard Worker long pagesize = physmem_get_pagesize(physmem);
969*c2e0c6b5SAndroid Build Coastguard Worker MEMORY_BASIC_INFORMATION info;
970*c2e0c6b5SAndroid Build Coastguard Worker NTSTATUS status;
971*c2e0c6b5SAndroid Build Coastguard Worker
972*c2e0c6b5SAndroid Build Coastguard Worker if (physmem->section_handle != INVALID_HANDLE_VALUE)
973*c2e0c6b5SAndroid Build Coastguard Worker {
974*c2e0c6b5SAndroid Build Coastguard Worker /*
975*c2e0c6b5SAndroid Build Coastguard Worker * NtUnmapViewOfSection() unmaps entire memory range previously mapped by
976*c2e0c6b5SAndroid Build Coastguard Worker * NtMapViewOfSection(). The specified ptr (BaseAddress) does not have to
977*c2e0c6b5SAndroid Build Coastguard Worker * point to the beginning of the mapped memory range.
978*c2e0c6b5SAndroid Build Coastguard Worker *
979*c2e0c6b5SAndroid Build Coastguard Worker * So verify that the ptr argument is the beginning of the mapped range
980*c2e0c6b5SAndroid Build Coastguard Worker * and length argument is the length of mapped range.
981*c2e0c6b5SAndroid Build Coastguard Worker */
982*c2e0c6b5SAndroid Build Coastguard Worker
983*c2e0c6b5SAndroid Build Coastguard Worker if (VirtualQuery(ptr, &info, sizeof(info)) != sizeof(info))
984*c2e0c6b5SAndroid Build Coastguard Worker {
985*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
986*c2e0c6b5SAndroid Build Coastguard Worker return -1;
987*c2e0c6b5SAndroid Build Coastguard Worker }
988*c2e0c6b5SAndroid Build Coastguard Worker
989*c2e0c6b5SAndroid Build Coastguard Worker /* RegionSize is already page aligned, but length does not have to be. */
990*c2e0c6b5SAndroid Build Coastguard Worker if (info.AllocationBase != ptr || info.RegionSize != ((length + pagesize-1) & ~(pagesize-1)))
991*c2e0c6b5SAndroid Build Coastguard Worker {
992*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
993*c2e0c6b5SAndroid Build Coastguard Worker return -1;
994*c2e0c6b5SAndroid Build Coastguard Worker }
995*c2e0c6b5SAndroid Build Coastguard Worker
996*c2e0c6b5SAndroid Build Coastguard Worker status = physmem->NtUnmapViewOfSection(GetCurrentProcess(), ptr);
997*c2e0c6b5SAndroid Build Coastguard Worker if (status < 0)
998*c2e0c6b5SAndroid Build Coastguard Worker {
999*c2e0c6b5SAndroid Build Coastguard Worker switch (status)
1000*c2e0c6b5SAndroid Build Coastguard Worker {
1001*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_NOT_MAPPED_VIEW: /* BaseAddress parameter (ptr) not mapped */
1002*c2e0c6b5SAndroid Build Coastguard Worker errno = EINVAL;
1003*c2e0c6b5SAndroid Build Coastguard Worker break;
1004*c2e0c6b5SAndroid Build Coastguard Worker case STATUS_ACCESS_DENIED: /* No permission to unmap BaseAddress (ptr) */
1005*c2e0c6b5SAndroid Build Coastguard Worker errno = EPERM;
1006*c2e0c6b5SAndroid Build Coastguard Worker break;
1007*c2e0c6b5SAndroid Build Coastguard Worker default: /* Other unspecified error */
1008*c2e0c6b5SAndroid Build Coastguard Worker errno = EACCES;
1009*c2e0c6b5SAndroid Build Coastguard Worker break;
1010*c2e0c6b5SAndroid Build Coastguard Worker }
1011*c2e0c6b5SAndroid Build Coastguard Worker return -1;
1012*c2e0c6b5SAndroid Build Coastguard Worker }
1013*c2e0c6b5SAndroid Build Coastguard Worker
1014*c2e0c6b5SAndroid Build Coastguard Worker return 0;
1015*c2e0c6b5SAndroid Build Coastguard Worker }
1016*c2e0c6b5SAndroid Build Coastguard Worker #if defined(__i386__) || defined(_M_IX86)
1017*c2e0c6b5SAndroid Build Coastguard Worker else if (physmem->VxDCall2 || physmem->w32skrnl_dpmi_lcall_ptr)
1018*c2e0c6b5SAndroid Build Coastguard Worker {
1019*c2e0c6b5SAndroid Build Coastguard Worker /* There is no way to unmap physical memory mapped by these methods. */
1020*c2e0c6b5SAndroid Build Coastguard Worker errno = ENOSYS;
1021*c2e0c6b5SAndroid Build Coastguard Worker return -1;
1022*c2e0c6b5SAndroid Build Coastguard Worker }
1023*c2e0c6b5SAndroid Build Coastguard Worker #endif
1024*c2e0c6b5SAndroid Build Coastguard Worker
1025*c2e0c6b5SAndroid Build Coastguard Worker /* invalid physmem parameter */
1026*c2e0c6b5SAndroid Build Coastguard Worker errno = EBADF;
1027*c2e0c6b5SAndroid Build Coastguard Worker return -1;
1028*c2e0c6b5SAndroid Build Coastguard Worker }
1029