move keyboard and mouse out of HAL into a standalone ps2.sys driver, implement usb stack with xhci controller discovery, hid keyboard/mouse, and bulk-only mass storage, add pci msi support with capability chain walking and software irq vector allocation (slots 16-23), rewrite user virtual memory as a USER_VA_REGION descriptor arena with per-process ownership tracking and guard page support, replacing the old bump allocator and top-down image region, add MmCreateUserRegion/MmDestroyAllUserRegions so process teardown reclaims all user va in one pass, allocate a pool-backed shadow framebuffer in hal_screen to fix cursor tearing and scroll corruption, reserve ap trampoline page below 1mb in uefi bootloader before boot services exit, rewrite memset/memcpy/memmove/memcmp with __stosq/__movsq intrinsics, promote driver flag literals to macros and add multi-tu STANDALONE_DRIVERS table to build.c, split rtl8139/rtl816x into header+source, rename KbReadScancode to KbReadKey, improve page fault output with MmDebugDescribeAddress and user region dump, fix %p to %016llX throughout.
This commit is contained in:
1 parent
b970d7f59c
commit
b838f8d83d
130 files changed
+8137
-2932
No files matched your search
+157
-21
@@ -8,6 +8,16 @@
|
||||
#include <kernel/mm_virt.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
|
||||
#ifndef LDR_DEBUG_VERBOSE
|
||||
#define LDR_DEBUG_VERBOSE 0
|
||||
#endif
|
||||
|
||||
#if LDR_DEBUG_VERBOSE
|
||||
#define LdrDbg(...) DbgPrint(__VA_ARGS__)
|
||||
#else
|
||||
#define LdrDbg(...) ((void)0)
|
||||
#endif
|
||||
|
||||
int _stricmp(const char* a, const char* b);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -78,6 +88,42 @@ typedef struct {
|
||||
uint32_t Characteristics;
|
||||
} SECTION_HEADER;
|
||||
|
||||
static size_t KiAlignPeSize(size_t value) {
|
||||
return (value + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
}
|
||||
|
||||
static KSTATUS KiComputeRequiredImageSize(const PE_HEADER* pe, size_t fileSize, size_t* outSize) {
|
||||
if (!pe || !outSize) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
const OPT_HEADER64* opt = &pe->OptionalHeader;
|
||||
size_t required = KiAlignPeSize(opt->SizeOfImage);
|
||||
size_t headers = KiAlignPeSize(opt->SizeOfHeaders);
|
||||
if (headers > required) required = headers;
|
||||
|
||||
const SECTION_HEADER* sec = (const SECTION_HEADER*)((const uint8_t*)&pe->OptionalHeader + pe->SizeOfOptionalHeader);
|
||||
for (int i = 0; i < pe->NumberOfSections; i++) {
|
||||
size_t va = (size_t)sec[i].VirtualAddress;
|
||||
size_t virt = (size_t)sec[i].VirtualSize;
|
||||
size_t raw = (size_t)sec[i].SizeOfRawData;
|
||||
size_t span = virt ? virt : raw;
|
||||
if (raw > span) span = raw;
|
||||
if (!span) continue;
|
||||
|
||||
if (va > (size_t)-1 - span) return STATUS_NO_MEMORY;
|
||||
size_t end = KiAlignPeSize(va + span);
|
||||
if (end > required) required = end;
|
||||
|
||||
if (raw) {
|
||||
size_t rawBase = (size_t)sec[i].PointerToRawData;
|
||||
if (rawBase > fileSize || raw > fileSize - rawBase) return STATUS_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!required) return STATUS_FAILURE;
|
||||
*outSize = required;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t Characteristics;
|
||||
uint32_t TimeDateStamp;
|
||||
@@ -246,33 +292,77 @@ void* LdrGetExportForProcess(PROCESS* process, const char* moduleName, const cha
|
||||
}
|
||||
|
||||
size_t LdrGetImageSize(uintptr_t base) {
|
||||
if (!base) return 0;
|
||||
uint32_t peOffset = *(uint32_t *)(base + 0x3C);
|
||||
PE_HEADER* pe = (PE_HEADER *)(base + peOffset);
|
||||
if (pe->Signature != PE_SIGNATURE) return 0;
|
||||
return (size_t)pe->OptionalHeader.SizeOfImage;
|
||||
}
|
||||
|
||||
|
||||
static void KiFreeLoadedImage(uintptr_t imageBase, bool user) {
|
||||
if (!imageBase) return;
|
||||
size_t imageSize = LdrGetImageSize(imageBase);
|
||||
if (user) MmFreeUserImage((void*)imageBase, imageSize);
|
||||
else MmFreePool((void*)imageBase);
|
||||
size_t LdrGetMappedImageSize(PROCESS* process, uintptr_t base) {
|
||||
if (!base) return 0;
|
||||
if (process) {
|
||||
size_t regionSize = MmGetUserRegionSize(process, (const void*)base);
|
||||
if (regionSize) return regionSize;
|
||||
}
|
||||
size_t globalRegionSize = MmGetUserRegionSizeByBase((const void*)base);
|
||||
if (globalRegionSize) return globalRegionSize;
|
||||
return LdrGetImageSize(base);
|
||||
}
|
||||
|
||||
|
||||
KSTATUS LdrProtectImage(uintptr_t imageBase, bool user) {
|
||||
static void KiFreeLoadedImageForProcess(PROCESS* process, uintptr_t imageBase, bool user) {
|
||||
if (!imageBase) return;
|
||||
size_t imageSize = user ? LdrGetMappedImageSize(process, imageBase) : LdrGetImageSize(imageBase);
|
||||
if (user) MmFreeUserImageForProcess(process, (void*)imageBase, imageSize);
|
||||
else MmFreePool((void*)imageBase);
|
||||
}
|
||||
|
||||
static void KiFreeLoadedImage(uintptr_t imageBase, bool user) {
|
||||
KiFreeLoadedImageForProcess(KeGetCurrentProcess(), imageBase, user);
|
||||
}
|
||||
|
||||
|
||||
KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool user) {
|
||||
if (!imageBase) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
size_t mappedSize = user ? LdrGetMappedImageSize(process, imageBase) : LdrGetImageSize(imageBase);
|
||||
if (!mappedSize) return STATUS_FAILURE;
|
||||
|
||||
uint32_t peOffset = *(uint32_t *)(imageBase + 0x3C);
|
||||
if ((size_t)peOffset > mappedSize || mappedSize - (size_t)peOffset < sizeof(uint32_t) + 20)
|
||||
return STATUS_FAILURE;
|
||||
|
||||
PE_HEADER* pe = (PE_HEADER *)(imageBase + peOffset);
|
||||
if (pe->Signature != PE_SIGNATURE) return STATUS_FAILURE;
|
||||
|
||||
SECTION_HEADER* sec = (SECTION_HEADER *)((uint8_t *)&pe->OptionalHeader + pe->SizeOfOptionalHeader);
|
||||
size_t sectionTableOffset = (size_t)peOffset + 24u + (size_t)pe->SizeOfOptionalHeader;
|
||||
size_t sectionTableSize = (size_t)pe->NumberOfSections * sizeof(SECTION_HEADER);
|
||||
if (sectionTableOffset > mappedSize || sectionTableSize > mappedSize - sectionTableOffset)
|
||||
return STATUS_FAILURE;
|
||||
|
||||
SECTION_HEADER* sec = (SECTION_HEADER *)(imageBase + sectionTableOffset);
|
||||
for (int i = 0; i < pe->NumberOfSections; i++) {
|
||||
size_t protectSize = sec[i].VirtualSize ? sec[i].VirtualSize : sec[i].SizeOfRawData;
|
||||
if (!protectSize) continue;
|
||||
|
||||
uintptr_t secBase = imageBase + (uintptr_t)sec[i].VirtualAddress;
|
||||
uintptr_t secEnd = secBase + protectSize;
|
||||
uintptr_t mapEnd = imageBase + mappedSize;
|
||||
|
||||
if (secBase < imageBase || secBase >= mapEnd) {
|
||||
LdrDbg("LDR: protect skipping out-of-range section %d base=%016llx size=%llx image=%016llx mapped=%llx\n",
|
||||
i, (unsigned long long)secBase, (unsigned long long)protectSize,
|
||||
(unsigned long long)imageBase, (unsigned long long)mappedSize);
|
||||
continue;
|
||||
}
|
||||
if (secEnd < secBase) return STATUS_NO_MEMORY;
|
||||
if (secEnd > mapEnd) {
|
||||
LdrDbg("LDR: protect clamping section %d end=%016llx to mapEnd=%016llx\n",
|
||||
i, (unsigned long long)secEnd, (unsigned long long)mapEnd);
|
||||
protectSize = (size_t)(mapEnd - secBase);
|
||||
}
|
||||
|
||||
uint64_t prot = PAGE_PRESENT | (user ? PAGE_USER : 0);
|
||||
if (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)
|
||||
prot |= PAGE_WRITE;
|
||||
@@ -280,12 +370,27 @@ KSTATUS LdrProtectImage(uintptr_t imageBase, bool user) {
|
||||
(sec[i].Characteristics & IMAGE_SCN_CNT_CODE)))
|
||||
prot |= PAGE_NX;
|
||||
|
||||
KSTATUS s = MmSetPageProtect(imageBase + sec[i].VirtualAddress, protectSize, prot);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
KSTATUS s;
|
||||
if (user) {
|
||||
s = MmProtectUserRegion(process, (void*)secBase, protectSize, prot);
|
||||
} else {
|
||||
s = MmSetPageProtect(secBase, protectSize, prot);
|
||||
}
|
||||
if (!KSUCCESS(s)) {
|
||||
LdrDbg("LDR: protect failed section=%d va=%016llx size=%llx prot=%016llx st=%d image=%016llx mapped=%llx\n",
|
||||
i, (unsigned long long)secBase, (unsigned long long)protectSize,
|
||||
(unsigned long long)prot, s,
|
||||
(unsigned long long)imageBase, (unsigned long long)mappedSize);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS LdrProtectImage(uintptr_t imageBase, bool user) {
|
||||
return LdrProtectImageForProcess(user ? (PROCESS*)0 : (PROCESS*)0, imageBase, user);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Entry point lookup
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -368,6 +473,7 @@ static KSTATUS LdrResolveImportsCommon(
|
||||
|
||||
//Compatibility remap.
|
||||
dllName = KiCanonicalModuleName(dllName);
|
||||
LdrDbg("LDR: resolve import dll=%s image=%016llx pid=%u\n", dllName, (unsigned long long)imageBase, process ? process->ProcessId : 0);
|
||||
|
||||
//
|
||||
// Ensure dependency is loaded into the process
|
||||
@@ -469,7 +575,7 @@ static KSTATUS LdrRegisterProcessModule(PROCESS* process, const char* name, uint
|
||||
strncpy(mod->Name, name, 31);
|
||||
mod->Name[31] = '\0';
|
||||
mod->Base = base;
|
||||
mod->Size = LdrGetImageSize(base);
|
||||
mod->Size = LdrGetMappedImageSize(process, base);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -500,6 +606,7 @@ KSTATUS LdrLoadModuleForProcess(PROCESS* process, const char* filename, uintptr_
|
||||
}
|
||||
|
||||
uint64_t fileSize = IoGetFileSize(f);
|
||||
LdrDbg("LDR: load module pid=%u file=%s size=%llu\n", process->ProcessId, filename, fileSize);
|
||||
void* mem = MmAllocatePool((size_t)fileSize);
|
||||
if (!mem) {
|
||||
IoCloseFile(f);
|
||||
@@ -515,39 +622,45 @@ KSTATUS LdrLoadModuleForProcess(PROCESS* process, const char* filename, uintptr_
|
||||
}
|
||||
|
||||
uintptr_t imageBase = 0;
|
||||
s = LdrLoadImage(mem, (size_t)fileSize, &imageBase, true);
|
||||
s = LdrLoadImageForProcess(process, mem, (size_t)fileSize, &imageBase);
|
||||
MmFreePool(mem);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("LDR: load image for module %s failed st=%d\n", filename, s);
|
||||
return s;
|
||||
}
|
||||
LdrDbg("LDR: module mapped pid=%u file=%s base=%016llx size=%llx\n",
|
||||
process->ProcessId, filename, (unsigned long long)imageBase, (unsigned long long)LdrGetMappedImageSize(process, imageBase));
|
||||
|
||||
|
||||
s = LdrResolveImportsForProcess(process, imageBase);
|
||||
if (!KSUCCESS(s)) {
|
||||
KiFreeLoadedImage(imageBase, true);
|
||||
KiFreeLoadedImageForProcess(process, imageBase, true);
|
||||
return s;
|
||||
}
|
||||
|
||||
s = LdrProtectImage(imageBase, true);
|
||||
s = LdrProtectImageForProcess(process, imageBase, true);
|
||||
if (!KSUCCESS(s)) {
|
||||
KiFreeLoadedImage(imageBase, true);
|
||||
KiFreeLoadedImageForProcess(process, imageBase, true);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
s = LdrRegisterProcessModule(process, filename, imageBase);
|
||||
if (!KSUCCESS(s)) {
|
||||
KiFreeLoadedImage(imageBase, true);
|
||||
KiFreeLoadedImageForProcess(process, imageBase, true);
|
||||
return s;
|
||||
}
|
||||
|
||||
LdrDbg("LDR: module registered pid=%u name=%s base=%016llx modules=%u\n",
|
||||
process->ProcessId, filename, (unsigned long long)imageBase, process->ModuleCount);
|
||||
if (baseOut) *baseOut = imageBase;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// LdrLoadImage - load a PE from a raw buffer into virtual space.
|
||||
KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool user) {
|
||||
static KSTATUS KiLdrLoadImageCommon(PROCESS* process, const void* buffer, size_t size, uintptr_t* baseOut, bool user) {
|
||||
if (!buffer || !size || !baseOut) return STATUS_INVALID_PARAMETER;
|
||||
if (user && !process) return STATUS_INVALID_PARAMETER;
|
||||
if (size < 0x40) return STATUS_FAILURE;
|
||||
|
||||
const uint8_t* bytes = (const uint8_t*)buffer;
|
||||
@@ -579,10 +692,23 @@ KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool u
|
||||
|
||||
PE_HEADER* pe = (PE_HEADER *)(bytes + peOffset);
|
||||
OPT_HEADER64* opt = &pe->OptionalHeader;
|
||||
size_t imageSize = opt->SizeOfImage;
|
||||
size_t imageSize = 0;
|
||||
KSTATUS sizeStatus = KiComputeRequiredImageSize(pe, size, &imageSize);
|
||||
if (!KSUCCESS(sizeStatus)) return sizeStatus;
|
||||
|
||||
void* mem = user ? MmAllocateUserImage(imageSize) : MmAllocatePool(imageSize);
|
||||
if (!mem) return STATUS_NO_MEMORY;
|
||||
LdrDbg("LDR: image header sizeOfImage=%x required=%llx preferred=%016llx sections=%u user=%d pid=%u\n",
|
||||
opt->SizeOfImage,
|
||||
(unsigned long long)imageSize,
|
||||
(unsigned long long)opt->ImageBase,
|
||||
pe->NumberOfSections,
|
||||
user ? 1 : 0,
|
||||
process ? process->ProcessId : 0);
|
||||
void* mem = user ? MmAllocateUserImageForProcess(process, imageSize) : MmAllocatePool(imageSize);
|
||||
if (!mem) {
|
||||
DbgPrint("LDR: image allocation failed required=%llx user=%d pid=%u\n",
|
||||
(unsigned long long)imageSize, user ? 1 : 0, process ? process->ProcessId : 0);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
memset(mem, 0, imageSize);
|
||||
|
||||
memcpy(mem, buffer, opt->SizeOfHeaders);
|
||||
@@ -591,7 +717,9 @@ KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool u
|
||||
void* dst = (uint8_t *)mem + sec[i].VirtualAddress;
|
||||
const void* src = (const uint8_t *)buffer + sec[i].PointerToRawData;
|
||||
if (sec[i].SizeOfRawData) {
|
||||
memcpy(dst, src, sec[i].SizeOfRawData < sec[i].VirtualSize ? sec[i].SizeOfRawData : sec[i].VirtualSize);
|
||||
size_t copySize = sec[i].SizeOfRawData;
|
||||
if (sec[i].VirtualSize && sec[i].VirtualSize < copySize) copySize = sec[i].VirtualSize;
|
||||
memcpy(dst, src, copySize);
|
||||
}
|
||||
|
||||
uint64_t prot = PAGE_PRESENT | PAGE_WRITE | (user ? PAGE_USER : 0);
|
||||
@@ -608,3 +736,11 @@ KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool u
|
||||
*baseOut = (uintptr_t)mem;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS LdrLoadImageForProcess(PROCESS* process, const void* buffer, size_t size, uintptr_t* baseOut) {
|
||||
return KiLdrLoadImageCommon(process, buffer, size, baseOut, true);
|
||||
}
|
||||
|
||||
KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool user) {
|
||||
return KiLdrLoadImageCommon(user ? KeGetCurrentProcess() : (PROCESS*)0, buffer, size, baseOut, user);
|
||||
}
|
||||
Reference in new issue
Block a user