diff --git a/binaries/system/aken.sys b/binaries/system/aken.sys index a2420ea7a3..f5f5259a70 100644 Binary files a/binaries/system/aken.sys and b/binaries/system/aken.sys differ diff --git a/binaries/system/aken64.sys b/binaries/system/aken64.sys index 8e70101b24..e943548418 100644 Binary files a/binaries/system/aken64.sys and b/binaries/system/aken64.sys differ diff --git a/binaries/system/aken64d.sys b/binaries/system/aken64d.sys index 5874e9c333..54324b6458 100644 Binary files a/binaries/system/aken64d.sys and b/binaries/system/aken64d.sys differ diff --git a/binaries/system/akend.sys b/binaries/system/akend.sys index fa2a8d6bef..9a48032c66 100644 Binary files a/binaries/system/akend.sys and b/binaries/system/akend.sys differ diff --git a/source/lib/sysdep/acpi.cpp b/source/lib/sysdep/acpi.cpp index ac160b6558..85ca3dec99 100644 --- a/source/lib/sysdep/acpi.cpp +++ b/source/lib/sysdep/acpi.cpp @@ -7,6 +7,7 @@ #pragma pack(1) + //----------------------------------------------------------------------------- // table utility functions //----------------------------------------------------------------------------- @@ -27,27 +28,32 @@ static u8 ComputeChecksum(const void* buf, size_t numBytes) // free() the returned pointer. static const AcpiTable* AllocateCopyOfTable(u64 physicalAddress) { - // 4 KiB ought to be enough; if not, the table will be re-mapped. - const size_t initialSize = 4*KiB; - const AcpiTable* mappedTable = (const AcpiTable*)mahaf_MapPhysicalMemory(physicalAddress, initialSize); - if(!mappedTable) + // ACPI table sizes are not known until they've been mapped and copied. + // since that is slow, we don't want to do it twice; solution is to copy + // into a buffer big enough to hold a typical table. if it should be too + // small, we map and copy again. using a temporary buffer, rather than + // allocating that much up-front, avoids wasting memory for each table. + static const size_t tempTableSize = 4*KiB; + static u8 tempTableBuf[tempTableSize]; + const AcpiTable* tempTable = (const AcpiTable*)tempTableBuf; + if(!mahaf_CopyPhysicalMemory(physicalAddress, tempTableSize, (void*)tempTable)) return 0; - const size_t size = mappedTable->size; - if(size > initialSize) + // allocate the final table + const size_t size = tempTable->size; + const AcpiTable* table = (const AcpiTable*)malloc(size); + if(!table) + return 0; + + // and fill it. + if(size <= tempTableSize) + cpu_memcpy((void*)table, tempTable, size); + else { - // re-map with correct size - mahaf_UnmapPhysicalMemory((void*)mappedTable); - mappedTable = (const AcpiTable*)mahaf_MapPhysicalMemory(physicalAddress, size); - if(!mappedTable) + if(!mahaf_CopyPhysicalMemory(physicalAddress, size, (void*)table)) return 0; } - AcpiTable* table = (AcpiTable*)malloc(size); - if(table) - cpu_memcpy(table, mappedTable, size); - - mahaf_UnmapPhysicalMemory((void*)mappedTable); return table; } @@ -175,7 +181,7 @@ struct RSDT u32 tables[1]; }; -// avoid std::map et al. because we are called before _cinit +// avoid std::map et al. because we may be called before _cinit static const AcpiTable** tables; static size_t numTables; diff --git a/source/lib/sysdep/win/aken/aken.cpp b/source/lib/sysdep/win/aken/aken.cpp index caa5a6e8d4..892b7efb22 100644 --- a/source/lib/sysdep/win/aken/aken.cpp +++ b/source/lib/sysdep/win/aken/aken.cpp @@ -193,6 +193,29 @@ static NTSTATUS AkenIoctlUnmap(PVOID buf, const ULONG inSize, ULONG& outSize) return ntStatus; } +static NTSTATUS AkenIoctlCopyPhysical(PVOID buf, const ULONG inSize, ULONG& outSize) +{ + if(inSize != sizeof(AkenCopyPhysicalIn) || outSize != 0) + return STATUS_BUFFER_TOO_SMALL; + + const AkenCopyPhysicalIn* in = (const AkenCopyPhysicalIn*)buf; + PHYSICAL_ADDRESS physicalAddress; + physicalAddress.QuadPart = in->physicalAddress; + const ULONG numBytes = (ULONG)in->numBytes; + void* userBuffer = (void*)(UINT_PTR)in->userAddress; + + PVOID kernelBuffer = MmMapIoSpace(physicalAddress, numBytes, MmNonCached); + if(!kernelBuffer) + return STATUS_NO_MEMORY; + + // (this works because we're called in the user's context) + RtlCopyMemory(userBuffer, kernelBuffer, numBytes); + + MmUnmapIoSpace(kernelBuffer, numBytes); + + return STATUS_SUCCESS; +} + static NTSTATUS AkenIoctlUnknown(PVOID buf, const ULONG inSize, ULONG& outSize) { KdPrint(("AkenIoctlUnknown\n")); @@ -219,6 +242,9 @@ static inline AkenIoctl AkenIoctlFromCode(ULONG ioctlCode) case IOCTL_AKEN_UNMAP: return AkenIoctlUnmap; + case IOCTL_AKEN_COPY_PHYSICAL: + return AkenIoctlCopyPhysical; + default: return AkenIoctlUnknown; } diff --git a/source/lib/sysdep/win/aken/aken.h b/source/lib/sysdep/win/aken/aken.h index a02dbcb440..c8da5fe811 100644 --- a/source/lib/sysdep/win/aken/aken.h +++ b/source/lib/sysdep/win/aken/aken.h @@ -25,6 +25,7 @@ #define IOCTL_AKEN_WRITE_PORT CTL_CODE(FILE_DEVICE_AKEN, AKEN_IOCTL+1, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AKEN_MAP CTL_CODE(FILE_DEVICE_AKEN, AKEN_IOCTL+2, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AKEN_UNMAP CTL_CODE(FILE_DEVICE_AKEN, AKEN_IOCTL+3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AKEN_COPY_PHYSICAL CTL_CODE(FILE_DEVICE_AKEN, AKEN_IOCTL+4, METHOD_BUFFERED, FILE_ANY_ACCESS) // input and output data structures for the IOCTLs @@ -67,6 +68,13 @@ struct AkenUnmapIn DWORD64 virtualAddress; }; +struct AkenCopyPhysicalIn +{ + DWORD64 physicalAddress; + DWORD64 numBytes; + DWORD64 userAddress; +}; + #pragma pack(pop) #endif // #ifndef INCLUDED_AKEN diff --git a/source/lib/sysdep/win/mahaf.cpp b/source/lib/sysdep/win/mahaf.cpp index 2a20218cd6..8d26651288 100644 --- a/source/lib/sysdep/win/mahaf.cpp +++ b/source/lib/sysdep/win/mahaf.cpp @@ -128,6 +128,26 @@ void mahaf_UnmapPhysicalMemory(void* virtualAddress) } +bool mahaf_CopyPhysicalMemory(uintptr_t physicalAddress, size_t numBytes, void* buffer) +{ + AkenCopyPhysicalIn in; + in.physicalAddress = (DWORD64)physicalAddress; + in.numBytes = (DWORD64)numBytes; + in.userAddress = (DWORD64)buffer; + + DWORD bytesReturned; + LPOVERLAPPED ovl = 0; // synchronous + BOOL ok = DeviceIoControl(hAken, (DWORD)IOCTL_AKEN_COPY_PHYSICAL, &in, sizeof(in), 0, 0, &bytesReturned, ovl); + if(!ok) + { + WARN_WIN32_ERR; + return false; + } + + return true; +} + + //----------------------------------------------------------------------------- // driver installation //----------------------------------------------------------------------------- @@ -195,13 +215,16 @@ static void StartDriver(const char* driverPathname) SC_HANDLE hService = OpenService(hSCM, AKEN_NAME, SERVICE_ALL_ACCESS); -#if 0 - // during development, we want to unload and re-create the - // service every time to ensure the newest build is used. - BOOL ok = CloseServiceHandle(hService); - WARN_IF_FALSE(ok); - hService = 0; - UninstallDriver(); +#if 1 + // during development, we want to ensure the newest build is used, so + // unload and re-create the service if it's running/installed. + if(hService) + { + BOOL ok = CloseServiceHandle(hService); + WARN_IF_FALSE(ok); + hService = 0; + UninstallDriver(); + } #endif // create service (note: this just enters the service into SCM's DB; diff --git a/source/lib/sysdep/win/mahaf.h b/source/lib/sysdep/win/mahaf.h index 12ed68987f..57e6f4185b 100644 --- a/source/lib/sysdep/win/mahaf.h +++ b/source/lib/sysdep/win/mahaf.h @@ -27,4 +27,9 @@ extern void mahaf_WritePort32(u16 port, u32 value); extern void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes); extern void mahaf_UnmapPhysicalMemory(void* virtualAddress); +/** + * @return false on failure (insufficient paged pool?) + **/ +extern bool mahaf_CopyPhysicalMemory(uintptr_t physicalAddress, size_t numBytes, void* buffer); + #endif // INCLUDED_MAHAF diff --git a/source/lib/sysdep/win/wdbg.cpp b/source/lib/sysdep/win/wdbg.cpp index 4b5e550c7e..9eae5fd723 100644 --- a/source/lib/sysdep/win/wdbg.cpp +++ b/source/lib/sysdep/win/wdbg.cpp @@ -11,16 +11,8 @@ #include "precompiled.h" #include "wdbg.h" -#include -#include -#include - #include "lib/bits.h" -#include "lib/posix/posix_pthread.h" -#include "lib/app_hooks.h" -#include "lib/sysdep/cpu.h" #include "win.h" -#include "wdbg_sym.h" #include "wutil.h" diff --git a/source/lib/sysdep/win/wseh.cpp b/source/lib/sysdep/win/wseh.cpp index 98f1f5f21b..85b1902481 100644 --- a/source/lib/sysdep/win/wseh.cpp +++ b/source/lib/sysdep/win/wseh.cpp @@ -22,6 +22,8 @@ # define NEED_COOKIE_INIT #endif +// note: several excellent references are pointed to by comments below. + //----------------------------------------------------------------------------- // analyze an exception (determine description and locus) @@ -292,6 +294,7 @@ unhandled SEH exceptions are caught: - with a vectored exception handler. this works across threads, but it's only available on WinXP (unacceptable). since it is called before __try blocks, we would receive expected/legitimate exceptions. + (see http://msdn.microsoft.com/msdnmag/issues/01/09/hood/default.aspx) - by setting the per-process unhandled exception filter. as above, this works across threads and is at least portable across Win32. unfortunately, some Win32 DLLs appear to register their own handlers, so this isn't reliable. @@ -306,7 +309,9 @@ dialog (it is able to jump directly to the offending code). wrapping all threads in a __try appears to be the best choice. unfortunately, we cannot retroactively install an SEH handler: the OS ensures SEH chain nodes are on the thread's stack (as defined by NT_TIB) in ascending order. -(the handler would also have to be marked via .safeseh, but that is doable) +(see http://www.microsoft.com/msj/0197/exception/exception.aspx) +the handler would also have to be marked via .safeseh, but that is doable +(see http://blogs.msdn.com/greggm/archive/2004/07/22/191544.aspx) consequently, we'll have to run within a __try; if the init code is to be covered, this must happen within the program entry point. @@ -321,6 +326,7 @@ C++ classes. this way is more reliable/documented, but has several drawbacks: - a new fat exception class would have to be created to hold the SEH exception information (e.g. CONTEXT for a stack trace), and - this information would not be available for C++ exceptions. +(see http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx) */ diff --git a/source/lib/sysdep/win/wstartup.cpp b/source/lib/sysdep/win/wstartup.cpp index 5ccb1a338f..4cb2ee31c7 100644 --- a/source/lib/sysdep/win/wstartup.cpp +++ b/source/lib/sysdep/win/wstartup.cpp @@ -87,13 +87,14 @@ application, not the CRT DLL.) // reference: see http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945__1 -EXTERN_C void wstartup_InitAndRegisterShutdown() +EXTERN_C int wstartup_InitAndRegisterShutdown() { winit_CallInitFunctions(); atexit(winit_CallShutdownFunctions); + return 0; } #pragma data_seg(".CRT$XIV") // after C init, after XIU ("User") block -EXTERN_C void(*wstartup_pInitAndRegisterShutdown)() = wstartup_InitAndRegisterShutdown; +EXTERN_C int(*wstartup_pInitAndRegisterShutdown)() = wstartup_InitAndRegisterShutdown; #pragma data_seg() #pragma comment(linker, "/include:_wstartup_pInitAndRegisterShutdown")