1
1
forked from 0ad/0ad

manual build.

aken: add provision for copying physical memory (safer than mapping)
acpi uses that to avoid problems due to nonaligned ACPI tables (bonus:
wastes less memory)

wdbg: remove unnecessary headers
wseh: add comments
wstartup: fix return type (since we're now called by _initterm_e)

This was SVN commit r5159.
This commit is contained in:
janwas 2007-06-10 13:25:09 +00:00
parent a3c21bdfa4
commit 3e874c54cf
12 changed files with 101 additions and 34 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -11,16 +11,8 @@
#include "precompiled.h"
#include "wdbg.h"
#include <stdlib.h>
#include <stdio.h>
#include <typeinfo>
#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"

View File

@ -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)
*/

View File

@ -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")