/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
-#define NDEBUG
+//#define NDEBUG
#include <debug.h>
+#ifdef _M_PPC
+#include <ppcmmu/mmu.h>
+#define KERNEL_RVA(x) RVA(x,0x80800000)
+#define KERNEL_DESCRIPTOR_PAGE(x) (((ULONG_PTR)(x) + KernelBase) >> PAGE_SHIFT)
+#else
+#define KERNEL_RVA(x) RVA(x,KSEG0_BASE)
+#define KERNEL_DESCRIPTOR_PAGE(x) (((ULONG_PTR)(x) & ~KSEG0_BASE) >> PAGE_SHIFT)
+#endif
+
+typedef struct _BIOS_MEMORY_DESCRIPTOR
+{
+ ULONG BlockBase;
+ ULONG BlockSize;
+} BIOS_MEMORY_DESCRIPTOR, *PBIOS_MEMORY_DESCRIPTOR;
+
/* GLOBALS *******************************************************************/
-/* FreeLDR Module Data */
-LOADER_MODULE KeLoaderModules[64];
-ULONG KeLoaderModuleCount;
-static CHAR KeLoaderModuleStrings[64][256];
-PLOADER_MODULE CachedModules[MaximumCachedModuleType];
+/* Function pointer for early debug prints */
+ULONG (*FrLdrDbgPrint)(const char *Format, ...);
-/* FreeLDR Memory Data */
+/* FreeLDR Loader Data */
+PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
+BOOLEAN AcpiTableDetected = FALSE;
ADDRESS_RANGE KeMemoryMap[64];
ULONG KeMemoryMapRangeCount;
-ULONG_PTR FirstKrnlPhysAddr;
-ULONG_PTR LastKrnlPhysAddr;
-ULONG_PTR LastKernelAddress;
-ULONG MmFreeLdrMemHigher, MmFreeLdrMemLower;
-ULONG MmFreeLdrPageDirectoryStart, MmFreeLdrPageDirectoryEnd;
-/* FreeLDR Loader Data */
-ROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
-static CHAR KeLoaderCommandLine[256];
-BOOLEAN AcpiTableDetected;
+/* NT Loader Module/Descriptor Count */
+ULONG BldrCurrentMd;
+ULONG BldrCurrentMod;
+
+/* NT Loader Data. Eats up about 100KB! */
+LOADER_PARAMETER_BLOCK BldrLoaderBlock; // 0x0000
+LOADER_PARAMETER_EXTENSION BldrExtensionBlock; // 0x0060
+CHAR BldrCommandLine[256]; // 0x00DC
+CHAR BldrArcBootPath[64]; // 0x01DC
+CHAR BldrArcHalPath[64]; // 0x021C
+CHAR BldrNtHalPath[64]; // 0x025C
+CHAR BldrNtBootPath[64]; // 0x029C
+LDR_DATA_TABLE_ENTRY BldrModules[64]; // 0x02DC
+MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors[60]; // 0x14DC
+WCHAR BldrModuleStrings[64][260]; // 0x19DC
+WCHAR BldrModuleStringsFull[64][260]; // 0x9BDC
+NLS_DATA_BLOCK BldrNlsDataBlock; // 0x11DDC
+SETUP_LOADER_BLOCK BldrSetupBlock; // 0x11DE8
+ARC_DISK_INFORMATION BldrArcDiskInfo; // 0x12134
+CHAR BldrArcNames[32][256]; // 0x1213C
+ARC_DISK_SIGNATURE BldrDiskInfo[32]; // 0x1413C
+CHAR BldrArcHwBuffer[16 * 1024]; // 0x1843C
-/* FreeLDR PE Hack Data */
-extern unsigned int _image_base__;
-ULONG_PTR KERNEL_BASE = (ULONG_PTR)&_image_base__;
-extern LDR_DATA_TABLE_ENTRY HalModuleObject;
+/* BIOS Memory Map */
+BIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptors[16] = { { 0, 0 }, };
+PBIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptorList = BiosMemoryDescriptors;
-/* NT Loader Data */
-LOADER_PARAMETER_BLOCK BldrLoaderBlock;
-CHAR BldrCommandLine[256];
+/* ARC Memory Map */
+ULONG NumberDescriptors = 0;
+MEMORY_DESCRIPTOR MDArray[60] = { { 0, 0, 0 }, };
/* FUNCTIONS *****************************************************************/
+PMEMORY_ALLOCATION_DESCRIPTOR
+NTAPI
+KiRosGetMdFromArray(VOID)
+{
+ /* Return the next MD from the list, but make sure we don't overflow */
+ if (BldrCurrentMd > 60) ASSERT(FALSE);
+ return &BldrMemoryDescriptors[BldrCurrentMd++];
+}
+
VOID
NTAPI
-KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
- IN PLOADER_PARAMETER_BLOCK *NtLoaderBlock)
+KiRosAddBiosBlock(ULONG Address,
+ ULONG Size)
{
- PLOADER_PARAMETER_BLOCK LoaderBlock;
+ PBIOS_MEMORY_DESCRIPTOR BiosBlock = BiosMemoryDescriptorList;
- /* First get some kernel-loader globals */
- AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
- MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
- MmFreeLdrMemLower = RosLoaderBlock->MemLower;
- MmFreeLdrPageDirectoryStart = RosLoaderBlock->PageDirectoryStart;
- MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
- KeLoaderModuleCount = RosLoaderBlock->ModsCount;
+ /* Loop our BIOS Memory Descriptor List */
+ while (BiosBlock->BlockSize > 0)
+ {
+ /* Check if we've found a matching head block */
+ if (Address + Size == BiosBlock->BlockBase)
+ {
+ /* Simply enlarge and rebase it */
+ BiosBlock->BlockBase = Address;
+ BiosBlock->BlockSize += Size;
+ break;
+ }
- /* Set the NT Loader block and initialize it */
- *NtLoaderBlock = LoaderBlock = &BldrLoaderBlock;
- RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+ /* Check if we've found a matching tail block */
+ if (Address == (BiosBlock->BlockBase + BiosBlock->BlockSize))
+ {
+ /* Simply enlarge it */
+ BiosBlock->BlockSize += Size;
+ break;
+ }
- /* Setup the list heads */
- InitializeListHead(&LoaderBlock->LoadOrderListHead);
- InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
- InitializeListHead(&LoaderBlock->BootDriverListHead);
+ /* Nothing suitable found, try the next block */
+ BiosBlock++;
+ }
- /* Setup command line */
- LoaderBlock->LoadOptions = BldrCommandLine;
- strcpy(BldrCommandLine, KeLoaderCommandLine);
+ /* No usable blocks found, found a free block instead */
+ if (!BiosBlock->BlockSize)
+ {
+ /* Write our data */
+ BiosBlock->BlockBase = Address;
+ BiosBlock->BlockSize = Size;
+
+ /* Create a new block and mark it as the end of the array */
+ BiosBlock++;
+ BiosBlock->BlockBase = BiosBlock->BlockSize = 0L;
+ }
}
VOID
NTAPI
-KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
+KiRosBuildBiosMemoryMap(VOID)
+{
+ ULONG BlockBegin, BlockEnd;
+ ULONG j;
+
+ /* Loop the BIOS Memory Map */
+ for (j = 0; j < KeMemoryMapRangeCount; j++)
+ {
+ /* Get the start and end addresses */
+ BlockBegin = KeMemoryMap[j].BaseAddrLow;
+ BlockEnd = KeMemoryMap[j].BaseAddrLow + KeMemoryMap[j].LengthLow - 1;
+
+ /* Make sure this isn't a > 4GB descriptor */
+ if (!KeMemoryMap[j].BaseAddrHigh)
+ {
+ /* Make sure we don't overflow */
+ if (BlockEnd < BlockBegin) BlockEnd = 0xFFFFFFFF;
+
+ /* Check if this is free memory */
+ if (KeMemoryMap[j].Type == 1)
+ {
+ /* Add it to our BIOS descriptors */
+ KiRosAddBiosBlock(BlockBegin, BlockEnd - BlockBegin + 1);
+ }
+ }
+ }
+}
+
+NTSTATUS
+NTAPI
+KiRosAllocateArcDescriptor(IN ULONG PageBegin,
+ IN ULONG PageEnd,
+ IN MEMORY_TYPE MemoryType)
{
ULONG i;
- ULONG size;
- ULONG HalBase;
- ULONG DriverBase;
- ULONG DriverSize;
- PIMAGE_NT_HEADERS NtHeader;
- PIMAGE_OPTIONAL_HEADER OptHead;
- PLOADER_PARAMETER_BLOCK NtLoaderBlock;
- CHAR* s;
- /* Load the GDT and IDT */
- Ke386SetGlobalDescriptorTable(KiGdtDescriptor);
- Ke386SetInterruptDescriptorTable(KiIdtDescriptor);
-
- /* Copy the Loader Block Data locally since Low-Memory will be wiped */
- memcpy(&KeRosLoaderBlock, LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK));
- memcpy(&KeLoaderModules[1],
- (PVOID)KeRosLoaderBlock.ModsAddr,
- sizeof(LOADER_MODULE) * KeRosLoaderBlock.ModsCount);
- KeRosLoaderBlock.ModsCount++;
- KeRosLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
-
- /* Check for BIOS memory map */
- KeMemoryMapRangeCount = 0;
- if (KeRosLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
+ /* Loop all our descriptors */
+ for (i = 0; i < NumberDescriptors; i++)
{
- /* We have a memory map from the nice BIOS */
- size = *((PULONG)(KeRosLoaderBlock.MmapAddr - sizeof(ULONG)));
- i = 0;
+ /* Attempt to fing a free block that describes our region */
+ if ((MDArray[i].MemoryType == MemoryFree) &&
+ (MDArray[i].BasePage <= PageBegin) &&
+ (MDArray[i].BasePage + MDArray[i].PageCount > PageBegin) &&
+ (MDArray[i].BasePage + MDArray[i].PageCount >= PageEnd))
+ {
+ /* Found one! */
+ break;
+ }
+ }
- /* Map it until we run out of size */
- while (i < KeRosLoaderBlock.MmapLength)
+ /* Check if we found no free blocks, and fail if so */
+ if (i == NumberDescriptors) return ENOMEM;
+
+ /* Check if the block has our base address */
+ if (MDArray[i].BasePage == PageBegin)
+ {
+ /* Check if it also has our ending address */
+ if ((MDArray[i].BasePage + MDArray[i].PageCount) == PageEnd)
{
- /* Copy into the Kernel Memory Map */
- memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
- (PVOID)(KeRosLoaderBlock.MmapAddr + i),
- sizeof(ADDRESS_RANGE));
+ /* Then convert this region into our new memory type */
+ MDArray[i].MemoryType = MemoryType;
+ }
+ else
+ {
+ /* Otherwise, make sure we have enough descriptors */
+ if (NumberDescriptors == 60) return ENOMEM;
- /* Increase Memory Map Count */
- KeMemoryMapRangeCount++;
+ /* Cut this descriptor short */
+ MDArray[i].BasePage = PageEnd;
+ MDArray[i].PageCount -= (PageEnd - PageBegin);
- /* Increase Size */
- i += size;
+ /* And allocate a new descriptor for our memory range */
+ MDArray[NumberDescriptors].BasePage = PageBegin;
+ MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
+ MDArray[NumberDescriptors].MemoryType = MemoryType;
+ NumberDescriptors++;
}
+ }
+ else if ((MDArray[i].BasePage + MDArray[i].PageCount) == PageEnd)
+ {
+ /* This block has our end address, make sure we have a free block */
+ if (NumberDescriptors == 60) return ENOMEM;
- /* Save data */
- KeRosLoaderBlock.MmapLength = KeMemoryMapRangeCount *
- sizeof(ADDRESS_RANGE);
- KeRosLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
+ /* Rebase this descriptor */
+ MDArray[i].PageCount = PageBegin - MDArray[i].BasePage;
+
+ /* And allocate a new descriptor for our memory range */
+ MDArray[NumberDescriptors].BasePage = PageBegin;
+ MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
+ MDArray[NumberDescriptors].MemoryType = MemoryType;
+ NumberDescriptors++;
}
else
{
- /* Nothing from BIOS */
- KeRosLoaderBlock.MmapLength = 0;
- KeRosLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
+ /* We'll need two descriptors, make sure they're available */
+ if ((NumberDescriptors + 1) >= 60) return ENOMEM;
+
+ /* Allocate a free memory descriptor for what follows us */
+ MDArray[NumberDescriptors].BasePage = PageEnd;
+ MDArray[NumberDescriptors].PageCount = MDArray[i].PageCount -
+ (PageEnd - MDArray[i].BasePage);
+ MDArray[NumberDescriptors].MemoryType = MemoryFree;
+ NumberDescriptors++;
+
+ /* Cut down the current free descriptor */
+ MDArray[i].PageCount = PageBegin - MDArray[i].BasePage;
+
+ /* Allocate a new memory descriptor for our memory range */
+ MDArray[NumberDescriptors].BasePage = PageBegin;
+ MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
+ MDArray[NumberDescriptors].MemoryType = MemoryType;
+ NumberDescriptors++;
}
- /* Save the Base Address */
- MmSystemRangeStart = (PVOID)KeRosLoaderBlock.KernelBase;
+ /* Everything went well */
+ return STATUS_SUCCESS;
+}
- /* Set the Command Line */
- strcpy(KeLoaderCommandLine, (PCHAR)LoaderBlock->CommandLine);
- KeRosLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
+NTSTATUS
+NTAPI
+KiRosConfigureArcDescriptor(IN ULONG PageBegin,
+ IN ULONG PageEnd,
+ IN TYPE_OF_MEMORY MemoryType)
+{
+ ULONG i;
+ ULONG BlockBegin, BlockEnd;
+ MEMORY_TYPE BlockType;
+ BOOLEAN Combined = FALSE;
+
+ /* If this descriptor seems bogus, just return */
+ if (PageEnd <= PageBegin) return STATUS_SUCCESS;
+
+ /* Loop every ARC descriptor, trying to find one we can modify */
+ for (i = 0; i < NumberDescriptors; i++)
+ {
+ /* Get its settings */
+ BlockBegin = MDArray[i].BasePage;
+ BlockEnd = MDArray[i].BasePage + MDArray[i].PageCount;
+ BlockType = MDArray[i].MemoryType;
+
+ /* Check if we can fit inside this block */
+ if (BlockBegin < PageBegin)
+ {
+ /* Check if we are larger then it */
+ if ((BlockEnd > PageBegin) && (BlockEnd <= PageEnd))
+ {
+ /* Make it end where we start */
+ BlockEnd = PageBegin;
+ }
+
+ /* Check if it ends after we do */
+ if (BlockEnd > PageEnd)
+ {
+ /* Make sure we can allocate a descriptor */
+ if (NumberDescriptors == 60) return ENOMEM;
+
+ /* Create a descriptor for whatever memory we're not part of */
+ MDArray[NumberDescriptors].MemoryType = BlockType;
+ MDArray[NumberDescriptors].BasePage = PageEnd;
+ MDArray[NumberDescriptors].PageCount = BlockEnd - PageEnd;
+ NumberDescriptors++;
+
+ /* The next block ending is now where we begin */
+ BlockEnd = PageBegin;
+ }
+ }
+ else
+ {
+ /* Check if the blog begins inside our range */
+ if (BlockBegin < PageEnd)
+ {
+ /* Check if it ends before we do */
+ if (BlockEnd < PageEnd)
+ {
+ /* Then make it disappear */
+ BlockEnd = BlockBegin;
+ }
+ else
+ {
+ /* Otherwise make it start where we end */
+ BlockBegin = PageEnd;
+ }
+ }
+ }
+
+ /* Check if the block matches us, and we haven't tried combining yet */
+ if (((TYPE_OF_MEMORY)BlockType == MemoryType) && !(Combined))
+ {
+ /* Check if it starts where we end */
+ if (BlockBegin == PageEnd)
+ {
+ /* Make it start with us, and combine us */
+ BlockBegin = PageBegin;
+ Combined = TRUE;
+ }
+ else if (BlockEnd == PageBegin)
+ {
+ /* Otherwise, it ends where we begin, combine its ending */
+ BlockEnd = PageEnd;
+ Combined = TRUE;
+ }
+ }
- /* Write the first Module (the Kernel) */
- strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
- KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
- KeLoaderModules[0].ModStart = KERNEL_BASE;
+ /* Check the original block data matches with what we came up with */
+ if ((MDArray[i].BasePage == BlockBegin) &&
+ (MDArray[i].PageCount == BlockEnd - BlockBegin))
+ {
+ /* Then skip it */
+ continue;
+ }
- /* Read PE Data */
- NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
- OptHead = &NtHeader->OptionalHeader;
+ /* Otherwise, set our new settings for this block */
+ MDArray[i].BasePage = BlockBegin;
+ MDArray[i].PageCount = BlockEnd - BlockBegin;
- /* Set Kernel Ending */
- KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart +
- PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
+ /* Check if we are killing the block */
+ if (BlockBegin == BlockEnd)
+ {
+ /* Delete this block and restart the loop properly */
+ NumberDescriptors--;
+ if (i < NumberDescriptors) MDArray[i] = MDArray[NumberDescriptors];
+ i--;
+ }
+ }
- /* Create a block for each module */
- for (i = 1; i < KeRosLoaderBlock.ModsCount; i++)
+ /* If we got here without combining, we need to allocate a new block */
+ if (!(Combined) && (MemoryType < LoaderMaximum))
{
- /* Check if we have to copy the path or not */
- if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0)
+ /* Make sure there's enough descriptors */
+ if (NumberDescriptors == 60) return ENOMEM;
+
+ /* Allocate a new block with our data */
+ MDArray[NumberDescriptors].MemoryType = MemoryType;
+ MDArray[NumberDescriptors].BasePage = PageBegin;
+ MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
+ NumberDescriptors++;
+ }
+
+ /* Changes complete, return success */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+KiRosBuildOsMemoryMap(VOID)
+{
+ PBIOS_MEMORY_DESCRIPTOR MdBlock;
+ ULONG BlockStart, BlockEnd, BiasedStart, BiasedEnd, PageStart, PageEnd;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG BiosPage = 0xA0;
+
+ /* Loop the BIOS Memory Descriptor List */
+ MdBlock = BiosMemoryDescriptorList;
+ while (MdBlock->BlockSize)
+ {
+ /* Get the statrt and end addresses */
+ BlockStart = MdBlock->BlockBase;
+ BlockEnd = BlockStart + MdBlock->BlockSize - 1;
+
+ /* Align them to page boundaries */
+ BiasedStart = BlockStart & (PAGE_SIZE - 1);
+ if (BiasedStart) BlockStart = BlockStart + PAGE_SIZE - BiasedStart;
+ BiasedEnd = (BlockEnd + 1) & (ULONG)(PAGE_SIZE - 1);
+ if (BiasedEnd) BlockEnd -= BiasedEnd;
+
+ /* Get the actual page numbers */
+ PageStart = BlockStart >> PAGE_SHIFT;
+ PageEnd = (BlockEnd + 1) >> PAGE_SHIFT;
+
+ /* If we're starting at page 0, then put the BIOS page at the end */
+ if (!PageStart) BiosPage = PageEnd;
+
+ /* Check if we did any alignment */
+ if (BiasedStart)
{
- strcpy(KeLoaderModuleStrings[i], s + 1);
+ /* Mark that region as reserved */
+ Status = KiRosConfigureArcDescriptor(PageStart - 1,
+ PageStart,
+ MemorySpecialMemory);
+ if (Status != STATUS_SUCCESS) break;
+ }
+
+ /* Check if we did any alignment */
+ if (BiasedEnd)
+ {
+ /* Mark that region as reserved */
+ Status = KiRosConfigureArcDescriptor(PageEnd - 1,
+ PageEnd,
+ MemorySpecialMemory);
+ if (Status != STATUS_SUCCESS) break;
+
+ /* If the bios page was the last page, use the next one instead */
+ if (BiosPage == PageEnd) BiosPage += 1;
+ }
+
+ /* Check if the page is below the 16MB Memory hole */
+ if (PageEnd <= 0xFC0)
+ {
+ /* It is, mark the memory a free */
+ Status = KiRosConfigureArcDescriptor(PageStart,
+ PageEnd,
+ LoaderFree);
+ }
+ else if (PageStart >= 0x1000)
+ {
+ /* It's over 16MB, so that memory gets marked as reserve */
+ Status = KiRosConfigureArcDescriptor(PageStart,
+ PageEnd,
+ LoaderFree);
}
else
{
- strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
+ /* Check if it starts below the memory hole */
+ if (PageStart < 0xFC0)
+ {
+ /* Mark that part as free */
+ Status = KiRosConfigureArcDescriptor(PageStart,
+ 0xFC0,
+ MemoryFree);
+ if (Status != STATUS_SUCCESS) break;
+
+ /* And update the page start for the code below */
+ PageStart = 0xFC0;
+ }
+
+ /* Any code in the memory hole region ends up as reserve */
+ Status = KiRosConfigureArcDescriptor(PageStart,
+ PageEnd,
+ LoaderFree);
}
- /* Substract the base Address in Physical Memory */
- KeLoaderModules[i].ModStart -= 0x200000;
+ /* If we failed, break out, otherwise, go to the next BIOS block */
+ if (Status != STATUS_SUCCESS) break;
+ MdBlock++;
+ }
+
+ /* If anything failed until now, return error code */
+ if (Status != STATUS_SUCCESS) return Status;
- /* Add the Kernel Base Address in Virtual Memory */
- KeLoaderModules[i].ModStart += KERNEL_BASE;
+#ifdef _M_IX86
+ /* Set the top 16MB region as reserved */
+ Status = KiRosConfigureArcDescriptor(0xFC0, 0x1000, MemorySpecialMemory);
+ if (Status != STATUS_SUCCESS) return Status;
- /* Substract the base Address in Physical Memory */
- KeLoaderModules[i].ModEnd -= 0x200000;
+ /* Setup the BIOS region as reserved */
+ KiRosConfigureArcDescriptor(0xA0, 0x100, LoaderMaximum);
+ KiRosConfigureArcDescriptor(BiosPage, 0x100, MemoryFirmwarePermanent);
- /* Add the Kernel Base Address in Virtual Memory */
- KeLoaderModules[i].ModEnd += KERNEL_BASE;
+ /* Build an entry for the IVT */
+ Status = KiRosAllocateArcDescriptor(0, 1, MemoryFirmwarePermanent);
+ if (Status != STATUS_SUCCESS) return Status;
+#endif
- /* Select the proper String */
- KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
+ /* Build an entry for the KPCR and KUSER_SHARED_DATA */
+ Status = KiRosAllocateArcDescriptor(1, 3, LoaderStartupPcrPage);
+ if (Status != STATUS_SUCCESS) return Status;
+
+ /* Build an entry for the PDE and return the status */
+ Status = KiRosAllocateArcDescriptor(KeRosLoaderBlock->
+ PageDirectoryStart >> PAGE_SHIFT,
+ KeRosLoaderBlock->
+ PageDirectoryEnd >> PAGE_SHIFT,
+ LoaderMemoryData);
+ return Status;
+}
+
+VOID
+NTAPI
+KiRosBuildReservedMemoryMap(VOID)
+{
+ ULONG j;
+ ULONG BlockBegin, BlockEnd, BiasedPage;
+
+ /* Loop the BIOS Memory Map */
+ for (j = 0; j < KeMemoryMapRangeCount; j++)
+ {
+ /* Get the start and end addresses */
+ BlockBegin = KeMemoryMap[j].BaseAddrLow;
+ BlockEnd = BlockBegin + KeMemoryMap[j].LengthLow - 1;
+
+ /* Make sure it wasn't a > 4GB descriptor */
+ if (!KeMemoryMap[j].BaseAddrHigh)
+ {
+ /* Make sure it doesn't overflow */
+ if (BlockEnd < BlockBegin) BlockEnd = 0xFFFFFFFF;
+
+ /* Check if this was free memory */
+ if (KeMemoryMap[j].Type == 1)
+ {
+ /* Get the page-aligned addresses */
+ BiasedPage = BlockBegin & (PAGE_SIZE - 1);
+ BlockBegin >>= PAGE_SHIFT;
+ if (BiasedPage) BlockBegin++;
+ BlockEnd = (BlockEnd >> PAGE_SHIFT) + 1;
+
+ /* Check if the block is within the 16MB memory hole */
+ if ((BlockBegin < 0xFC0) && (BlockEnd >= 0xFC0))
+ {
+ /* Don't allow it to cross this boundary */
+ BlockBegin = 0xFC0;
+ }
+
+ /* Check if the boundary is across 16MB */
+ if ((BlockEnd > 0xFFF) && (BlockBegin <= 0xFFF))
+ {
+ /* Don't let it cross */
+ BlockEnd = 0xFFF;
+ }
+
+ /* Check if the block describes the memory hole */
+ if ((BlockBegin >= 0xFC0) && (BlockEnd <= 0xFFF))
+ {
+ /* Set this region as temporary */
+ KiRosConfigureArcDescriptor(BlockBegin,
+ BlockEnd,
+ MemoryFirmwareTemporary);
+ }
+ }
+ else
+ {
+ /* Get the page-aligned addresses */
+ BlockBegin >>= PAGE_SHIFT;
+ BiasedPage = (BlockEnd + 1) & (PAGE_SIZE - 1);
+ BlockEnd >>= PAGE_SHIFT;
+ if (BiasedPage) BlockEnd++;
+
+ /* Set this memory as reserved */
+ KiRosConfigureArcDescriptor(BlockBegin,
+ BlockEnd + 1,
+ MemorySpecialMemory);
+ }
+ }
}
+}
- /* Choose last module address as the final kernel address */
- LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeRosLoaderBlock.
- ModsCount - 1].ModEnd);
+VOID
+NTAPI
+KiRosInsertNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
+{
+ PLIST_ENTRY ListHead, PreviousEntry, NextEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor = NULL, NextDescriptor = NULL;
- /* Select the HAL Base */
- HalBase = KeLoaderModules[1].ModStart;
+ /* Loop the memory descriptor list */
+ ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
+ PreviousEntry = ListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current descriptor and check if it's below ours */
+ NextDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+ if (NewDescriptor->BasePage < NextDescriptor->BasePage) break;
- /* Choose Driver Base */
- DriverBase = LastKernelAddress;
- LdrHalBase = (ULONG_PTR)DriverBase;
+ /* It isn't, save the previous entry and descriptor, and try again */
+ PreviousEntry = NextEntry;
+ Descriptor = NextDescriptor;
+ NextEntry = NextEntry->Flink;
+ }
- /* Initialize Module Management */
- LdrInitModuleManagement();
+ /* So we found the right spot to insert. Is this free memory? */
+ if (NewDescriptor->MemoryType != LoaderFree)
+ {
+ /* It isn't, so insert us before the last descriptor */
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
+ }
+ else
+ {
+ /* We're free memory. Check if the entry we found is also free memory */
+ if ((PreviousEntry != ListHead) &&
+ ((Descriptor->MemoryType == LoaderFree) ||
+ (Descriptor->MemoryType == LoaderReserve)) &&
+ ((Descriptor->BasePage + Descriptor->PageCount) ==
+ NewDescriptor->BasePage))
+ {
+ /* It's free memory, and we're right after it. Enlarge that block */
+ Descriptor->PageCount += NewDescriptor->PageCount;
+ NewDescriptor = Descriptor;
+ }
+ else
+ {
+ /* Our range scan't be combined, so just insert us separately */
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
+ }
- /* Load HAL.DLL with the PE Loader */
- LdrSafePEProcessModule((PVOID)HalBase,
- (PVOID)DriverBase,
- (PVOID)KERNEL_BASE,
- &DriverSize);
+ /* Check if we merged with an existing free memory block */
+ if ((NextEntry != ListHead) &&
+ ((NextDescriptor->MemoryType == LoaderFree) ||
+ (NextDescriptor->MemoryType == LoaderReserve)) &&
+ ((NewDescriptor->BasePage + NewDescriptor->PageCount) ==
+ NextDescriptor->BasePage))
+ {
+ /* Update our own block */
+ NewDescriptor->PageCount += NextDescriptor->PageCount;
+ /* Remove the next block */
+ RemoveEntryList(&NextDescriptor->ListEntry);
+ }
+ }
+}
+
+NTSTATUS
+NTAPI
+KiRosBuildNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor,
+ IN MEMORY_TYPE MemoryType,
+ IN ULONG BasePage,
+ IN ULONG PageCount)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor, NextDescriptor = NULL;
+ LONG Delta;
+ TYPE_OF_MEMORY CurrentType;
+ BOOLEAN UseNext;
+
+ /* Check how many pages we'll be consuming */
+ Delta = BasePage - MemoryDescriptor->BasePage;
+ if (!(Delta) && (PageCount == MemoryDescriptor->PageCount))
+ {
+ /* We can simply convert the current descriptor into our new type */
+ MemoryDescriptor->MemoryType = MemoryType;
+ }
+ else
+ {
+ /* Get the current memory type of the descriptor, and reserve it */
+ CurrentType = MemoryDescriptor->MemoryType;
+ MemoryDescriptor->MemoryType = LoaderSpecialMemory;
+
+ /* Check if we'll need another descriptor for what's left of memory */
+ UseNext = ((BasePage != MemoryDescriptor->BasePage) &&
+ (Delta + PageCount != MemoryDescriptor->PageCount));
+
+ /* Get a descriptor */
+ Descriptor = KiRosGetMdFromArray();
+ if (!Descriptor) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Check if we are using another descriptor */
+ if (UseNext)
+ {
+ /* Allocate that one too */
+ NextDescriptor = KiRosGetMdFromArray();
+ if (!NextDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Build the descriptor we got */
+ Descriptor->MemoryType = MemoryType;
+ Descriptor->BasePage = BasePage;
+ Descriptor->PageCount = PageCount;
+
+ /* Check if we're starting at the same place as the old one */
+ if (BasePage == MemoryDescriptor->BasePage)
+ {
+ /* Simply decrease the old descriptor and rebase it */
+ MemoryDescriptor->BasePage += PageCount;
+ MemoryDescriptor->PageCount -= PageCount;
+ MemoryDescriptor->MemoryType = CurrentType;
+ }
+ else if (Delta + PageCount == MemoryDescriptor->PageCount)
+ {
+ /* We finish where the old one did, shorten it */
+ MemoryDescriptor->PageCount -= PageCount;
+ MemoryDescriptor->MemoryType = CurrentType;
+ }
+ else
+ {
+ /* We're inside the current block, mark our free region */
+ NextDescriptor->MemoryType = LoaderFree;
+ NextDescriptor->BasePage = BasePage + PageCount;
+ NextDescriptor->PageCount = MemoryDescriptor->PageCount -
+ (PageCount + Delta);
+
+ /* And cut down the current descriptor */
+ MemoryDescriptor->PageCount = Delta;
+ MemoryDescriptor->MemoryType = CurrentType;
+
+ /* Finally, insert our new free descriptor into the list */
+ KiRosInsertNtDescriptor(NextDescriptor);
+ }
+
+ /* Insert the descriptor we allocated */
+ KiRosInsertNtDescriptor(Descriptor);
+ }
+
+ /* Return success */
+ return STATUS_SUCCESS;
+}
+
+PMEMORY_ALLOCATION_DESCRIPTOR
+NTAPI
+KiRosFindNtDescriptor(IN ULONG BasePage)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock = NULL;
+ PLIST_ENTRY NextEntry, ListHead;
+
+ /* Scan the memory descriptor list */
+ ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current descriptor */
+ MdBlock = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Check if it can contain our memory range */
+ if ((MdBlock->BasePage <= BasePage) &&
+ (MdBlock->BasePage + MdBlock->PageCount > BasePage))
+ {
+ /* It can, break out */
+ break;
+ }
+
+ /* Go to the next descriptor */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Return the descriptor we found, if any */
+ return MdBlock;
+}
+
+NTSTATUS
+NTAPI
+KiRosAllocateNtDescriptor(IN TYPE_OF_MEMORY MemoryType,
+ IN ULONG BasePage,
+ IN ULONG PageCount,
+ IN ULONG Alignment,
+ OUT PULONG ReturnedBase)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
+ ULONG AlignedBase, AlignedLimit;
+ PMEMORY_ALLOCATION_DESCRIPTOR ActiveMdBlock;
+ ULONG ActiveAlignedBase = 0;
+ PLIST_ENTRY NextEntry, ListHead;
+
+ /* If no information was given, make some assumptions */
+ if (!Alignment) Alignment = 1;
+ if (!PageCount) PageCount = 1;
+
+ /* Start looking for a matching descvriptor */
+ do
+ {
+ /* Calculate the limit of the range */
+ AlignedLimit = PageCount + BasePage;
+
+ /* Find a descriptor that already contains our base address */
+ MdBlock = KiRosFindNtDescriptor(BasePage);
+
+ if (MdBlock)
+ {
+ /* If it contains our limit as well, break out early */
+ if ((MdBlock->PageCount + MdBlock->BasePage) >= AlignedLimit) break;
+ }
+
+ /* Loop the memory list */
+ ActiveMdBlock = NULL;
+ ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current descriptors */
+ MdBlock = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Align the base address and our limit */
+ AlignedBase = (MdBlock->BasePage + (Alignment - 1)) &~ Alignment;
+ AlignedLimit = MdBlock->PageCount -
+ AlignedBase +
+ MdBlock->BasePage;
+
+ /* Check if this is a free block that can satisfy us */
+ if ((MdBlock->MemoryType == LoaderFree) &&
+ (AlignedLimit <= MdBlock->PageCount) &&
+ (PageCount <= AlignedLimit))
+ {
+ /* It is, stop searching */
+ ActiveMdBlock = MdBlock;
+ ActiveAlignedBase = AlignedBase;
+ break;
+ }
+
+ /* Try the next block */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* See if we came up with an adequate block */
+ if (ActiveMdBlock)
+ {
+ /* Generate a descriptor in it */
+ *ReturnedBase = AlignedBase;
+ return KiRosBuildNtDescriptor(ActiveMdBlock,
+ MemoryType,
+ ActiveAlignedBase,
+ PageCount);
+ }
+ } while (TRUE);
+
+ /* We found a matching block, generate a descriptor with it */
+ *ReturnedBase = BasePage;
+ return KiRosBuildNtDescriptor(MdBlock, MemoryType, BasePage, PageCount);
+}
+
+NTSTATUS
+NTAPI
+KiRosBuildArcMemoryList(VOID)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ MEMORY_DESCRIPTOR *Memory;
+ ULONG i;
+
+ /* Loop all BIOS Memory Descriptors */
+ for (i = 0; i < NumberDescriptors; i++)
+ {
+ /* Get the current descriptor */
+ Memory = &MDArray[i];
+
+ /* Allocate an NT Memory Descriptor */
+ Descriptor = KiRosGetMdFromArray();
+ if (!Descriptor) return ENOMEM;
+
+ /* Copy the memory type */
+ Descriptor->MemoryType = Memory->MemoryType;
+ if (Memory->MemoryType == MemoryFreeContiguous)
+ {
+ /* Convert this to free */
+ Descriptor->MemoryType = LoaderFree;
+ }
+ else if (Memory->MemoryType == MemorySpecialMemory)
+ {
+ /* Convert this to special memory */
+ Descriptor->MemoryType = LoaderSpecialMemory;
+ }
+
+ /* Copy the range data */
+ Descriptor->BasePage = Memory->BasePage;
+ Descriptor->PageCount = Memory->PageCount;
+
+ /* Insert the descriptor */
+ if (Descriptor->PageCount) KiRosInsertNtDescriptor(Descriptor);
+ }
+
+ /* All went well */
+ return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+KiRosFixupComponentTree(IN PCONFIGURATION_COMPONENT_DATA p,
+ IN ULONG_PTR i)
+{
+ PCONFIGURATION_COMPONENT pp;
+
+ /* Loop each entry */
+ while (p)
+ {
+ /* Grab the component entry */
+ pp = &p->ComponentEntry;
+
+ /* Fixup the pointers */
+ if (pp->Identifier) pp->Identifier = (PVOID)((ULONG_PTR)pp->Identifier + i);
+ if (p->ConfigurationData) p->ConfigurationData = (PVOID)((ULONG_PTR)p->ConfigurationData + i);
+ if (p->Parent) p->Parent = (PVOID)((ULONG_PTR)p->Parent + i);
+ if (p->Sibling) p->Sibling = (PVOID)((ULONG_PTR)p->Sibling + i);
+ if (p->Child) p->Child = (PVOID)((ULONG_PTR)p->Child + i);
+
+ /* Check if we have a child */
+ if (p->Child) KiRosFixupComponentTree(p->Child, i);
+
+ /* Get to the next entry */
+ p = p->Sibling;
+ }
+}
+
+VOID
+NTAPI
+KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
+ IN PLOADER_PARAMETER_BLOCK *NtLoaderBlock)
+{
+ PLOADER_PARAMETER_BLOCK LoaderBlock;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ PLOADER_MODULE RosEntry = NULL;
+ ULONG i, j, ModSize;
+ PVOID ModStart;
+ PCHAR DriverName;
+ PCHAR BootPath, HalPath;
+ CHAR CommandLine[256];
+ PARC_DISK_SIGNATURE RosDiskInfo, ArcDiskInfo;
+ PIMAGE_NT_HEADERS NtHeader;
+ WCHAR PathToDrivers[] = L"\\SystemRoot\\System32\\drivers\\";
+ WCHAR PathToSystem32[] = L"\\SystemRoot\\System32\\";
+ WCHAR PathSetup[] = L"\\SystemRoot\\";
+ CHAR DriverNameLow[256];
+ ULONG Base;
+#ifdef _M_PPC
+ ULONG KernelBase = RosLoaderBlock->ModsAddr[0].ModStart;
+#endif
+
+ /* First get some kernel-loader globals */
+ AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
+
+ /* Set the NT Loader block and initialize it */
+ *NtLoaderBlock = KeLoaderBlock = LoaderBlock = &BldrLoaderBlock;
+ RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+
+ /* Set the NLS Data block */
+ LoaderBlock->NlsData = &BldrNlsDataBlock;
+
+ /* Set the ARC Data block */
+ LoaderBlock->ArcDiskInformation = &BldrArcDiskInfo;
+
+ /* Assume this is from FreeLDR's SetupLdr */
+ LoaderBlock->SetupLdrBlock = &BldrSetupBlock;
+
+ /* Setup the list heads */
+ InitializeListHead(&LoaderBlock->LoadOrderListHead);
+ InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
+ InitializeListHead(&LoaderBlock->BootDriverListHead);
+ InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
+
+ /* Build the free memory map, which uses BIOS Descriptors */
+ KiRosBuildBiosMemoryMap();
+
+ /* Build entries for ReactOS memory ranges, which uses ARC Descriptors */
+ KiRosBuildOsMemoryMap();
+
+#if defined(_M_IX86) || defined(_M_AMD64)
+ /* Build entries for the reserved map, which uses ARC Descriptors */
+ KiRosBuildReservedMemoryMap();
+#endif
+
+ /* Now convert the BIOS and ARC Descriptors into NT Memory Descirptors */
+ KiRosBuildArcMemoryList();
+
+ /* Loop boot driver list */
+ for (i = 0; i < RosLoaderBlock->ModsCount; i++)
+ {
+ /* Get the ROS loader entry */
+ RosEntry = &RosLoaderBlock->ModsAddr[i];
+ DriverName = (PCHAR)RosEntry->String;
+ ModStart = (PVOID)RosEntry->ModStart;
+ ModSize = RosEntry->ModEnd - (ULONG_PTR)ModStart;
+
+#ifdef _M_PPC
+ ModStart -= KernelBase;
+#endif
+
+ /* Check if this is any of the NLS files */
+ if (!_stricmp(DriverName, "ansi.nls"))
+ {
+ /* ANSI Code page */
+ LoaderBlock->NlsData->AnsiCodePageData = KERNEL_RVA(ModStart);
+
+ /* Create an MD for it */
+ KiRosAllocateNtDescriptor(LoaderNlsData,
+ KERNEL_DESCRIPTOR_PAGE(ModStart),
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
+ continue;
+ }
+ else if (!_stricmp(DriverName, "oem.nls"))
+ {
+ /* OEM Code page */
+ LoaderBlock->NlsData->OemCodePageData = KERNEL_RVA(ModStart);
+
+ /* Create an MD for it */
+ KiRosAllocateNtDescriptor(LoaderNlsData,
+ KERNEL_DESCRIPTOR_PAGE(ModStart),
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
+ continue;
+ }
+ else if (!_stricmp(DriverName, "casemap.nls"))
+ {
+ /* Unicode Code page */
+ LoaderBlock->NlsData->UnicodeCodePageData = KERNEL_RVA(ModStart);
+
+ /* Create an MD for it */
+ KiRosAllocateNtDescriptor(LoaderNlsData,
+ KERNEL_DESCRIPTOR_PAGE(ModStart),
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
+ continue;
+ }
+
+ /* Check if this is the SYSTEM hive */
+ if (!(_stricmp(DriverName, "system")) ||
+ !(_stricmp(DriverName, "system.hiv")))
+ {
+ /* Save registry data */
+ LoaderBlock->RegistryBase = KERNEL_RVA(ModStart);
+ LoaderBlock->RegistryLength = ModSize;
+
+ /* Disable setup mode */
+ LoaderBlock->SetupLdrBlock = NULL;
+
+ /* Create an MD for it */
+ KiRosAllocateNtDescriptor(LoaderRegistryData,
+ KERNEL_DESCRIPTOR_PAGE(ModStart),
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
+ continue;
+ }
+
+ /* Check if this is the HARDWARE hive */
+ if (!(_stricmp(DriverName, "hardware")) ||
+ !(_stricmp(DriverName, "hardware.hiv")))
+ {
+ /* Create an MD for it */
+ KiRosAllocateNtDescriptor(LoaderRegistryData,
+ KERNEL_DESCRIPTOR_PAGE(ModStart),
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
+ continue;
+ }
+
+ /* Check if this is the kernel */
+ if (!(_stricmp(DriverName, "ntoskrnl.exe")))
+ {
+ /* Create an MD for it */
+ KiRosAllocateNtDescriptor(LoaderSystemCode,
+ KERNEL_DESCRIPTOR_PAGE(ModStart),
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
+ }
+ else if (!(_stricmp(DriverName, "hal.dll")))
+ {
+ /* Create an MD for the HAL */
+ KiRosAllocateNtDescriptor(LoaderHalCode,
+ KERNEL_DESCRIPTOR_PAGE(ModStart),
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
+ }
+ else
+ {
+ /* Create an MD for any driver */
+ KiRosAllocateNtDescriptor(LoaderBootDriver,
+ KERNEL_DESCRIPTOR_PAGE(ModStart),
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
+ }
+
+#ifdef _M_PPC
+ ModStart += 0x80800000;
+#endif
+
+ /* Lowercase the drivername so we can check its extension later */
+ strcpy(DriverNameLow, DriverName);
+ _strlwr(DriverNameLow);
+
+ /* Setup the loader entry */
+ LdrEntry = &BldrModules[i];
+ RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
+
+ /* Convert driver name from ANSI to Unicode */
+ for (j = 0; j < strlen(DriverName); j++)
+ {
+ BldrModuleStrings[i][j] = DriverName[j];
+ }
+
+ /* Setup driver name */
+ RtlInitUnicodeString(&LdrEntry->BaseDllName, BldrModuleStrings[i]);
+
+ /* Construct a correct full name */
+ BldrModuleStringsFull[i][0] = 0;
+ LdrEntry->FullDllName.MaximumLength = 260 * sizeof(WCHAR);
+ LdrEntry->FullDllName.Length = 0;
+ LdrEntry->FullDllName.Buffer = BldrModuleStringsFull[i];
+
+ /* Guess the path */
+ if (LoaderBlock->SetupLdrBlock)
+ {
+ UNICODE_STRING TempString;
+ RtlInitUnicodeString(&TempString, PathSetup);
+ RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &TempString);
+ }
+ else if (strstr(DriverNameLow, ".dll") || strstr(DriverNameLow, ".exe"))
+ {
+ UNICODE_STRING TempString;
+ RtlInitUnicodeString(&TempString, PathToSystem32);
+ RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &TempString);
+ }
+ else /* .sys */
+ {
+ UNICODE_STRING TempString;
+ RtlInitUnicodeString(&TempString, PathToDrivers);
+ RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &TempString);
+ }
+
+ /* Append base name of the driver */
+ RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &LdrEntry->BaseDllName);
+
+ /* Copy data from Freeldr Module Entry */
+ LdrEntry->DllBase = ModStart;
+ LdrEntry->SizeOfImage = ModSize;
+
+ /* Copy additional data */
+ NtHeader = RtlImageNtHeader(ModStart);
+ LdrEntry->EntryPoint = RVA(ModStart,
+ NtHeader->
+ OptionalHeader.AddressOfEntryPoint);
+
+ /* Initialize other data */
+ LdrEntry->LoadCount = 1;
+ LdrEntry->Flags = LDRP_IMAGE_DLL |
+ LDRP_ENTRY_PROCESSED;
+ if (RosEntry->Reserved) LdrEntry->Flags |= LDRP_ENTRY_INSERTED;
+
+ /* Insert it into the loader block */
+ InsertTailList(&LoaderBlock->LoadOrderListHead,
+ &LdrEntry->InLoadOrderLinks);
+ }
+
+ /* Now mark the remainder of the FreeLDR 6MB area as "in use" */
+ KiRosAllocateNtDescriptor(LoaderMemoryData,
+ KERNEL_DESCRIPTOR_PAGE(RosEntry->ModEnd),
+ KERNEL_DESCRIPTOR_PAGE((RosLoaderBlock->KernelBase + 0x600000)) -
+ KERNEL_DESCRIPTOR_PAGE(RosEntry->ModEnd),
+ 0,
+ &Base);
+
//
+ // Check if we have a ramdisk
//
- // HACK HACK HACK WHEN WILL YOU PEOPLE FIX FREELDR?!?!?!
- // FREELDR SENDS US AN ***INVALID*** HAL PE HEADER!!!
- // WE READ IT IN LdrInitModuleManagement ABOVE!!!
- // WE SET .SizeOfImage TO A *GARBAGE* VALUE!!!
- //
- // This dirty hack fixes it, and should make symbol lookup work too.
- //
- HalModuleObject.SizeOfImage = RtlImageNtHeader((PVOID)HalModuleObject.
- DllBase)->
- OptionalHeader.SizeOfImage;
+ if ((RosLoaderBlock->RdAddr) && (RosLoaderBlock->RdLength))
+ {
+ //
+ // Build a descriptor for it
+ //
+ KiRosAllocateNtDescriptor(LoaderXIPRom,
+ KERNEL_DESCRIPTOR_PAGE(RosLoaderBlock->RdAddr),
+ (RosLoaderBlock->RdLength + PAGE_SIZE - 1) >> PAGE_SHIFT,
+ 0,
+ &Base);
+ }
+
+ /* Setup command line */
+ LoaderBlock->LoadOptions = BldrCommandLine;
+ strcpy(BldrCommandLine, RosLoaderBlock->CommandLine);
+
+ /* Setup the extension block */
+ LoaderBlock->Extension = &BldrExtensionBlock;
+ LoaderBlock->Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
+ LoaderBlock->Extension->MajorVersion = 5;
+ LoaderBlock->Extension->MinorVersion = 2;
+
- /* Increase the last kernel address with the size of HAL */
- LastKernelAddress += PAGE_ROUND_UP(DriverSize);
+// FIXME FIXME FIXME NOW!!!!
- /* Now select the final beginning and ending Kernel Addresses */
- FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
- LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
+ /* FreeLDR hackllocates 1536 static pages for the initial boot images */
+ LoaderBlock->Extension->LoaderPagesSpanned = 1536 * PAGE_SIZE;
- /* Setup the IDT */
- KeInitExceptions(); // ONCE HACK BELOW IS GONE, MOVE TO KISYSTEMSTARTUP!
- KeInitInterrupts(); // ROS HACK DEPRECATED SOON BY NEW HAL
+ /* ReactOS always boots the kernel at 0x80800000 (just like NT 5.2) */
+ LoaderBlock->Extension->LoaderPagesSpanned += 0x80800000 - KSEG0_BASE;
+
+ /* Now convert to pages */
+ LoaderBlock->Extension->LoaderPagesSpanned /= PAGE_SIZE;
+
+ /* Now setup the setup block if we have one */
+ if (LoaderBlock->SetupLdrBlock)
+ {
+ /* All we'll setup right now is the flag for text-mode setup */
+ LoaderBlock->SetupLdrBlock->Flags = SETUPLDR_TEXT_MODE;
+ }
+
+ /* Make a copy of the command line */
+ strcpy(CommandLine, LoaderBlock->LoadOptions);
+
+ /* Find the first \, separating the ARC path from NT path */
+ BootPath = strchr(CommandLine, '\\');
+ *BootPath = ANSI_NULL;
+ strncpy(BldrArcBootPath, CommandLine, 63);
+ LoaderBlock->ArcBootDeviceName = BldrArcBootPath;
+
+ /* The rest of the string is the NT path */
+ HalPath = strchr(BootPath + 1, ' ');
+ *HalPath = ANSI_NULL;
+ BldrNtBootPath[0] = '\\';
+ strncat(BldrNtBootPath, BootPath + 1, 63);
+ strcat(BldrNtBootPath,"\\");
+ LoaderBlock->NtBootPathName = BldrNtBootPath;
+
+ /* Set the HAL paths */
+ strncpy(BldrArcHalPath, BldrArcBootPath, 63);
+ LoaderBlock->ArcHalDeviceName = BldrArcHalPath;
+ strcpy(BldrNtHalPath, "\\");
+ LoaderBlock->NtHalPathName = BldrNtHalPath;
+
+ /* Use this new command line */
+ strncpy(LoaderBlock->LoadOptions, HalPath + 2, 255);
+
+ /* Parse it and change every slash to a space */
+ BootPath = LoaderBlock->LoadOptions;
+ do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++);
+
+ /* Now let's loop ARC disk information */
+ for (i = 0; i < RosLoaderBlock->DrivesCount; i++)
+ {
+ /* Get the ROS loader entry */
+ RosDiskInfo = &RosLoaderBlock->DrivesAddr[i];
- /* Load the Kernel with the PE Loader */
- LdrSafePEProcessModule((PVOID)KERNEL_BASE,
- (PVOID)KERNEL_BASE,
- (PVOID)DriverBase,
- &DriverSize);
+ /* Get the ARC structure */
+ ArcDiskInfo = &BldrDiskInfo[i];
+
+ /* Copy the data over */
+ ArcDiskInfo->Signature = RosDiskInfo->Signature;
+ ArcDiskInfo->CheckSum = RosDiskInfo->CheckSum;
+
+ /* Copy the ARC Name */
+ strcpy(BldrArcNames[i], RosDiskInfo->ArcName);
+ ArcDiskInfo->ArcName = BldrArcNames[i];
+
+ /* Insert into the list */
+ InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead,
+ &ArcDiskInfo->ListEntry);
+ }
+
+ /* Copy the ARC Hardware Tree */
+ RtlCopyMemory(BldrArcHwBuffer, (PVOID)RosLoaderBlock->ArchExtra, 16 * 1024);
+ LoaderBlock->ConfigurationRoot = (PVOID)BldrArcHwBuffer;
+
+ /* Apply fixups */
+ KiRosFixupComponentTree(LoaderBlock->ConfigurationRoot,
+ (ULONG_PTR)BldrArcHwBuffer -
+ RosLoaderBlock->ArchExtra);
+}
+
+VOID
+NTAPI
+KiSetupSyscallHandler();
+
+VOID
+FASTCALL
+KiRosPrepareForSystemStartup(IN ULONG Dummy,
+ IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLOADER_PARAMETER_BLOCK NtLoaderBlock;
+ ULONG size, i = 0, *ent;
+#if defined(_M_IX86)
+ PKTSS Tss;
+ PKGDTENTRY TssEntry;
+
+ /* Load the GDT and IDT */
+ Ke386SetGlobalDescriptorTable(*(PKDESCRIPTOR)&KiGdtDescriptor.Limit);
+ Ke386SetInterruptDescriptorTable(*(PKDESCRIPTOR)&KiIdtDescriptor.Limit);
+
+ /* Initialize the boot TSS */
+ Tss = &KiBootTss;
+ TssEntry = &KiBootGdt[KGDT_TSS / sizeof(KGDTENTRY)];
+ TssEntry->HighWord.Bits.Type = I386_TSS;
+ TssEntry->HighWord.Bits.Pres = 1;
+ TssEntry->HighWord.Bits.Dpl = 0;
+ TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
+ TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
+ TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
+#endif
+
+#if defined(_M_PPC)
+ // Zero bats. We might have residual bats set that will interfere with
+ // our mapping of ofwldr.
+ for (i = 0; i < 4; i++)
+ {
+ SetBat(i, 0, 0, 0); SetBat(i, 1, 0, 0);
+ }
+ KiSetupSyscallHandler();
+ DbgPrint("Kernel Power (%08x)\n", LoaderBlock);
+ DbgPrint("ArchExtra (%08x)!\n", LoaderBlock->ArchExtra);
+#endif
+
+ /* Save pointer to ROS Block */
+ KeRosLoaderBlock = LoaderBlock;
+
+ /* Get debugging function */
+ FrLdrDbgPrint = LoaderBlock->FrLdrDbgPrint;
+
+ /* Save memory manager data */
+ KeMemoryMapRangeCount = 0;
+ if (LoaderBlock->Flags & MB_FLAGS_MMAP_INFO)
+ {
+ /* We have a memory map from the nice BIOS */
+ ent = ((PULONG)(LoaderBlock->MmapAddr - sizeof(ULONG))); // FIXME: this is ugly
+ size = *ent;
+ i = 0;
+
+ /* Map it until we run out of size */
+ while (i < LoaderBlock->MmapLength)
+ {
+ /* Copy into the Kernel Memory Map */
+ memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
+ (PVOID)(LoaderBlock->MmapAddr + i),
+ sizeof(ADDRESS_RANGE));
+
+ /* Increase Memory Map Count */
+ KeMemoryMapRangeCount++;
+
+ /* Increase Size */
+ i += size;
+ }
+
+ /* Save data */
+ LoaderBlock->MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
+ LoaderBlock->MmapAddr = (ULONG_PTR)KeMemoryMap;
+ }
+ else
+ {
+ /* Nothing from BIOS */
+ LoaderBlock->MmapLength = 0;
+ LoaderBlock->MmapAddr = (ULONG_PTR)KeMemoryMap;
+ }
/* Convert the loader block */
- KiRosFrldrLpbToNtLpb(&KeRosLoaderBlock, &NtLoaderBlock);
+ KiRosFrldrLpbToNtLpb(KeRosLoaderBlock, &NtLoaderBlock);
+
+#if defined(_M_PPC)
+ DbgPrint("Finished KiRosFrldrLpbToNtLpb\n");
+#endif
/* Do general System Startup */
- KiSystemStartup(NtLoaderBlock);
+ KiSystemStartupReal(NtLoaderBlock);
}
/* EOF */