- This gets us as far as 24061(+24048) for booting.
svn path=/trunk/; revision=24078
return (PVOID)NULL;
}
-/*++
-* @name LdrpSetProtection
-*
-* Local routine, used to set or reset pages protection.
-* Used during PE relocation process.
-*
-* @param BaseAddress
-* Base address of the image.
-*
-* @param Protection
-* FALSE to disable protection, TRUE to enable it
-*
-* @return Usual NTSTATUS.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-LdrpSetProtection(IN PVOID BaseAddress,
- IN BOOLEAN Protection)
-{
- PIMAGE_NT_HEADERS NtHeaders;
- PIMAGE_SECTION_HEADER SectionHeader;
- ULONG i;
- PVOID Address;
- SIZE_T Size;
- NTSTATUS Status;
- ULONG NewAccess, OldAccess;
- NtHeaders = RtlImageNtHeader(BaseAddress);
+/**********************************************************************
+ * NAME LOCAL
+ * LdrPerformRelocations
+ *
+ * DESCRIPTION
+ * Relocate a DLL's memory image.
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ *
+ * NOTE
+ *
+ */
+static NTSTATUS
+LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
+ PVOID ImageBase)
+{
+ PIMAGE_DATA_DIRECTORY RelocationDDir;
+ PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
+ ULONG Count, ProtectSize, OldProtect, OldProtect2;
+ PVOID Page, ProtectPage, ProtectPage2;
+ PUSHORT TypeOffset;
+ ULONG_PTR Delta;
+ NTSTATUS Status;
- /* Ensure image is valid */
- if (NtHeaders == NULL)
- return STATUS_INVALID_IMAGE_FORMAT;
+ if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
- /* Get the first section header */
- SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
+ RelocationDDir =
+ &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
- /* Loop through every section */
- for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++)
+ if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
{
- /* If section has no data - just skip to the next section */
- if (SectionHeader->SizeOfRawData == 0)
- continue;
+ return STATUS_SUCCESS;
+ }
- /* We need to act only if section isn't RW */
- if (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))
+ ProtectSize = PAGE_SIZE;
+ Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
+ RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
+ RelocationDDir->VirtualAddress);
+ RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
+ RelocationDDir->VirtualAddress + RelocationDDir->Size);
+
+ while (RelocationDir < RelocationEnd &&
+ RelocationDir->SizeOfBlock > 0)
+ {
+ Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
+ sizeof(USHORT);
+ Page = (PVOID)((ULONG_PTR)ImageBase + (ULONG_PTR)RelocationDir->VirtualAddress);
+ TypeOffset = (PUSHORT)(RelocationDir + 1);
+
+ /* Unprotect the page(s) we're about to relocate. */
+ ProtectPage = Page;
+ Status = NtProtectVirtualMemory(NtCurrentProcess(),
+ &ProtectPage,
+ &ProtectSize,
+ PAGE_READWRITE,
+ &OldProtect);
+ if (!NT_SUCCESS(Status))
{
- if (Protection)
- {
- /* Check if the section was also executable, then we should
- give it PAGE_EXECUTE, otherwise just PAGE_READONLY */
- NewAccess = (SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ? PAGE_EXECUTE : PAGE_READONLY;
+ DPRINT1("Failed to unprotect relocation target.\n");
+ return Status;
+ }
- /* Also check caching */
- NewAccess |= (SectionHeader->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) ? PAGE_NOCACHE : 0;
- }
- else
+ if (RelocationDir->VirtualAddress + PAGE_SIZE <
+ NTHeaders->OptionalHeader.SizeOfImage)
+ {
+ ProtectPage2 = (PVOID)((ULONG_PTR)ProtectPage + PAGE_SIZE);
+ Status = NtProtectVirtualMemory(NtCurrentProcess(),
+ &ProtectPage2,
+ &ProtectSize,
+ PAGE_READWRITE,
+ &OldProtect2);
+ if (!NT_SUCCESS(Status))
{
- /* Set access to RW */
- NewAccess = PAGE_READWRITE;
+ DPRINT1("Failed to unprotect relocation target (2).\n");
+ NtProtectVirtualMemory(NtCurrentProcess(),
+ &ProtectPage,
+ &ProtectSize,
+ OldProtect,
+ &OldProtect);
+ return Status;
}
+ }
+ else
+ {
+ ProtectPage2 = NULL;
+ }
- /* Get the address and size of the section, and set protectin accordingly */
- Address = (PVOID)((ULONG_PTR)BaseAddress + SectionHeader->VirtualAddress);
- Size = SectionHeader->SizeOfRawData;
-
- Status = NtProtectVirtualMemory(NtCurrentProcess(),
- &Address,
- &Size,
- NewAccess,
- &OldAccess);
-
- if (!NT_SUCCESS(Status))
- return Status;
+ RelocationDir = LdrProcessRelocationBlock((ULONG_PTR)Page,
+ Count,
+ TypeOffset,
+ Delta);
+ if (RelocationDir == NULL)
+ return STATUS_UNSUCCESSFUL;
+
+ /* Restore old page protection. */
+ NtProtectVirtualMemory(NtCurrentProcess(),
+ &ProtectPage,
+ &ProtectSize,
+ OldProtect,
+ &OldProtect);
+
+ if (ProtectPage2 != NULL)
+ {
+ NtProtectVirtualMemory(NtCurrentProcess(),
+ &ProtectPage2,
+ &ProtectSize,
+ OldProtect2,
+ &OldProtect2);
}
}
- /* Instruction cache should be flushed if we enabled protection */
- if (Protection)
- NtFlushInstructionCache(NtCurrentProcess(), NULL, 0);
-
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
static NTSTATUS
if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
{
DPRINT("LDR: Performing relocations\n");
-
- /* Remove protection */
- Status = LdrpSetProtection(ImageBase, FALSE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("LdrpSetProtection() failed with Status=0x%08X\n", Status);
- return NULL;
- }
-
- /* Relocate */
- Status = LdrRelocateImageWithBias(ImageBase, 0, "", STATUS_SUCCESS,
- STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("LdrRelocateImageWithBias() failed with Status=0x%08X\n", Status);
- return NULL;
- }
-
- /* Set protection back */
- Status = LdrpSetProtection(ImageBase, TRUE);
+ Status = LdrPerformRelocations(NTHeaders, ImageBase);
if (!NT_SUCCESS(Status))
{
- DPRINT1("LdrpSetProtection() failed with Status=0x%08X\n", Status);
+ DPRINT1("LdrPerformRelocations() failed\n");
return NULL;
}
-
}
if (Module != NULL)
{
DPRINT1("Relocating (%lx -> %p) %wZ\n",
NtHeaders->OptionalHeader.ImageBase, ImageBase, &FullDosName);
-
- Status = LdrRelocateImageWithBias(ImageBase, 0, "", STATUS_SUCCESS,
- STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
-
+ Status = LdrPerformRelocations(NtHeaders, ImageBase);
if (!NT_SUCCESS(Status))
{
- DPRINT1("LdrRelocateImageWithBias() failed\n");
+ DPRINT1("LdrPerformRelocations() failed\n");
NtUnmapViewOfSection (NtCurrentProcess (), ImageBase);
NtClose (SectionHandle);
RtlFreeUnicodeString(&FullDosName);
* FILE: lib/rtl/image.c
* PURPOSE: Image handling functions
* Relocate functions were previously located in
- * ntoskrnl/ldr/loader.c and
- * dll/ntdll/ldr/utils.c files
- * PROGRAMMER: Eric Kohl + original authors from loader.c and utils.c file
- * Aleksey Bragin
+ * ntoskrnl/ldr/loader.c
+ * PROGRAMMER: Eric Kohl + original authors from loader.c file
*/
/* INCLUDES *****************************************************************/
(ULONG_PTR)Section->VirtualAddress);
}
-PIMAGE_BASE_RELOCATION
-LdrProcessRelocationBlockLongLong(
- IN ULONG_PTR Address,
- IN ULONG Count,
- IN PUSHORT TypeOffset,
- IN LONGLONG Delta
- )
-{
- SHORT Offset;
- USHORT Type;
- USHORT i;
- PUSHORT ShortPtr;
- PULONG LongPtr;
-
- for (i = 0; i < Count; i++)
- {
- Offset = *TypeOffset & 0xFFF;
- Type = *TypeOffset >> 12;
- ShortPtr = (PUSHORT)(RVA(Address, Offset));
-
- /*
- * Don't relocate within the relocation section itself.
- * GCC/LD generates sometimes relocation records for the relocation section.
- * This is a bug in GCC/LD.
- * Fix for it disabled, since it was only in ntoskrnl and not in ntdll
- */
- /*
- if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
- (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
- {*/
- switch (Type)
- {
- /* case IMAGE_REL_BASED_SECTION : */
- /* case IMAGE_REL_BASED_REL32 : */
- case IMAGE_REL_BASED_ABSOLUTE:
- break;
-
- case IMAGE_REL_BASED_HIGH:
- *ShortPtr += HIWORD(Delta);
- break;
-
- case IMAGE_REL_BASED_LOW:
- *ShortPtr += LOWORD(Delta);
- break;
-
- case IMAGE_REL_BASED_HIGHLOW:
- LongPtr = (PULONG)RVA(Address, Offset);
- *LongPtr += Delta;
- break;
-
- case IMAGE_REL_BASED_HIGHADJ:
- case IMAGE_REL_BASED_MIPS_JMPADDR:
- default:
- DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
- DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
- return (PIMAGE_BASE_RELOCATION)NULL;
- }
-
- TypeOffset++;
- }
-
- return (PIMAGE_BASE_RELOCATION)TypeOffset;
-}
-
ULONG
NTAPI
LdrRelocateImageWithBias(
IN PVOID BaseAddress,
IN LONGLONG AdditionalBias,
- IN PCCH LoaderName,
+ IN PCCH LoaderName,
IN ULONG Success,
IN ULONG Conflict,
IN ULONG Invalid
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_DATA_DIRECTORY RelocationDDir;
PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
- ULONG Count;
- ULONG_PTR Address;
+ ULONG Count, i;
+ PVOID Address;//, MaxAddress;
PUSHORT TypeOffset;
- LONGLONG Delta;
+ ULONG_PTR Delta;
+ SHORT Offset;
+ USHORT Type;
+ PUSHORT ShortPtr;
+ PULONG LongPtr;
NtHeaders = RtlImageNtHeader(BaseAddress);
Delta = (ULONG_PTR)BaseAddress - NtHeaders->OptionalHeader.ImageBase + AdditionalBias;
RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + RelocationDDir->VirtualAddress);
RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
+ //MaxAddress = RVA(BaseAddress, DriverSize);
while (RelocationDir < RelocationEnd &&
RelocationDir->SizeOfBlock > 0)
{
Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
- Address = (ULONG_PTR)RVA(BaseAddress, RelocationDir->VirtualAddress);
+ Address = RVA(BaseAddress, RelocationDir->VirtualAddress);
TypeOffset = (PUSHORT)(RelocationDir + 1);
- RelocationDir = LdrProcessRelocationBlockLongLong(Address,
- Count,
- TypeOffset,
- Delta);
-
- if (RelocationDir == NULL)
+ for (i = 0; i < Count; i++)
{
- DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");
- return Invalid;
+ Offset = *TypeOffset & 0xFFF;
+ Type = *TypeOffset >> 12;
+ ShortPtr = (PUSHORT)(RVA(Address, Offset));
+
+ /* Don't relocate after the end of the loaded driver */
+ /*if ((PVOID)ShortPtr >= MaxAddress)
+ {
+ break;
+ }*/
+
+ /*
+ * Don't relocate within the relocation section itself.
+ * GCC/LD generates sometimes relocation records for the relocation section.
+ * This is a bug in GCC/LD.
+ */
+ if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
+ (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
+ {
+ switch (Type)
+ {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ break;
+
+ case IMAGE_REL_BASED_HIGH:
+ *ShortPtr += HIWORD(Delta);
+ break;
+
+ case IMAGE_REL_BASED_LOW:
+ *ShortPtr += LOWORD(Delta);
+ break;
+
+ case IMAGE_REL_BASED_HIGHLOW:
+ LongPtr = (PULONG)ShortPtr;
+ *LongPtr += Delta;
+ break;
+
+ case IMAGE_REL_BASED_HIGHADJ:
+ case IMAGE_REL_BASED_MIPS_JMPADDR:
+ default:
+ DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
+ DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
+ return Invalid;
+ }
+ }
+ TypeOffset++;
}
+ RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
}
return Success;
-#ifndef __NTOSKRNL_INCLUDE_INTERNAL_PO_H
-#define __NTOSKRNL_INCLUDE_INTERNAL_PO_H
+/*
+* PROJECT: ReactOS Kernel
+* LICENSE: GPL - See COPYING in the top level directory
+* FILE: ntoskrnl/include/po.h
+* PURPOSE: Internal header for the Power Manager
+* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+*/
-extern PDEVICE_NODE PopSystemPowerDeviceNode;
+//
+// Define this if you want debugging support
+//
+#define _PO_DEBUG_ 0x00
+
+//
+// These define the Debug Masks Supported
+//
+#define PO_STATE_DEBUG 0x01
+//
+// Debug/Tracing support
+//
+#if _PO_DEBUG_
+#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
+#define POTRACE DbgPrintEx
+#else
+#define POTRACE(x, ...) \
+ if (x & PopTraceLevel) DbgPrint(__VA_ARGS__)
+#endif
+#else
+#define POTRACE(x, ...) DPRINT(__VA_ARGS__)
+#endif
+
+//
+// Initialization routines
+//
VOID
NTAPI
PoInit(
- PROS_LOADER_PARAMETER_BLOCK LoaderBlock,
+ PROS_LOADER_PARAMETER_BLOCK LoaderBlock,
BOOLEAN ForceAcpiDisable
);
+VOID
+NTAPI
+PoInitializePrcb(
+ IN PKPRCB Prcb
+);
+
+//
+// Power State routines
+//
NTSTATUS
NTAPI
PopSetSystemPowerState(
IN PPOWER_STATE PowerState
);
-VOID
-NTAPI
-PoInitializePrcb(
- IN PKPRCB Prcb
-);
-
-#endif /* __NTOSKRNL_INCLUDE_INTERNAL_PO_H */
+//
+// Global data inside the Power Manager
+//
+extern PDEVICE_NODE PopSystemPowerDeviceNode;
Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE;\r
Thread->KernelStackResident = TRUE;\r
\r
+ /* ROS Mm HACK */\r
+ MmUpdatePageDir((PEPROCESS)Process,\r
+ (PVOID)Thread->StackLimit,\r
+ KERNEL_STACK_SIZE);\r
+ MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));\r
+\r
/* Enter SEH to avoid crashes due to user mode */\r
Status = STATUS_SUCCESS;\r
_SEH_TRY\r
KiIdleSummary |= Affinity;\r
}\r
\r
+ MmUpdatePageDir((PEPROCESS)PsGetCurrentProcess(),((PETHREAD)CurrentThread)->ThreadsProcess, sizeof(EPROCESS));\r
+\r
/* Special note for Filip: This will release the Dispatcher DB Lock ;-) -- Alex */\r
DPRINT("You are : %x, swapping to: %x.\n", OldThread, CurrentThread);\r
ApcState = KiSwapContext(OldThread, CurrentThread);\r