VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPLib.cpp@ 18499

Last change on this file since 18499 was 18450, checked in by vboxsync, 15 years ago

supR3LoggerSettings: warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 71.4 KB
Line 
1/* $Id: SUPLib.cpp 18450 2009-03-28 03:38:02Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Common code.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/** @page pg_sup SUP - The Support Library
32 *
33 * The support library is responsible for providing facilities to load
34 * VMM Host Ring-0 code, to call Host VMM Ring-0 code from Ring-3 Host
35 * code, to pin down physical memory, and more.
36 *
37 * The VMM Host Ring-0 code can be combined in the support driver if
38 * permitted by kernel module license policies. If it is not combined
39 * it will be externalized in a .r0 module that will be loaded using
40 * the IPRT loader.
41 *
42 * The Ring-0 calling is done thru a generic SUP interface which will
43 * tranfer an argument set and call a predefined entry point in the Host
44 * VMM Ring-0 code.
45 *
46 * See @ref grp_sup "SUP - Support APIs" for API details.
47 */
48
49/*******************************************************************************
50* Header Files *
51*******************************************************************************/
52#define LOG_GROUP LOG_GROUP_SUP
53#include <VBox/sup.h>
54#include <VBox/err.h>
55#include <VBox/param.h>
56#include <VBox/vmm.h>
57#include <VBox/log.h>
58#include <VBox/x86.h>
59
60#include <iprt/assert.h>
61#include <iprt/alloc.h>
62#include <iprt/alloca.h>
63#include <iprt/ldr.h>
64#include <iprt/asm.h>
65#include <iprt/mp.h>
66#include <iprt/cpuset.h>
67#include <iprt/thread.h>
68#include <iprt/process.h>
69#include <iprt/path.h>
70#include <iprt/string.h>
71#include <iprt/env.h>
72#include <iprt/rand.h>
73
74#include "SUPLibInternal.h"
75#include "SUPDrvIOC.h"
76
77
78/*******************************************************************************
79* Defined Constants And Macros *
80*******************************************************************************/
81/** R0 VMM module name. */
82#define VMMR0_NAME "VMMR0"
83
84
85/*******************************************************************************
86* Structures and Typedefs *
87*******************************************************************************/
88typedef DECLCALLBACK(int) FNCALLVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg);
89typedef FNCALLVMMR0 *PFNCALLVMMR0;
90
91
92/*******************************************************************************
93* Global Variables *
94*******************************************************************************/
95/** Init counter. */
96static uint32_t g_cInits = 0;
97/** Whether we've been preinitied. */
98static bool g_fPreInited = false;
99/** The SUPLib instance data.
100 * Well, at least parts of it, specificly the parts that are being handed over
101 * via the pre-init mechanism from the hardened executable stub. */
102static SUPLIBDATA g_supLibData =
103{
104 NIL_RTFILE
105#if defined(RT_OS_DARWIN)
106 , NULL
107#elif defined(RT_OS_LINUX)
108 , false
109#endif
110};
111
112/** Pointer to the Global Information Page.
113 *
114 * This pointer is valid as long as SUPLib has a open session. Anyone using
115 * the page must treat this pointer as higly volatile and not trust it beyond
116 * one transaction.
117 *
118 * @todo This will probably deserve it's own session or some other good solution...
119 */
120DECLEXPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;
121/** Address of the ring-0 mapping of the GIP. */
122static PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPageR0;
123/** The physical address of the GIP. */
124static RTHCPHYS g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS;
125
126/** The negotiated cookie. */
127uint32_t g_u32Cookie = 0;
128/** The negotiated session cookie. */
129uint32_t g_u32SessionCookie;
130/** Session handle. */
131PSUPDRVSESSION g_pSession;
132/** R0 SUP Functions used for resolving referenced to the SUPR0 module. */
133static PSUPQUERYFUNCS g_pFunctions;
134
135/** VMMR0 Load Address. */
136static RTR0PTR g_pvVMMR0 = NIL_RTR0PTR;
137/** PAGE_ALLOC_EX sans kernel mapping support indicator. */
138static bool g_fSupportsPageAllocNoKernel = true;
139/** Fake mode indicator. (~0 at first, 0 or 1 after first test) */
140static uint32_t g_u32FakeMode = ~0;
141
142
143/*******************************************************************************
144* Internal Functions *
145*******************************************************************************/
146static int supInitFake(PSUPDRVSESSION *ppSession);
147static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase);
148static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
149
150
151SUPR3DECL(int) SUPInstall(void)
152{
153 return suplibOsInstall();
154}
155
156
157SUPR3DECL(int) SUPUninstall(void)
158{
159 return suplibOsUninstall();
160}
161
162
163DECLEXPORT(int) supR3PreInit(PSUPPREINITDATA pPreInitData, uint32_t fFlags)
164{
165 /*
166 * The caller is kind of trustworthy, just perform some basic checks.
167 *
168 * Note! Do not do any fancy stuff here because IPRT has NOT been
169 * initialized at this point.
170 */
171 if (!VALID_PTR(pPreInitData))
172 return VERR_INVALID_POINTER;
173 if (g_fPreInited || g_cInits > 0)
174 return VERR_WRONG_ORDER;
175
176 if ( pPreInitData->u32Magic != SUPPREINITDATA_MAGIC
177 || pPreInitData->u32EndMagic != SUPPREINITDATA_MAGIC)
178 return VERR_INVALID_MAGIC;
179 if ( !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
180 && pPreInitData->Data.hDevice == NIL_RTFILE)
181 return VERR_INVALID_HANDLE;
182 if ( (fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
183 && pPreInitData->Data.hDevice != NIL_RTFILE)
184 return VERR_INVALID_PARAMETER;
185
186 /*
187 * Hand out the data.
188 */
189 int rc = supR3HardenedRecvPreInitData(pPreInitData);
190 if (RT_FAILURE(rc))
191 return rc;
192
193 /** @todo This may need some small restructuring later, it doesn't quite work with a root service flag... */
194 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
195 {
196 g_supLibData = pPreInitData->Data;
197 g_fPreInited = true;
198 }
199
200 return VINF_SUCCESS;
201}
202
203
204SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession)
205{
206 /*
207 * Perform some sanity checks.
208 * (Got some trouble with compile time member alignment assertions.)
209 */
210 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz) & 0x7));
211 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs) & 0x1f));
212 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[1]) & 0x1f));
213 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64NanoTS) & 0x7));
214 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64TSC) & 0x7));
215 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64CpuHz) & 0x7));
216
217 /*
218 * Check if already initialized.
219 */
220 if (ppSession)
221 *ppSession = g_pSession;
222 if (g_cInits++ > 0)
223 return VINF_SUCCESS;
224
225 /*
226 * Check for fake mode.
227 *
228 * Fake mode is used when we're doing smoke testing and debugging.
229 * It's also useful on platforms where we haven't root access or which
230 * we haven't ported the support driver to.
231 */
232 if (g_u32FakeMode == ~0U)
233 {
234 const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
235 if (psz && !strcmp(psz, "fake"))
236 ASMAtomicCmpXchgU32(&g_u32FakeMode, 1, ~0U);
237 else
238 ASMAtomicCmpXchgU32(&g_u32FakeMode, 0, ~0U);
239 }
240 if (RT_UNLIKELY(g_u32FakeMode))
241 return supInitFake(ppSession);
242
243 /*
244 * Open the support driver.
245 */
246 int rc = suplibOsInit(&g_supLibData, g_fPreInited);
247 if (RT_SUCCESS(rc))
248 {
249 /*
250 * Negotiate the cookie.
251 */
252 SUPCOOKIE CookieReq;
253 memset(&CookieReq, 0xff, sizeof(CookieReq));
254 CookieReq.Hdr.u32Cookie = SUPCOOKIE_INITIAL_COOKIE;
255 CookieReq.Hdr.u32SessionCookie = RTRandU32();
256 CookieReq.Hdr.cbIn = SUP_IOCTL_COOKIE_SIZE_IN;
257 CookieReq.Hdr.cbOut = SUP_IOCTL_COOKIE_SIZE_OUT;
258 CookieReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
259 CookieReq.Hdr.rc = VERR_INTERNAL_ERROR;
260 strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);
261 CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
262 const uint32_t MinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x000a0000
263 ? 0x000a0009
264 : SUPDRV_IOC_VERSION & 0xffff0000;
265 CookieReq.u.In.u32MinVersion = MinVersion;
266 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_COOKIE, &CookieReq, SUP_IOCTL_COOKIE_SIZE);
267 if ( RT_SUCCESS(rc)
268 && RT_SUCCESS(CookieReq.Hdr.rc))
269 {
270 if ( (CookieReq.u.Out.u32SessionVersion & 0xffff0000) == (SUPDRV_IOC_VERSION & 0xffff0000)
271 && CookieReq.u.Out.u32SessionVersion >= MinVersion)
272 {
273 /*
274 * Query the functions.
275 */
276 PSUPQUERYFUNCS pFuncsReq = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));
277 if (pFuncsReq)
278 {
279 pFuncsReq->Hdr.u32Cookie = CookieReq.u.Out.u32Cookie;
280 pFuncsReq->Hdr.u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
281 pFuncsReq->Hdr.cbIn = SUP_IOCTL_QUERY_FUNCS_SIZE_IN;
282 pFuncsReq->Hdr.cbOut = SUP_IOCTL_QUERY_FUNCS_SIZE_OUT(CookieReq.u.Out.cFunctions);
283 pFuncsReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
284 pFuncsReq->Hdr.rc = VERR_INTERNAL_ERROR;
285 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_QUERY_FUNCS(CookieReq.u.Out.cFunctions), pFuncsReq, SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));
286 if (RT_SUCCESS(rc))
287 rc = pFuncsReq->Hdr.rc;
288 if (RT_SUCCESS(rc))
289 {
290 /*
291 * Map the GIP into userspace.
292 */
293 Assert(!g_pSUPGlobalInfoPage);
294 SUPGIPMAP GipMapReq;
295 GipMapReq.Hdr.u32Cookie = CookieReq.u.Out.u32Cookie;
296 GipMapReq.Hdr.u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
297 GipMapReq.Hdr.cbIn = SUP_IOCTL_GIP_MAP_SIZE_IN;
298 GipMapReq.Hdr.cbOut = SUP_IOCTL_GIP_MAP_SIZE_OUT;
299 GipMapReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
300 GipMapReq.Hdr.rc = VERR_INTERNAL_ERROR;
301 GipMapReq.u.Out.HCPhysGip = NIL_RTHCPHYS;
302 GipMapReq.u.Out.pGipR0 = NIL_RTR0PTR;
303 GipMapReq.u.Out.pGipR3 = NULL;
304 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GIP_MAP, &GipMapReq, SUP_IOCTL_GIP_MAP_SIZE);
305 if (RT_SUCCESS(rc))
306 rc = GipMapReq.Hdr.rc;
307 if (RT_SUCCESS(rc))
308 {
309 AssertRelease(GipMapReq.u.Out.pGipR3->u32Magic == SUPGLOBALINFOPAGE_MAGIC);
310 AssertRelease(GipMapReq.u.Out.pGipR3->u32Version >= SUPGLOBALINFOPAGE_VERSION);
311
312 /*
313 * Set the globals and return success.
314 */
315 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, GipMapReq.u.Out.HCPhysGip);
316 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, GipMapReq.u.Out.pGipR3, NULL);
317 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, (void *)GipMapReq.u.Out.pGipR0, NULL);
318
319 g_u32Cookie = CookieReq.u.Out.u32Cookie;
320 g_u32SessionCookie = CookieReq.u.Out.u32SessionCookie;
321 g_pSession = CookieReq.u.Out.pSession;
322 g_pFunctions = pFuncsReq;
323 if (ppSession)
324 *ppSession = CookieReq.u.Out.pSession;
325 return VINF_SUCCESS;
326 }
327 }
328
329 /* bailout */
330 RTMemFree(pFuncsReq);
331 }
332 else
333 rc = VERR_NO_MEMORY;
334 }
335 else
336 {
337 LogRel(("Support driver version mismatch: SessionVersion=%#x DriverVersion=%#x ClientVersion=%#x MinVersion=%#x\n",
338 CookieReq.u.Out.u32SessionVersion, CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, MinVersion));
339 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
340 }
341 }
342 else
343 {
344 if (RT_SUCCESS(rc))
345 {
346 rc = CookieReq.Hdr.rc;
347 LogRel(("Support driver version mismatch: DriverVersion=%#x ClientVersion=%#x rc=%Rrc\n",
348 CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, rc));
349 if (rc != VERR_VM_DRIVER_VERSION_MISMATCH)
350 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
351 }
352 else
353 {
354 /* for pre 0x00060000 drivers */
355 LogRel(("Support driver version mismatch: DriverVersion=too-old ClientVersion=%#x\n", SUPDRV_IOC_VERSION));
356 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
357 }
358 }
359
360 suplibOsTerm(&g_supLibData);
361 }
362 AssertMsgFailed(("SUPR3Init() failed rc=%Rrc\n", rc));
363 g_cInits--;
364
365 return rc;
366}
367
368/**
369 * Fake mode init.
370 */
371static int supInitFake(PSUPDRVSESSION *ppSession)
372{
373 Log(("SUP: Fake mode!\n"));
374 static const SUPFUNC s_aFakeFunctions[] =
375 {
376 /* name function */
377 { "SUPR0AbsIs64bit", 0 },
378 { "SUPR0Abs64bitKernelCS", 0 },
379 { "SUPR0Abs64bitKernelSS", 0 },
380 { "SUPR0Abs64bitKernelDS", 0 },
381 { "SUPR0AbsKernelCS", 8 },
382 { "SUPR0AbsKernelSS", 16 },
383 { "SUPR0AbsKernelDS", 16 },
384 { "SUPR0AbsKernelES", 16 },
385 { "SUPR0AbsKernelFS", 24 },
386 { "SUPR0AbsKernelGS", 32 },
387 { "SUPR0ComponentRegisterFactory", 0xefeefffd },
388 { "SUPR0ComponentDeregisterFactory", 0xefeefffe },
389 { "SUPR0ComponentQueryFactory", 0xefeeffff },
390 { "SUPR0ObjRegister", 0xefef0000 },
391 { "SUPR0ObjAddRef", 0xefef0001 },
392 { "SUPR0ObjAddRefEx", 0xefef0001 },
393 { "SUPR0ObjRelease", 0xefef0002 },
394 { "SUPR0ObjVerifyAccess", 0xefef0003 },
395 { "SUPR0LockMem", 0xefef0004 },
396 { "SUPR0UnlockMem", 0xefef0005 },
397 { "SUPR0ContAlloc", 0xefef0006 },
398 { "SUPR0ContFree", 0xefef0007 },
399 { "SUPR0MemAlloc", 0xefef0008 },
400 { "SUPR0MemGetPhys", 0xefef0009 },
401 { "SUPR0MemFree", 0xefef000a },
402 { "SUPR0Printf", 0xefef000b },
403 { "SUPR0GetPagingMode", 0xefef000c },
404 { "SUPR0EnableVTx", 0xefef000c },
405 { "RTMemAlloc", 0xefef000d },
406 { "RTMemAllocZ", 0xefef000e },
407 { "RTMemFree", 0xefef000f },
408 { "RTR0MemObjAddress", 0xefef0010 },
409 { "RTR0MemObjAddressR3", 0xefef0011 },
410 { "RTR0MemObjAllocPage", 0xefef0012 },
411 { "RTR0MemObjAllocPhysNC", 0xefef0013 },
412 { "RTR0MemObjAllocLow", 0xefef0014 },
413 { "RTR0MemObjEnterPhys", 0xefef0014 },
414 { "RTR0MemObjFree", 0xefef0015 },
415 { "RTR0MemObjGetPagePhysAddr", 0xefef0016 },
416 { "RTR0MemObjMapUser", 0xefef0017 },
417 { "RTR0MemObjMapKernel", 0xefef0017 },
418 { "RTR0MemObjMapKernelEx", 0xefef0017 },
419 { "RTProcSelf", 0xefef0038 },
420 { "RTR0ProcHandleSelf", 0xefef0039 },
421 { "RTSemEventCreate", 0xefef0018 },
422 { "RTSemEventSignal", 0xefef0019 },
423 { "RTSemEventWait", 0xefef001a },
424 { "RTSemEventWaitNoResume", 0xefef001b },
425 { "RTSemEventDestroy", 0xefef001c },
426 { "RTSemEventMultiCreate", 0xefef001d },
427 { "RTSemEventMultiSignal", 0xefef001e },
428 { "RTSemEventMultiReset", 0xefef001f },
429 { "RTSemEventMultiWait", 0xefef0020 },
430 { "RTSemEventMultiWaitNoResume", 0xefef0021 },
431 { "RTSemEventMultiDestroy", 0xefef0022 },
432 { "RTSemFastMutexCreate", 0xefef0023 },
433 { "RTSemFastMutexDestroy", 0xefef0024 },
434 { "RTSemFastMutexRequest", 0xefef0025 },
435 { "RTSemFastMutexRelease", 0xefef0026 },
436 { "RTSpinlockCreate", 0xefef0027 },
437 { "RTSpinlockDestroy", 0xefef0028 },
438 { "RTSpinlockAcquire", 0xefef0029 },
439 { "RTSpinlockRelease", 0xefef002a },
440 { "RTSpinlockAcquireNoInts", 0xefef002b },
441 { "RTSpinlockReleaseNoInts", 0xefef002c },
442 { "RTTimeNanoTS", 0xefef002d },
443 { "RTTimeMillieTS", 0xefef002e },
444 { "RTTimeSystemNanoTS", 0xefef002f },
445 { "RTTimeSystemMillieTS", 0xefef0030 },
446 { "RTThreadNativeSelf", 0xefef0031 },
447 { "RTThreadSleep", 0xefef0032 },
448 { "RTThreadYield", 0xefef0033 },
449 { "RTLogDefaultInstance", 0xefef0034 },
450 { "RTLogRelDefaultInstance", 0xefef0035 },
451 { "RTLogSetDefaultInstanceThread", 0xefef0036 },
452 { "RTLogLogger", 0xefef0037 },
453 { "RTLogLoggerEx", 0xefef0038 },
454 { "RTLogLoggerExV", 0xefef0039 },
455 { "AssertMsg1", 0xefef003a },
456 { "AssertMsg2", 0xefef003b },
457 { "RTAssertMsg1", 0xefef003c },
458 { "RTAssertMsg2", 0xefef003d },
459 { "RTAssertMsg2V", 0xefef003e },
460 };
461
462 /* fake r0 functions. */
463 g_pFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
464 if (g_pFunctions)
465 {
466 g_pFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);
467 memcpy(&g_pFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));
468 g_pSession = (PSUPDRVSESSION)(void *)g_pFunctions;
469 if (ppSession)
470 *ppSession = g_pSession;
471
472 /* fake the GIP. */
473 g_pSUPGlobalInfoPage = (PSUPGLOBALINFOPAGE)RTMemPageAllocZ(PAGE_SIZE);
474 if (g_pSUPGlobalInfoPage)
475 {
476 g_pSUPGlobalInfoPageR0 = g_pSUPGlobalInfoPage;
477 g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS & ~(RTHCPHYS)PAGE_OFFSET_MASK;
478 /* the page is supposed to be invalid, so don't set the magic. */
479 return VINF_SUCCESS;
480 }
481
482 RTMemFree(g_pFunctions);
483 g_pFunctions = NULL;
484 }
485 return VERR_NO_MEMORY;
486}
487
488
489SUPR3DECL(int) SUPTerm(bool fForced)
490{
491 /*
492 * Verify state.
493 */
494 AssertMsg(g_cInits > 0, ("SUPTerm() is called before SUPR3Init()!\n"));
495 if (g_cInits == 0)
496 return VERR_WRONG_ORDER;
497 if (g_cInits == 1 || fForced)
498 {
499 /*
500 * NULL the GIP pointer.
501 */
502 if (g_pSUPGlobalInfoPage)
503 {
504 ASMAtomicXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, NULL);
505 ASMAtomicXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, NULL);
506 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, NIL_RTHCPHYS);
507 /* just a little safe guard against threads using the page. */
508 RTThreadSleep(50);
509 }
510
511 /*
512 * Close the support driver.
513 */
514 int rc = suplibOsTerm(&g_supLibData);
515 if (rc)
516 return rc;
517
518 g_u32Cookie = 0;
519 g_u32SessionCookie = 0;
520 g_cInits = 0;
521 }
522 else
523 g_cInits--;
524
525 return 0;
526}
527
528
529SUPR3DECL(SUPPAGINGMODE) SUPGetPagingMode(void)
530{
531 /* fake */
532 if (RT_UNLIKELY(g_u32FakeMode))
533#ifdef RT_ARCH_AMD64
534 return SUPPAGINGMODE_AMD64_GLOBAL_NX;
535#else
536 return SUPPAGINGMODE_32_BIT_GLOBAL;
537#endif
538
539 /*
540 * Issue IOCtl to the SUPDRV kernel module.
541 */
542 SUPGETPAGINGMODE Req;
543 Req.Hdr.u32Cookie = g_u32Cookie;
544 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
545 Req.Hdr.cbIn = SUP_IOCTL_GET_PAGING_MODE_SIZE_IN;
546 Req.Hdr.cbOut = SUP_IOCTL_GET_PAGING_MODE_SIZE_OUT;
547 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
548 Req.Hdr.rc = VERR_INTERNAL_ERROR;
549 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GET_PAGING_MODE, &Req, SUP_IOCTL_GET_PAGING_MODE_SIZE);
550 if ( RT_FAILURE(rc)
551 || RT_FAILURE(Req.Hdr.rc))
552 {
553 LogRel(("SUPGetPagingMode: %Rrc %Rrc\n", rc, Req.Hdr.rc));
554 Req.u.Out.enmMode = SUPPAGINGMODE_INVALID;
555 }
556
557 return Req.u.Out.enmMode;
558}
559
560
561/**
562 * For later.
563 */
564static int supCallVMMR0ExFake(PVMR0 pVMR0, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
565{
566 AssertMsgFailed(("%d\n", uOperation));
567 return VERR_NOT_SUPPORTED;
568}
569
570
571SUPR3DECL(int) SUPCallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, unsigned idCpu)
572{
573 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_RAW_RUN))
574 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_RAW_RUN, idCpu);
575 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_HWACC_RUN))
576 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_HWACC_RUN, idCpu);
577 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_NOP))
578 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_NOP, idCpu);
579
580 AssertMsgFailed(("%#x\n", uOperation));
581 return VERR_INTERNAL_ERROR;
582}
583
584
585SUPR3DECL(int) SUPCallVMMR0Ex(PVMR0 pVMR0, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
586{
587 /*
588 * The following operations don't belong here.
589 */
590 AssertMsgReturn( uOperation != SUP_VMMR0_DO_RAW_RUN
591 && uOperation != SUP_VMMR0_DO_HWACC_RUN
592 && uOperation != SUP_VMMR0_DO_NOP,
593 ("%#x\n", uOperation),
594 VERR_INTERNAL_ERROR);
595
596 /* fake */
597 if (RT_UNLIKELY(g_u32FakeMode))
598 return supCallVMMR0ExFake(pVMR0, uOperation, u64Arg, pReqHdr);
599
600 int rc;
601 if (!pReqHdr)
602 {
603 /* no data. */
604 SUPCALLVMMR0 Req;
605 Req.Hdr.u32Cookie = g_u32Cookie;
606 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
607 Req.Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(0);
608 Req.Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(0);
609 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
610 Req.Hdr.rc = VERR_INTERNAL_ERROR;
611 Req.u.In.pVMR0 = pVMR0;
612 Req.u.In.uOperation = uOperation;
613 Req.u.In.u64Arg = u64Arg;
614 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(0), &Req, SUP_IOCTL_CALL_VMMR0_SIZE(0));
615 if (RT_SUCCESS(rc))
616 rc = Req.Hdr.rc;
617 }
618 else if (SUP_IOCTL_CALL_VMMR0_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */
619 {
620 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
621 AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);
622 const size_t cbReq = pReqHdr->cbReq;
623
624 PSUPCALLVMMR0 pReq = (PSUPCALLVMMR0)alloca(SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
625 pReq->Hdr.u32Cookie = g_u32Cookie;
626 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
627 pReq->Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(cbReq);
628 pReq->Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(cbReq);
629 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
630 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
631 pReq->u.In.pVMR0 = pVMR0;
632 pReq->u.In.uOperation = uOperation;
633 pReq->u.In.u64Arg = u64Arg;
634 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
635 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(cbReq), pReq, SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
636 if (RT_SUCCESS(rc))
637 rc = pReq->Hdr.rc;
638 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
639 }
640 else /** @todo may have to remove the size limits one this request... */
641 AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_INTERNAL_ERROR);
642 return rc;
643}
644
645
646SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg)
647{
648 /*
649 * The following operations don't belong here.
650 */
651 AssertMsgReturn( uOperation != SUP_VMMR0_DO_RAW_RUN
652 && uOperation != SUP_VMMR0_DO_HWACC_RUN
653 && uOperation != SUP_VMMR0_DO_NOP,
654 ("%#x\n", uOperation),
655 VERR_INTERNAL_ERROR);
656 return SUPCallVMMR0Ex(pVMR0, uOperation, (uintptr_t)pvArg, NULL);
657}
658
659
660SUPR3DECL(int) SUPSetVMForFastIOCtl(PVMR0 pVMR0)
661{
662 if (RT_UNLIKELY(g_u32FakeMode))
663 return VINF_SUCCESS;
664
665 SUPSETVMFORFAST Req;
666 Req.Hdr.u32Cookie = g_u32Cookie;
667 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
668 Req.Hdr.cbIn = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_IN;
669 Req.Hdr.cbOut = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_OUT;
670 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
671 Req.Hdr.rc = VERR_INTERNAL_ERROR;
672 Req.u.In.pVMR0 = pVMR0;
673 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SET_VM_FOR_FAST, &Req, SUP_IOCTL_SET_VM_FOR_FAST_SIZE);
674 if (RT_SUCCESS(rc))
675 rc = Req.Hdr.rc;
676 return rc;
677}
678
679
680SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
681{
682 AssertReturn(cchService < RT_SIZEOFMEMB(SUPCALLSERVICE, u.In.szName), VERR_INVALID_PARAMETER);
683 Assert(strlen(pszService) == cchService);
684
685 /* fake */
686 if (RT_UNLIKELY(g_u32FakeMode))
687 return VERR_NOT_SUPPORTED;
688
689 int rc;
690 if (!pReqHdr)
691 {
692 /* no data. */
693 SUPCALLSERVICE Req;
694 Req.Hdr.u32Cookie = g_u32Cookie;
695 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
696 Req.Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(0);
697 Req.Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(0);
698 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
699 Req.Hdr.rc = VERR_INTERNAL_ERROR;
700 memcpy(Req.u.In.szName, pszService, cchService);
701 Req.u.In.szName[cchService] = '\0';
702 Req.u.In.uOperation = uOperation;
703 Req.u.In.u64Arg = u64Arg;
704 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(0), &Req, SUP_IOCTL_CALL_SERVICE_SIZE(0));
705 if (RT_SUCCESS(rc))
706 rc = Req.Hdr.rc;
707 }
708 else if (SUP_IOCTL_CALL_SERVICE_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */
709 {
710 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
711 AssertReturn(pReqHdr->u32Magic == SUPR0SERVICEREQHDR_MAGIC, VERR_INVALID_MAGIC);
712 const size_t cbReq = pReqHdr->cbReq;
713
714 PSUPCALLSERVICE pReq = (PSUPCALLSERVICE)alloca(SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
715 pReq->Hdr.u32Cookie = g_u32Cookie;
716 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
717 pReq->Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(cbReq);
718 pReq->Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(cbReq);
719 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
720 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
721 memcpy(pReq->u.In.szName, pszService, cchService);
722 pReq->u.In.szName[cchService] = '\0';
723 pReq->u.In.uOperation = uOperation;
724 pReq->u.In.u64Arg = u64Arg;
725 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
726 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(cbReq), pReq, SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
727 if (RT_SUCCESS(rc))
728 rc = pReq->Hdr.rc;
729 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
730 }
731 else /** @todo may have to remove the size limits one this request... */
732 AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_INTERNAL_ERROR);
733 return rc;
734}
735
736
737/**
738 * Worker for the SUPR3Logger* APIs.
739 *
740 * @returns VBox status code.
741 * @param enmWhich Which logger.
742 * @param fWhat What to do with the logger.
743 * @param pszFlags The flags settings.
744 * @param pszGroups The groups settings.
745 * @param pszDest The destionation specificier.
746 */
747static int supR3LoggerSettings(SUPLOGGER enmWhich, uint32_t fWhat, const char *pszFlags, const char *pszGroups, const char *pszDest)
748{
749 uint32_t const cchFlags = pszFlags ? (uint32_t)strlen(pszFlags) : 0;
750 uint32_t const cchGroups = pszGroups ? (uint32_t)strlen(pszGroups) : 0;
751 uint32_t const cchDest = pszDest ? (uint32_t)strlen(pszDest) : 0;
752 uint32_t const cbStrTab = cchFlags + !!cchFlags
753 + cchGroups + !!cchGroups
754 + cchDest + !!cchDest
755 + (!cchFlags && !cchGroups && !cchDest);
756
757 PSUPLOGGERSETTINGS pReq = (PSUPLOGGERSETTINGS)alloca(SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
758 pReq->Hdr.u32Cookie = g_u32Cookie;
759 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
760 pReq->Hdr.cbIn = SUP_IOCTL_LOGGER_SETTINGS_SIZE_IN(cbStrTab);
761 pReq->Hdr.cbOut = SUP_IOCTL_LOGGER_SETTINGS_SIZE_OUT;
762 pReq->Hdr.fFlags= SUPREQHDR_FLAGS_DEFAULT;
763 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
764 switch (enmWhich)
765 {
766 case SUPLOGGER_DEBUG: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_DEBUG; break;
767 case SUPLOGGER_RELEASE: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_RELEASE; break;
768 default:
769 return VERR_INVALID_PARAMETER;
770 }
771 pReq->u.In.fWhat = fWhat;
772
773 uint32_t off = 0;
774 if (cchFlags)
775 {
776 pReq->u.In.offFlags = off;
777 memcpy(&pReq->u.In.szStrings[off], pszFlags, cchFlags + 1);
778 off += cchFlags + 1;
779 }
780 else
781 pReq->u.In.offFlags = cbStrTab - 1;
782
783 if (cchGroups)
784 {
785 pReq->u.In.offGroups = off;
786 memcpy(&pReq->u.In.szStrings[off], pszGroups, cchGroups + 1);
787 off += cchGroups + 1;
788 }
789 else
790 pReq->u.In.offGroups = cbStrTab - 1;
791
792 if (cchDest)
793 {
794 pReq->u.In.offDestination = off;
795 memcpy(&pReq->u.In.szStrings[off], pszDest, cchDest + 1);
796 off += cchDest + 1;
797 }
798 else
799 pReq->u.In.offDestination = cbStrTab - 1;
800
801 if (!off)
802 {
803 pReq->u.In.szStrings[0] = '\0';
804 off++;
805 }
806 Assert(off == cbStrTab);
807 Assert(pReq->u.In.szStrings[cbStrTab - 1] == '\0');
808
809
810 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOGGER_SETTINGS(cbStrTab), pReq, SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
811 if (RT_SUCCESS(rc))
812 rc = pReq->Hdr.rc;
813 return rc;
814}
815
816
817SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
818{
819 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_SETTINGS, pszFlags, pszGroups, pszDest);
820}
821
822
823SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
824{
825 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_CREATE, pszFlags, pszGroups, pszDest);
826}
827
828
829SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich)
830{
831 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_DESTROY, NULL, NULL, NULL);
832}
833
834
835SUPR3DECL(int) SUPPageAlloc(size_t cPages, void **ppvPages)
836{
837 /*
838 * Validate.
839 */
840 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
841 *ppvPages = NULL;
842 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
843
844#ifdef RT_OS_WINDOWS
845 /*
846 * Temporary hack for windows until we've sorted out the
847 * locked memory that doesn't need to be accessible from kernel space.
848 */
849 return SUPPageAllocLockedEx(cPages, ppvPages, NULL);
850#else
851 /*
852 * Call OS specific worker.
853 */
854 return suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);
855#endif
856}
857
858
859SUPR3DECL(int) SUPPageFree(void *pvPages, size_t cPages)
860{
861 /*
862 * Validate.
863 */
864 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
865 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
866
867#ifdef RT_OS_WINDOWS
868 /*
869 * Temporary hack for windows, see above.
870 */
871 return SUPPageFreeLocked(pvPages, cPages);
872#else
873 /*
874 * Call OS specific worker.
875 */
876 return suplibOsPageFree(&g_supLibData, pvPages, cPages);
877#endif
878}
879
880
881SUPR3DECL(int) SUPPageLock(void *pvStart, size_t cPages, PSUPPAGE paPages)
882{
883 /*
884 * Validate.
885 */
886 AssertPtr(pvStart);
887 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
888 AssertPtr(paPages);
889
890 /* fake */
891 if (RT_UNLIKELY(g_u32FakeMode))
892 {
893 RTHCPHYS Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024;
894 size_t iPage = cPages;
895 while (iPage-- > 0)
896 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
897 return VINF_SUCCESS;
898 }
899
900 /*
901 * Issue IOCtl to the SUPDRV kernel module.
902 */
903 int rc;
904 PSUPPAGELOCK pReq = (PSUPPAGELOCK)RTMemTmpAllocZ(SUP_IOCTL_PAGE_LOCK_SIZE(cPages));
905 if (RT_LIKELY(pReq))
906 {
907 pReq->Hdr.u32Cookie = g_u32Cookie;
908 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
909 pReq->Hdr.cbIn = SUP_IOCTL_PAGE_LOCK_SIZE_IN;
910 pReq->Hdr.cbOut = SUP_IOCTL_PAGE_LOCK_SIZE_OUT(cPages);
911 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
912 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
913 pReq->u.In.pvR3 = pvStart;
914 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
915 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_LOCK, pReq, SUP_IOCTL_PAGE_LOCK_SIZE(cPages));
916 if (RT_SUCCESS(rc))
917 rc = pReq->Hdr.rc;
918 if (RT_SUCCESS(rc))
919 {
920 for (uint32_t iPage = 0; iPage < cPages; iPage++)
921 {
922 paPages[iPage].uReserved = 0;
923 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
924 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
925 }
926 }
927 RTMemTmpFree(pReq);
928 }
929 else
930 rc = VERR_NO_TMP_MEMORY;
931
932 return rc;
933}
934
935
936SUPR3DECL(int) SUPPageUnlock(void *pvStart)
937{
938 /*
939 * Validate.
940 */
941 AssertPtr(pvStart);
942 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
943
944 /* fake */
945 if (RT_UNLIKELY(g_u32FakeMode))
946 return VINF_SUCCESS;
947
948 /*
949 * Issue IOCtl to the SUPDRV kernel module.
950 */
951 SUPPAGEUNLOCK Req;
952 Req.Hdr.u32Cookie = g_u32Cookie;
953 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
954 Req.Hdr.cbIn = SUP_IOCTL_PAGE_UNLOCK_SIZE_IN;
955 Req.Hdr.cbOut = SUP_IOCTL_PAGE_UNLOCK_SIZE_OUT;
956 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
957 Req.Hdr.rc = VERR_INTERNAL_ERROR;
958 Req.u.In.pvR3 = pvStart;
959 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_UNLOCK, &Req, SUP_IOCTL_PAGE_UNLOCK_SIZE);
960 if (RT_SUCCESS(rc))
961 rc = Req.Hdr.rc;
962 return rc;
963}
964
965
966SUPR3DECL(int) SUPPageAllocLockedEx(size_t cPages, void **ppvPages, PSUPPAGE paPages)
967{
968 return SUPR3PageAllocEx(cPages, 0 /*fFlags*/, ppvPages, NULL /*pR0Ptr*/, paPages);
969}
970
971
972SUPR3DECL(int) SUPPageFreeLocked(void *pvPages, size_t cPages)
973{
974 /*
975 * Validate.
976 */
977 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
978 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
979
980 /*
981 * Check if we're employing the fallback or not to avoid the
982 * fuzzy handling of this in SUPR3PageFreeEx.
983 */
984 int rc;
985 if (g_fSupportsPageAllocNoKernel)
986 rc = SUPR3PageFreeEx(pvPages, cPages);
987 else
988 {
989 /* fallback */
990 rc = SUPPageUnlock(pvPages);
991 if (RT_SUCCESS(rc))
992 rc = suplibOsPageFree(&g_supLibData, pvPages, cPages);
993 }
994 return rc;
995}
996
997
998/**
999 * Fallback for SUPPageAllocLockedEx on systems where RTR0MemObjPhysAllocNC isn't supported.
1000 */
1001static int supPagePageAllocNoKernelFallback(size_t cPages, void **ppvPages, PSUPPAGE paPages)
1002{
1003 int rc = suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);
1004 if (RT_SUCCESS(rc))
1005 {
1006 if (!paPages)
1007 paPages = (PSUPPAGE)alloca(sizeof(paPages[0]) * cPages);
1008 rc = SUPPageLock(*ppvPages, cPages, paPages);
1009 if (RT_FAILURE(rc))
1010 suplibOsPageFree(&g_supLibData, *ppvPages, cPages);
1011 }
1012 return rc;
1013}
1014
1015
1016SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages)
1017{
1018 /*
1019 * Validate.
1020 */
1021 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
1022 *ppvPages = NULL;
1023 AssertPtrNullReturn(pR0Ptr, VERR_INVALID_POINTER);
1024 if (pR0Ptr)
1025 *pR0Ptr = NIL_RTR0PTR;
1026 AssertPtrNullReturn(paPages, VERR_INVALID_POINTER);
1027 AssertMsgReturn(cPages > 0 && cPages <= VBOX_MAX_ALLOC_PAGE_COUNT, ("cPages=%zu\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
1028
1029 /* fake */
1030 if (RT_UNLIKELY(g_u32FakeMode))
1031 {
1032 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
1033 if (!pv)
1034 return VERR_NO_MEMORY;
1035 *ppvPages = pv;
1036 if (pR0Ptr)
1037 *pR0Ptr = (RTR0PTR)pv;
1038 if (paPages)
1039 for (size_t iPage = 0; iPage < cPages; iPage++)
1040 {
1041 paPages[iPage].uReserved = 0;
1042 paPages[iPage].Phys = (iPage + 4321) << PAGE_SHIFT;
1043 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1044 }
1045 return VINF_SUCCESS;
1046 }
1047
1048 /*
1049 * Use fallback for non-R0 mapping?
1050 */
1051 if ( !pR0Ptr
1052 && !g_fSupportsPageAllocNoKernel)
1053 return supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);
1054
1055 /*
1056 * Issue IOCtl to the SUPDRV kernel module.
1057 */
1058 int rc;
1059 PSUPPAGEALLOCEX pReq = (PSUPPAGEALLOCEX)RTMemTmpAllocZ(SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
1060 if (pReq)
1061 {
1062 pReq->Hdr.u32Cookie = g_u32Cookie;
1063 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
1064 pReq->Hdr.cbIn = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_IN;
1065 pReq->Hdr.cbOut = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_OUT(cPages);
1066 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
1067 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
1068 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
1069 pReq->u.In.fKernelMapping = pR0Ptr != NULL;
1070 pReq->u.In.fUserMapping = true;
1071 pReq->u.In.fReserved0 = false;
1072 pReq->u.In.fReserved1 = false;
1073 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_ALLOC_EX, pReq, SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
1074 if (RT_SUCCESS(rc))
1075 {
1076 rc = pReq->Hdr.rc;
1077 if (RT_SUCCESS(rc))
1078 {
1079 *ppvPages = pReq->u.Out.pvR3;
1080 if (pR0Ptr)
1081 *pR0Ptr = pReq->u.Out.pvR0;
1082 if (paPages)
1083 for (size_t iPage = 0; iPage < cPages; iPage++)
1084 {
1085 paPages[iPage].uReserved = 0;
1086 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
1087 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1088 }
1089 }
1090 else if ( rc == VERR_NOT_SUPPORTED
1091 && !pR0Ptr)
1092 {
1093 g_fSupportsPageAllocNoKernel = false;
1094 rc = supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);
1095 }
1096 }
1097
1098 RTMemTmpFree(pReq);
1099 }
1100 else
1101 rc = VERR_NO_TMP_MEMORY;
1102 return rc;
1103
1104}
1105
1106
1107SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr)
1108{
1109 /*
1110 * Validate.
1111 */
1112 AssertPtrReturn(pvR3, VERR_INVALID_POINTER);
1113 AssertPtrReturn(pR0Ptr, VERR_INVALID_POINTER);
1114 Assert(!(off & PAGE_OFFSET_MASK));
1115 Assert(!(cb & PAGE_OFFSET_MASK) && cb);
1116 Assert(!fFlags);
1117 *pR0Ptr = NIL_RTR0PTR;
1118
1119 /* fake */
1120 if (RT_UNLIKELY(g_u32FakeMode))
1121 return VERR_NOT_SUPPORTED;
1122
1123 /*
1124 * Issue IOCtl to the SUPDRV kernel module.
1125 */
1126 SUPPAGEMAPKERNEL Req;
1127 Req.Hdr.u32Cookie = g_u32Cookie;
1128 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1129 Req.Hdr.cbIn = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_IN;
1130 Req.Hdr.cbOut = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_OUT;
1131 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1132 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1133 Req.u.In.pvR3 = pvR3;
1134 Req.u.In.offSub = off;
1135 Req.u.In.cbSub = cb;
1136 Req.u.In.fFlags = fFlags;
1137 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_MAP_KERNEL, &Req, SUP_IOCTL_PAGE_MAP_KERNEL_SIZE);
1138 if (RT_SUCCESS(rc))
1139 rc = Req.Hdr.rc;
1140 if (RT_SUCCESS(rc))
1141 *pR0Ptr = Req.u.Out.pvR0;
1142 return rc;
1143}
1144
1145
1146SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages)
1147{
1148 /*
1149 * Validate.
1150 */
1151 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
1152 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1153
1154 /* fake */
1155 if (RT_UNLIKELY(g_u32FakeMode))
1156 {
1157 RTMemPageFree(pvPages);
1158 return VINF_SUCCESS;
1159 }
1160
1161 /*
1162 * Try normal free first, then if it fails check if we're using the fallback .
1163 * for the allocations without kernel mappings and attempt unlocking it.
1164 */
1165 NOREF(cPages);
1166 SUPPAGEFREE Req;
1167 Req.Hdr.u32Cookie = g_u32Cookie;
1168 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1169 Req.Hdr.cbIn = SUP_IOCTL_PAGE_FREE_SIZE_IN;
1170 Req.Hdr.cbOut = SUP_IOCTL_PAGE_FREE_SIZE_OUT;
1171 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1172 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1173 Req.u.In.pvR3 = pvPages;
1174 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_FREE, &Req, SUP_IOCTL_PAGE_FREE_SIZE);
1175 if (RT_SUCCESS(rc))
1176 {
1177 rc = Req.Hdr.rc;
1178 if ( rc == VERR_INVALID_PARAMETER
1179 && !g_fSupportsPageAllocNoKernel)
1180 {
1181 int rc2 = SUPPageUnlock(pvPages);
1182 if (RT_SUCCESS(rc2))
1183 rc = suplibOsPageFree(&g_supLibData, pvPages, cPages);
1184 }
1185 }
1186 return rc;
1187}
1188
1189
1190SUPR3DECL(void *) SUPContAlloc(size_t cPages, PRTHCPHYS pHCPhys)
1191{
1192 return SUPContAlloc2(cPages, NIL_RTR0PTR, pHCPhys);
1193}
1194
1195
1196SUPR3DECL(void *) SUPContAlloc2(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys)
1197{
1198 /*
1199 * Validate.
1200 */
1201 AssertPtrReturn(pHCPhys, NULL);
1202 *pHCPhys = NIL_RTHCPHYS;
1203 AssertPtrNullReturn(pR0Ptr, NULL);
1204 if (pR0Ptr)
1205 *pR0Ptr = NIL_RTR0PTR;
1206 AssertPtrNullReturn(pHCPhys, NULL);
1207 AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), NULL);
1208
1209 /* fake */
1210 if (RT_UNLIKELY(g_u32FakeMode))
1211 {
1212 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
1213 if (pR0Ptr)
1214 *pR0Ptr = (RTR0PTR)pv;
1215 if (pHCPhys)
1216 *pHCPhys = (uintptr_t)pv + (PAGE_SHIFT * 1024);
1217 return pv;
1218 }
1219
1220 /*
1221 * Issue IOCtl to the SUPDRV kernel module.
1222 */
1223 SUPCONTALLOC Req;
1224 Req.Hdr.u32Cookie = g_u32Cookie;
1225 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1226 Req.Hdr.cbIn = SUP_IOCTL_CONT_ALLOC_SIZE_IN;
1227 Req.Hdr.cbOut = SUP_IOCTL_CONT_ALLOC_SIZE_OUT;
1228 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1229 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1230 Req.u.In.cPages = (uint32_t)cPages;
1231 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_ALLOC, &Req, SUP_IOCTL_CONT_ALLOC_SIZE);
1232 if ( RT_SUCCESS(rc)
1233 && RT_SUCCESS(Req.Hdr.rc))
1234 {
1235 *pHCPhys = Req.u.Out.HCPhys;
1236 if (pR0Ptr)
1237 *pR0Ptr = Req.u.Out.pvR0;
1238 return Req.u.Out.pvR3;
1239 }
1240
1241 return NULL;
1242}
1243
1244
1245SUPR3DECL(int) SUPContFree(void *pv, size_t cPages)
1246{
1247 /*
1248 * Validate.
1249 */
1250 if (!pv)
1251 return VINF_SUCCESS;
1252 AssertPtrReturn(pv, VERR_INVALID_POINTER);
1253 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1254
1255 /* fake */
1256 if (RT_UNLIKELY(g_u32FakeMode))
1257 {
1258 RTMemPageFree(pv);
1259 return VINF_SUCCESS;
1260 }
1261
1262 /*
1263 * Issue IOCtl to the SUPDRV kernel module.
1264 */
1265 SUPCONTFREE Req;
1266 Req.Hdr.u32Cookie = g_u32Cookie;
1267 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1268 Req.Hdr.cbIn = SUP_IOCTL_CONT_FREE_SIZE_IN;
1269 Req.Hdr.cbOut = SUP_IOCTL_CONT_FREE_SIZE_OUT;
1270 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1271 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1272 Req.u.In.pvR3 = pv;
1273 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_FREE, &Req, SUP_IOCTL_CONT_FREE_SIZE);
1274 if (RT_SUCCESS(rc))
1275 rc = Req.Hdr.rc;
1276 return rc;
1277}
1278
1279
1280SUPR3DECL(int) SUPLowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages)
1281{
1282 /*
1283 * Validate.
1284 */
1285 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
1286 *ppvPages = NULL;
1287 AssertPtrReturn(paPages, VERR_INVALID_POINTER);
1288 AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
1289
1290 /* fake */
1291 if (RT_UNLIKELY(g_u32FakeMode))
1292 {
1293 *ppvPages = RTMemPageAllocZ((size_t)cPages * PAGE_SIZE);
1294 if (!*ppvPages)
1295 return VERR_NO_LOW_MEMORY;
1296
1297 /* fake physical addresses. */
1298 RTHCPHYS Phys = (uintptr_t)*ppvPages + PAGE_SIZE * 1024;
1299 size_t iPage = cPages;
1300 while (iPage-- > 0)
1301 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
1302 return VINF_SUCCESS;
1303 }
1304
1305 /*
1306 * Issue IOCtl to the SUPDRV kernel module.
1307 */
1308 int rc;
1309 PSUPLOWALLOC pReq = (PSUPLOWALLOC)RTMemTmpAllocZ(SUP_IOCTL_LOW_ALLOC_SIZE(cPages));
1310 if (pReq)
1311 {
1312 pReq->Hdr.u32Cookie = g_u32Cookie;
1313 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
1314 pReq->Hdr.cbIn = SUP_IOCTL_LOW_ALLOC_SIZE_IN;
1315 pReq->Hdr.cbOut = SUP_IOCTL_LOW_ALLOC_SIZE_OUT(cPages);
1316 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
1317 pReq->Hdr.rc = VERR_INTERNAL_ERROR;
1318 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
1319 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_ALLOC, pReq, SUP_IOCTL_LOW_ALLOC_SIZE(cPages));
1320 if (RT_SUCCESS(rc))
1321 rc = pReq->Hdr.rc;
1322 if (RT_SUCCESS(rc))
1323 {
1324 *ppvPages = pReq->u.Out.pvR3;
1325 if (ppvPagesR0)
1326 *ppvPagesR0 = pReq->u.Out.pvR0;
1327 if (paPages)
1328 for (size_t iPage = 0; iPage < cPages; iPage++)
1329 {
1330 paPages[iPage].uReserved = 0;
1331 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
1332 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
1333 Assert(paPages[iPage].Phys <= UINT32_C(0xfffff000));
1334 }
1335 }
1336 RTMemTmpFree(pReq);
1337 }
1338 else
1339 rc = VERR_NO_TMP_MEMORY;
1340
1341 return rc;
1342}
1343
1344
1345SUPR3DECL(int) SUPLowFree(void *pv, size_t cPages)
1346{
1347 /*
1348 * Validate.
1349 */
1350 if (!pv)
1351 return VINF_SUCCESS;
1352 AssertPtrReturn(pv, VERR_INVALID_POINTER);
1353 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
1354
1355 /* fake */
1356 if (RT_UNLIKELY(g_u32FakeMode))
1357 {
1358 RTMemPageFree(pv);
1359 return VINF_SUCCESS;
1360 }
1361
1362 /*
1363 * Issue IOCtl to the SUPDRV kernel module.
1364 */
1365 SUPCONTFREE Req;
1366 Req.Hdr.u32Cookie = g_u32Cookie;
1367 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1368 Req.Hdr.cbIn = SUP_IOCTL_LOW_FREE_SIZE_IN;
1369 Req.Hdr.cbOut = SUP_IOCTL_LOW_FREE_SIZE_OUT;
1370 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1371 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1372 Req.u.In.pvR3 = pv;
1373 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_FREE, &Req, SUP_IOCTL_LOW_FREE_SIZE);
1374 if (RT_SUCCESS(rc))
1375 rc = Req.Hdr.rc;
1376 return rc;
1377}
1378
1379
1380SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszMsg, PRTFILE phFile)
1381{
1382 /*
1383 * Quick input validation.
1384 */
1385 AssertPtr(pszFilename);
1386 AssertPtr(pszMsg);
1387 AssertReturn(!phFile, VERR_NOT_IMPLEMENTED); /** @todo Implement this. The deal is that we make sure the
1388 file is the same we verified after opening it. */
1389
1390 /*
1391 * Only do the actual check in hardened builds.
1392 */
1393#ifdef VBOX_WITH_HARDENING
1394 int rc = supR3HardenedVerifyFile(pszFilename, false /* fFatal */);
1395 if (RT_FAILURE(rc))
1396 LogRel(("SUPR3HardenedVerifyFile: %s: Verification of \"%s\" failed, rc=%Rrc\n", pszMsg, pszFilename, rc));
1397 return rc;
1398#else
1399 return VINF_SUCCESS;
1400#endif
1401}
1402
1403
1404SUPR3DECL(int) SUPLoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase)
1405{
1406 int rc = VINF_SUCCESS;
1407#ifdef VBOX_WITH_HARDENING
1408 /*
1409 * Check that the module can be trusted.
1410 */
1411 rc = supR3HardenedVerifyFile(pszFilename, false /* fFatal */);
1412#endif
1413 if (RT_SUCCESS(rc))
1414 rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);
1415 else
1416 LogRel(("SUPLoadModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
1417 return rc;
1418}
1419
1420
1421SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
1422 const char *pszSrvReqHandler, void **ppvImageBase)
1423{
1424 int rc = VINF_SUCCESS;
1425 AssertPtrReturn(pszSrvReqHandler, VERR_INVALID_PARAMETER);
1426
1427#ifdef VBOX_WITH_HARDENING
1428 /*
1429 * Check that the module can be trusted.
1430 */
1431 rc = supR3HardenedVerifyFile(pszFilename, false /* fFatal */);
1432#endif
1433 if (RT_SUCCESS(rc))
1434 rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);
1435 else
1436 LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
1437 return rc;
1438}
1439
1440
1441/**
1442 * Resolve an external symbol during RTLdrGetBits().
1443 *
1444 * @returns VBox status code.
1445 * @param hLdrMod The loader module handle.
1446 * @param pszModule Module name.
1447 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
1448 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
1449 * @param pValue Where to store the symbol value (address).
1450 * @param pvUser User argument.
1451 */
1452static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,
1453 const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
1454{
1455 AssertPtr(pValue);
1456 AssertPtr(pvUser);
1457
1458 /*
1459 * Only SUPR0 and VMMR0.r0
1460 */
1461 if ( pszModule
1462 && *pszModule
1463 && strcmp(pszModule, "SUPR0.dll")
1464 && strcmp(pszModule, "VMMR0.r0"))
1465 {
1466 AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitiv)\n", pvUser, pszModule));
1467 return VERR_SYMBOL_NOT_FOUND;
1468 }
1469
1470 /*
1471 * No ordinals.
1472 */
1473 if (pszSymbol < (const char*)0x10000)
1474 {
1475 AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));
1476 return VERR_SYMBOL_NOT_FOUND;
1477 }
1478
1479 /*
1480 * Lookup symbol.
1481 */
1482 /* skip the 64-bit ELF import prefix first. */
1483 if (!strncmp(pszSymbol, "SUPR0$", sizeof("SUPR0$") - 1))
1484 pszSymbol += sizeof("SUPR0$") - 1;
1485
1486 /*
1487 * Check the VMMR0.r0 module if loaded.
1488 */
1489 /** @todo call the SUPLoadModule caller.... */
1490 /** @todo proper reference counting and such. */
1491 if (g_pvVMMR0 != NIL_RTR0PTR)
1492 {
1493 void *pvValue;
1494 if (!SUPGetSymbolR0((void *)g_pvVMMR0, pszSymbol, &pvValue))
1495 {
1496 *pValue = (uintptr_t)pvValue;
1497 return VINF_SUCCESS;
1498 }
1499 }
1500
1501 /* iterate the function table. */
1502 int c = g_pFunctions->u.Out.cFunctions;
1503 PSUPFUNC pFunc = &g_pFunctions->u.Out.aFunctions[0];
1504 while (c-- > 0)
1505 {
1506 if (!strcmp(pFunc->szName, pszSymbol))
1507 {
1508 *pValue = (uintptr_t)pFunc->pfn;
1509 return VINF_SUCCESS;
1510 }
1511 pFunc++;
1512 }
1513
1514 /*
1515 * The GIP.
1516 */
1517 /** @todo R0 mapping? */
1518 if ( pszSymbol
1519 && g_pSUPGlobalInfoPage
1520 && g_pSUPGlobalInfoPageR0
1521 && !strcmp(pszSymbol, "g_SUPGlobalInfoPage"))
1522 {
1523 *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;
1524 return VINF_SUCCESS;
1525 }
1526
1527 /*
1528 * Despair.
1529 */
1530 c = g_pFunctions->u.Out.cFunctions;
1531 pFunc = &g_pFunctions->u.Out.aFunctions[0];
1532 while (c-- > 0)
1533 {
1534 AssertMsg2("%d: %s\n", g_pFunctions->u.Out.cFunctions - c, pFunc->szName);
1535 pFunc++;
1536 }
1537
1538 AssertMsg2("%s is importing %s which we couldn't find\n", pvUser, pszSymbol);
1539 AssertMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
1540 if (g_u32FakeMode)
1541 {
1542 *pValue = 0xdeadbeef;
1543 return VINF_SUCCESS;
1544 }
1545 return VERR_SYMBOL_NOT_FOUND;
1546}
1547
1548
1549/** Argument package for supLoadModuleCalcSizeCB. */
1550typedef struct SUPLDRCALCSIZEARGS
1551{
1552 size_t cbStrings;
1553 uint32_t cSymbols;
1554 size_t cbImage;
1555} SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;
1556
1557/**
1558 * Callback used to calculate the image size.
1559 * @return VINF_SUCCESS
1560 */
1561static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
1562{
1563 PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;
1564 if ( pszSymbol != NULL
1565 && *pszSymbol
1566 && Value <= pArgs->cbImage)
1567 {
1568 pArgs->cSymbols++;
1569 pArgs->cbStrings += strlen(pszSymbol) + 1;
1570 }
1571 return VINF_SUCCESS;
1572}
1573
1574
1575/** Argument package for supLoadModuleCreateTabsCB. */
1576typedef struct SUPLDRCREATETABSARGS
1577{
1578 size_t cbImage;
1579 PSUPLDRSYM pSym;
1580 char *pszBase;
1581 char *psz;
1582} SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;
1583
1584/**
1585 * Callback used to calculate the image size.
1586 * @return VINF_SUCCESS
1587 */
1588static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
1589{
1590 PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;
1591 if ( pszSymbol != NULL
1592 && *pszSymbol
1593 && Value <= pArgs->cbImage)
1594 {
1595 pArgs->pSym->offSymbol = (uint32_t)Value;
1596 pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;
1597 pArgs->pSym++;
1598
1599 size_t cbCopy = strlen(pszSymbol) + 1;
1600 memcpy(pArgs->psz, pszSymbol, cbCopy);
1601 pArgs->psz += cbCopy;
1602 }
1603 return VINF_SUCCESS;
1604}
1605
1606
1607/**
1608 * Worker for SUPLoadModule().
1609 *
1610 * @returns VBox status code.
1611 * @param pszFilename Name of the VMMR0 image file
1612 */
1613static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)
1614{
1615 /*
1616 * Validate input.
1617 */
1618 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
1619 AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
1620 AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
1621 AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);
1622
1623 const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");
1624 AssertReturn(!pszSrvReqHandler || !fIsVMMR0, VERR_INTERNAL_ERROR);
1625 *ppvImageBase = NULL;
1626
1627 /*
1628 * Open image file and figure its size.
1629 */
1630 RTLDRMOD hLdrMod;
1631 int rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);
1632 if (!RT_SUCCESS(rc))
1633 return rc;
1634
1635 SUPLDRCALCSIZEARGS CalcArgs;
1636 CalcArgs.cbStrings = 0;
1637 CalcArgs.cSymbols = 0;
1638 CalcArgs.cbImage = RTLdrSize(hLdrMod);
1639 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
1640 if (RT_SUCCESS(rc))
1641 {
1642 const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
1643 const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
1644 const uint32_t cbImage = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
1645
1646 /*
1647 * Open the R0 image.
1648 */
1649 SUPLDROPEN OpenReq;
1650 OpenReq.Hdr.u32Cookie = g_u32Cookie;
1651 OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
1652 OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
1653 OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
1654 OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1655 OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
1656 OpenReq.u.In.cbImage = cbImage;
1657 strcpy(OpenReq.u.In.szName, pszModule);
1658 if (!g_u32FakeMode)
1659 {
1660 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
1661 if (RT_SUCCESS(rc))
1662 rc = OpenReq.Hdr.rc;
1663 }
1664 else
1665 {
1666 OpenReq.u.Out.fNeedsLoading = true;
1667 OpenReq.u.Out.pvImageBase = 0xef423420;
1668 }
1669 *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
1670 if ( RT_SUCCESS(rc)
1671 && OpenReq.u.Out.fNeedsLoading)
1672 {
1673 /*
1674 * We need to load it.
1675 * Allocate memory for the image bits.
1676 */
1677 PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImage));
1678 if (pLoadReq)
1679 {
1680 /*
1681 * Get the image bits.
1682 */
1683 rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
1684 supLoadModuleResolveImport, (void *)pszModule);
1685
1686 if (RT_SUCCESS(rc))
1687 {
1688 /*
1689 * Get the entry points.
1690 */
1691 RTUINTPTR VMMR0EntryInt = 0;
1692 RTUINTPTR VMMR0EntryFast = 0;
1693 RTUINTPTR VMMR0EntryEx = 0;
1694 RTUINTPTR SrvReqHandler = 0;
1695 RTUINTPTR ModuleInit = 0;
1696 RTUINTPTR ModuleTerm = 0;
1697 if (fIsVMMR0)
1698 {
1699 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryInt", &VMMR0EntryInt);
1700 if (RT_SUCCESS(rc))
1701 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryFast", &VMMR0EntryFast);
1702 if (RT_SUCCESS(rc))
1703 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryEx", &VMMR0EntryEx);
1704 }
1705 else if (pszSrvReqHandler)
1706 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, pszSrvReqHandler, &SrvReqHandler);
1707 if (RT_SUCCESS(rc))
1708 {
1709 int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleInit", &ModuleInit);
1710 if (RT_FAILURE(rc2))
1711 ModuleInit = 0;
1712
1713 rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.achImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleTerm", &ModuleTerm);
1714 if (RT_FAILURE(rc2))
1715 ModuleTerm = 0;
1716 }
1717 if (RT_SUCCESS(rc))
1718 {
1719 /*
1720 * Create the symbol and string tables.
1721 */
1722 SUPLDRCREATETABSARGS CreateArgs;
1723 CreateArgs.cbImage = CalcArgs.cbImage;
1724 CreateArgs.pSym = (PSUPLDRSYM)&pLoadReq->u.In.achImage[offSymTab];
1725 CreateArgs.pszBase = (char *)&pLoadReq->u.In.achImage[offStrTab];
1726 CreateArgs.psz = CreateArgs.pszBase;
1727 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
1728 if (RT_SUCCESS(rc))
1729 {
1730 AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
1731 AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.achImage[offSymTab]) <= CalcArgs.cSymbols);
1732
1733 /*
1734 * Upload the image.
1735 */
1736 pLoadReq->Hdr.u32Cookie = g_u32Cookie;
1737 pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
1738 pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImage);
1739 pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
1740 pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
1741 pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
1742
1743 pLoadReq->u.In.pfnModuleInit = (RTR0PTR)ModuleInit;
1744 pLoadReq->u.In.pfnModuleTerm = (RTR0PTR)ModuleTerm;
1745 if (fIsVMMR0)
1746 {
1747 pLoadReq->u.In.eEPType = SUPLDRLOADEP_VMMR0;
1748 pLoadReq->u.In.EP.VMMR0.pvVMMR0 = OpenReq.u.Out.pvImageBase;
1749 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryInt = (RTR0PTR)VMMR0EntryInt;
1750 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
1751 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx = (RTR0PTR)VMMR0EntryEx;
1752 }
1753 else if (pszSrvReqHandler)
1754 {
1755 pLoadReq->u.In.eEPType = SUPLDRLOADEP_SERVICE;
1756 pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
1757 pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
1758 pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
1759 pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
1760 }
1761 else
1762 pLoadReq->u.In.eEPType = SUPLDRLOADEP_NOTHING;
1763 pLoadReq->u.In.offStrTab = offStrTab;
1764 pLoadReq->u.In.cbStrTab = (uint32_t)CalcArgs.cbStrings;
1765 AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);
1766 pLoadReq->u.In.offSymbols = offSymTab;
1767 pLoadReq->u.In.cSymbols = CalcArgs.cSymbols;
1768 pLoadReq->u.In.cbImage = cbImage;
1769 pLoadReq->u.In.pvImageBase = OpenReq.u.Out.pvImageBase;
1770 if (!g_u32FakeMode)
1771 {
1772 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImage));
1773 if (RT_SUCCESS(rc))
1774 rc = pLoadReq->Hdr.rc;
1775 }
1776 else
1777 rc = VINF_SUCCESS;
1778 if ( RT_SUCCESS(rc)
1779 || rc == VERR_ALREADY_LOADED /* A competing process. */
1780 )
1781 {
1782 LogRel(("SUP: Loaded %s (%s) at %#p - ModuleInit at %RTptr and ModuleTerm at %RTptr\n", pszModule, pszFilename,
1783 OpenReq.u.Out.pvImageBase, ModuleInit, ModuleTerm));
1784 if (fIsVMMR0)
1785 {
1786 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
1787 LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",
1788 VMMR0EntryEx, VMMR0EntryFast, VMMR0EntryInt));
1789 }
1790#ifdef RT_OS_WINDOWS
1791 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
1792#endif
1793
1794 RTMemTmpFree(pLoadReq);
1795 RTLdrClose(hLdrMod);
1796 return VINF_SUCCESS;
1797 }
1798 }
1799 }
1800 }
1801 RTMemTmpFree(pLoadReq);
1802 }
1803 else
1804 {
1805 AssertMsgFailed(("failed to allocated %d bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImage)));
1806 rc = VERR_NO_TMP_MEMORY;
1807 }
1808 }
1809 else if (RT_SUCCESS(rc))
1810 {
1811 if (fIsVMMR0)
1812 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
1813 LogRel(("SUP: Opened %s (%s) at %#p.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase));
1814#ifdef RT_OS_WINDOWS
1815 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
1816#endif
1817 }
1818 }
1819 RTLdrClose(hLdrMod);
1820 return rc;
1821}
1822
1823
1824SUPR3DECL(int) SUPFreeModule(void *pvImageBase)
1825{
1826 /* fake */
1827 if (RT_UNLIKELY(g_u32FakeMode))
1828 {
1829 g_pvVMMR0 = NIL_RTR0PTR;
1830 return VINF_SUCCESS;
1831 }
1832
1833 /*
1834 * Free the requested module.
1835 */
1836 SUPLDRFREE Req;
1837 Req.Hdr.u32Cookie = g_u32Cookie;
1838 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1839 Req.Hdr.cbIn = SUP_IOCTL_LDR_FREE_SIZE_IN;
1840 Req.Hdr.cbOut = SUP_IOCTL_LDR_FREE_SIZE_OUT;
1841 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1842 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1843 Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
1844 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_FREE, &Req, SUP_IOCTL_LDR_FREE_SIZE);
1845 if (RT_SUCCESS(rc))
1846 rc = Req.Hdr.rc;
1847 if ( RT_SUCCESS(rc)
1848 && (RTR0PTR)pvImageBase == g_pvVMMR0)
1849 g_pvVMMR0 = NIL_RTR0PTR;
1850 return rc;
1851}
1852
1853
1854SUPR3DECL(int) SUPGetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)
1855{
1856 *ppvValue = NULL;
1857
1858 /* fake */
1859 if (RT_UNLIKELY(g_u32FakeMode))
1860 {
1861 *ppvValue = (void *)(uintptr_t)0xdeadf00d;
1862 return VINF_SUCCESS;
1863 }
1864
1865 /*
1866 * Do ioctl.
1867 */
1868 SUPLDRGETSYMBOL Req;
1869 Req.Hdr.u32Cookie = g_u32Cookie;
1870 Req.Hdr.u32SessionCookie = g_u32SessionCookie;
1871 Req.Hdr.cbIn = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_IN;
1872 Req.Hdr.cbOut = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_OUT;
1873 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
1874 Req.Hdr.rc = VERR_INTERNAL_ERROR;
1875 Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
1876 size_t cchSymbol = strlen(pszSymbol);
1877 if (cchSymbol >= sizeof(Req.u.In.szSymbol))
1878 return VERR_SYMBOL_NOT_FOUND;
1879 memcpy(Req.u.In.szSymbol, pszSymbol, cchSymbol + 1);
1880 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);
1881 if (RT_SUCCESS(rc))
1882 rc = Req.Hdr.rc;
1883 if (RT_SUCCESS(rc))
1884 *ppvValue = (void *)Req.u.Out.pvSymbol;
1885 return rc;
1886}
1887
1888
1889SUPR3DECL(int) SUPLoadVMM(const char *pszFilename)
1890{
1891 void *pvImageBase;
1892 return SUPLoadModule(pszFilename, "VMMR0.r0", &pvImageBase);
1893}
1894
1895
1896SUPR3DECL(int) SUPUnloadVMM(void)
1897{
1898 return SUPFreeModule((void*)g_pvVMMR0);
1899}
1900
1901
1902SUPR3DECL(int) SUPGipGetPhys(PRTHCPHYS pHCPhys)
1903{
1904 if (g_pSUPGlobalInfoPage)
1905 {
1906 *pHCPhys = g_HCPhysSUPGlobalInfoPage;
1907 return VINF_SUCCESS;
1908 }
1909 *pHCPhys = NIL_RTHCPHYS;
1910 return VERR_WRONG_ORDER;
1911}
1912
1913
1914/**
1915 * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.
1916 *
1917 * @returns iprt status code.
1918 * @param pszFilename The full file name.
1919 * @param phLdrMod Where to store the handle to the loaded module.
1920 */
1921static int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod)
1922{
1923#ifdef VBOX_WITH_HARDENING
1924 /*
1925 * Verify the image file.
1926 */
1927 int rc = supR3HardenedVerifyFile(pszFilename, false /* fFatal */);
1928 if (RT_FAILURE(rc))
1929 {
1930 LogRel(("supR3HardenedLdrLoadIt: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
1931 return rc;
1932 }
1933#endif
1934
1935 /*
1936 * Try load it.
1937 */
1938 return RTLdrLoad(pszFilename, phLdrMod);
1939}
1940
1941
1942SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod)
1943{
1944 /*
1945 * Validate input.
1946 */
1947 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
1948 AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
1949 *phLdrMod = NIL_RTLDRMOD;
1950 AssertReturn(RTPathHavePath(pszFilename), VERR_INVALID_PARAMETER);
1951
1952 /*
1953 * Add the default extension if it's missing.
1954 */
1955 if (!RTPathHaveExt(pszFilename))
1956 {
1957 const char *pszSuff = RTLdrGetSuff();
1958 size_t cchSuff = strlen(pszSuff);
1959 size_t cchFilename = strlen(pszFilename);
1960 char *psz = (char *)alloca(cchFilename + cchSuff + 1);
1961 AssertReturn(psz, VERR_NO_TMP_MEMORY);
1962 memcpy(psz, pszFilename, cchFilename);
1963 memcpy(psz + cchFilename, pszSuff, cchSuff + 1);
1964 pszFilename = psz;
1965 }
1966
1967 /*
1968 * Pass it on to the common library loader.
1969 */
1970 return supR3HardenedLdrLoadIt(pszFilename, phLdrMod);
1971}
1972
1973
1974SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod)
1975{
1976 LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p\n", pszFilename, pszFilename, phLdrMod));
1977
1978 /*
1979 * Validate input.
1980 */
1981 AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
1982 *phLdrMod = NIL_RTLDRMOD;
1983 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
1984 AssertMsgReturn(!RTPathHavePath(pszFilename), ("%s\n", pszFilename), VERR_INVALID_PARAMETER);
1985
1986 /*
1987 * Check the filename.
1988 */
1989 size_t cchFilename = strlen(pszFilename);
1990 AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);
1991
1992 const char *pszExt = "";
1993 size_t cchExt = 0;
1994 if (!RTPathHaveExt(pszFilename))
1995 {
1996 pszExt = RTLdrGetSuff();
1997 cchExt = strlen(pszExt);
1998 }
1999
2000 /*
2001 * Construct the private arch path and check if the file exists.
2002 */
2003 char szPath[RTPATH_MAX];
2004 int rc = RTPathAppPrivateArch(szPath, sizeof(szPath) - 1 - cchExt - cchFilename);
2005 AssertRCReturn(rc, rc);
2006
2007 char *psz = strchr(szPath, '\0');
2008 *psz++ = RTPATH_SLASH;
2009 memcpy(psz, pszFilename, cchFilename);
2010 psz += cchFilename;
2011 memcpy(psz, pszExt, cchExt + 1);
2012
2013 if (!RTPathExists(szPath))
2014 {
2015 LogRel(("SUPR3HardenedLdrLoadAppPriv: \"%s\" not found\n", szPath));
2016 return VERR_FILE_NOT_FOUND;
2017 }
2018
2019 /*
2020 * Pass it on to SUPR3HardenedLdrLoad.
2021 */
2022 rc = SUPR3HardenedLdrLoad(szPath, phLdrMod);
2023
2024 LogFlow(("SUPR3HardenedLdrLoadAppPriv: returns %Rrc\n", rc));
2025 return rc;
2026}
2027
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use