[FREELDR] Fix memory initialization on Xbox

- Refactor and use PC memory map init functions
- This fixes filesystem detection and probably some other problems

Based on a patch by Matt Borgerson.

CORE-16204 CORE-16206

Co-authored-by: Matt Borgerson <contact@mborgerson.com>
This commit is contained in:
Stanislav Motylkov 2019-07-16 00:36:54 +03:00 committed by Hermès BÉLUSCA - MAÏTO
parent 8c55fdd17c
commit bca8093b89
2 changed files with 91 additions and 59 deletions

View file

@ -480,6 +480,7 @@ nextRange:
VOID VOID
ReserveMemory( ReserveMemory(
PFREELDR_MEMORY_DESCRIPTOR MemoryMap,
ULONG_PTR BaseAddress, ULONG_PTR BaseAddress,
SIZE_T Size, SIZE_T Size,
TYPE_OF_MEMORY MemoryType, TYPE_OF_MEMORY MemoryType,
@ -494,11 +495,11 @@ ReserveMemory(
for (i = 0; i < PcMapCount; i++) for (i = 0; i < PcMapCount; i++)
{ {
/* Check for conflicting descriptor */ /* Check for conflicting descriptor */
if ((PcMemoryMap[i].BasePage < BasePage + PageCount) && if ((MemoryMap[i].BasePage < BasePage + PageCount) &&
(PcMemoryMap[i].BasePage + PcMemoryMap[i].PageCount > BasePage)) (MemoryMap[i].BasePage + MemoryMap[i].PageCount > BasePage))
{ {
/* Check if the memory is free */ /* Check if the memory is free */
if (PcMemoryMap[i].MemoryType != LoaderFree) if (MemoryMap[i].MemoryType != LoaderFree)
{ {
FrLdrBugCheckWithMessage( FrLdrBugCheckWithMessage(
MEMORY_INIT_FAILURE, MEMORY_INIT_FAILURE,
@ -513,7 +514,7 @@ ReserveMemory(
} }
/* Add the memory descriptor */ /* Add the memory descriptor */
PcMapCount = AddMemoryDescriptor(PcMemoryMap, PcMapCount = AddMemoryDescriptor(MemoryMap,
MAX_BIOS_DESCRIPTORS, MAX_BIOS_DESCRIPTORS,
BasePage, BasePage,
PageCount, PageCount,
@ -522,6 +523,7 @@ ReserveMemory(
VOID VOID
SetMemory( SetMemory(
PFREELDR_MEMORY_DESCRIPTOR MemoryMap,
ULONG_PTR BaseAddress, ULONG_PTR BaseAddress,
SIZE_T Size, SIZE_T Size,
TYPE_OF_MEMORY MemoryType) TYPE_OF_MEMORY MemoryType)
@ -532,17 +534,67 @@ SetMemory(
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, Size); PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, Size);
/* Add the memory descriptor */ /* Add the memory descriptor */
PcMapCount = AddMemoryDescriptor(PcMemoryMap, PcMapCount = AddMemoryDescriptor(MemoryMap,
MAX_BIOS_DESCRIPTORS, MAX_BIOS_DESCRIPTORS,
BasePage, BasePage,
PageCount, PageCount,
MemoryType); MemoryType);
} }
ULONG
PcMemFinalizeMemoryMap(
PFREELDR_MEMORY_DESCRIPTOR MemoryMap)
{
ULONG i;
/* Reserve some static ranges for freeldr */
ReserveMemory(MemoryMap, 0x1000, STACKLOW - 0x1000, LoaderFirmwareTemporary, "BIOS area");
ReserveMemory(MemoryMap, STACKLOW, STACKADDR - STACKLOW, LoaderOsloaderStack, "FreeLdr stack");
ReserveMemory(MemoryMap, FREELDR_BASE, FrLdrImageSize, LoaderLoadedProgram, "FreeLdr image");
/* Default to 1 page above freeldr for the disk read buffer */
DiskReadBuffer = (PUCHAR)ALIGN_UP_BY(FREELDR_BASE + FrLdrImageSize, PAGE_SIZE);
DiskReadBufferSize = PAGE_SIZE;
/* Scan for free range above freeldr image */
for (i = 0; i < PcMapCount; i++)
{
if ((MemoryMap[i].BasePage > (FREELDR_BASE / PAGE_SIZE)) &&
(MemoryMap[i].MemoryType == LoaderFree))
{
/* Use this range for the disk read buffer */
DiskReadBuffer = (PVOID)(MemoryMap[i].BasePage * PAGE_SIZE);
DiskReadBufferSize = min(MemoryMap[i].PageCount * PAGE_SIZE,
MAX_DISKREADBUFFER_SIZE);
break;
}
}
TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
DiskReadBuffer, DiskReadBufferSize);
/* Now reserve the range for the disk read buffer */
ReserveMemory(MemoryMap,
(ULONG_PTR)DiskReadBuffer,
DiskReadBufferSize,
LoaderFirmwareTemporary,
"Disk read buffer");
TRACE("Dumping resulting memory map:\n");
for (i = 0; i < PcMapCount; i++)
{
TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n",
MemoryMap[i].BasePage,
MemoryMap[i].PageCount,
MmGetSystemMemoryMapTypeString(MemoryMap[i].MemoryType));
}
return PcMapCount;
}
PFREELDR_MEMORY_DESCRIPTOR PFREELDR_MEMORY_DESCRIPTOR
PcMemGetMemoryMap(ULONG *MemoryMapSize) PcMemGetMemoryMap(ULONG *MemoryMapSize)
{ {
ULONG i, EntryCount; ULONG EntryCount;
ULONG ExtendedMemorySizeAtOneMB; ULONG ExtendedMemorySizeAtOneMB;
ULONG ExtendedMemorySizeAtSixteenMB; ULONG ExtendedMemorySizeAtSixteenMB;
ULONG EbdaBase, EbdaSize; ULONG EbdaBase, EbdaSize;
@ -596,53 +648,12 @@ PcMemGetMemoryMap(ULONG *MemoryMapSize)
} }
/* Setup some protected ranges */ /* Setup some protected ranges */
SetMemory(0x000000, 0x01000, LoaderFirmwarePermanent); // Realmode IVT / BDA SetMemory(PcMemoryMap, 0x000000, 0x01000, LoaderFirmwarePermanent); // Realmode IVT / BDA
SetMemory(0x0A0000, 0x50000, LoaderFirmwarePermanent); // Video memory SetMemory(PcMemoryMap, 0x0A0000, 0x50000, LoaderFirmwarePermanent); // Video memory
SetMemory(0x0F0000, 0x10000, LoaderSpecialMemory); // ROM SetMemory(PcMemoryMap, 0x0F0000, 0x10000, LoaderSpecialMemory); // ROM
SetMemory(0xFFF000, 0x01000, LoaderSpecialMemory); // unusable memory (do we really need this?) SetMemory(PcMemoryMap, 0xFFF000, 0x01000, LoaderSpecialMemory); // unusable memory (do we really need this?)
/* Reserve some static ranges for freeldr */ *MemoryMapSize = PcMemFinalizeMemoryMap(PcMemoryMap);
ReserveMemory(0x1000, STACKLOW - 0x1000, LoaderFirmwareTemporary, "BIOS area");
ReserveMemory(STACKLOW, STACKADDR - STACKLOW, LoaderOsloaderStack, "FreeLdr stack");
ReserveMemory(FREELDR_BASE, FrLdrImageSize, LoaderLoadedProgram, "FreeLdr image");
/* Default to 1 page above freeldr for the disk read buffer */
DiskReadBuffer = (PUCHAR)ALIGN_UP_BY(FREELDR_BASE + FrLdrImageSize, PAGE_SIZE);
DiskReadBufferSize = PAGE_SIZE;
/* Scan for free range above freeldr image */
for (i = 0; i < PcMapCount; i++)
{
if ((PcMemoryMap[i].BasePage > (FREELDR_BASE / PAGE_SIZE)) &&
(PcMemoryMap[i].MemoryType == LoaderFree))
{
/* Use this range for the disk read buffer */
DiskReadBuffer = (PVOID)(PcMemoryMap[i].BasePage * PAGE_SIZE);
DiskReadBufferSize = min(PcMemoryMap[i].PageCount * PAGE_SIZE,
MAX_DISKREADBUFFER_SIZE);
break;
}
}
TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
DiskReadBuffer, DiskReadBufferSize);
/* Now reserve the range for the disk read buffer */
ReserveMemory((ULONG_PTR)DiskReadBuffer,
DiskReadBufferSize,
LoaderFirmwareTemporary,
"Disk read buffer");
TRACE("Dumping resulting memory map:\n");
for (i = 0; i < PcMapCount; i++)
{
TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n",
PcMemoryMap[i].BasePage,
PcMemoryMap[i].PageCount,
MmGetSystemMemoryMapTypeString(PcMemoryMap[i].MemoryType));
}
*MemoryMapSize = PcMapCount;
return PcMemoryMap; return PcMemoryMap;
} }

View file

@ -20,6 +20,9 @@
*/ */
#include <freeldr.h> #include <freeldr.h>
#include <debug.h>
DBG_DEFAULT_CHANNEL(MEMORY);
static ULONG InstalledMemoryMb = 0; static ULONG InstalledMemoryMb = 0;
static ULONG AvailableMemoryMb = 0; static ULONG AvailableMemoryMb = 0;
@ -28,6 +31,17 @@ static ULONG AvailableMemoryMb = 0;
#define TEST_PATTERN1 0xAA #define TEST_PATTERN1 0xAA
#define TEST_PATTERN2 0x55 #define TEST_PATTERN2 0x55
extern VOID
SetMemory(
PFREELDR_MEMORY_DESCRIPTOR MemoryMap,
ULONG_PTR BaseAddress,
SIZE_T Size,
TYPE_OF_MEMORY MemoryType);
extern ULONG
PcMemFinalizeMemoryMap(
PFREELDR_MEMORY_DESCRIPTOR MemoryMap);
VOID VOID
XboxMemInit(VOID) XboxMemInit(VOID)
{ {
@ -71,6 +85,7 @@ XboxMemInit(VOID)
WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84));
WRITE_PORT_ULONG((ULONG*) 0xcfc, InstalledMemoryMb * 1024 * 1024 - 1); WRITE_PORT_ULONG((ULONG*) 0xcfc, InstalledMemoryMb * 1024 * 1024 - 1);
/* 4 MB video framebuffer is reserved later using XboxMemReserveMemory() */
AvailableMemoryMb = InstalledMemoryMb; AvailableMemoryMb = InstalledMemoryMb;
} }
@ -79,25 +94,31 @@ FREELDR_MEMORY_DESCRIPTOR XboxMemoryMap[2];
PFREELDR_MEMORY_DESCRIPTOR PFREELDR_MEMORY_DESCRIPTOR
XboxMemGetMemoryMap(ULONG *MemoryMapSize) XboxMemGetMemoryMap(ULONG *MemoryMapSize)
{ {
TRACE("XboxMemGetMemoryMap()\n");
/* Synthesize memory map */ /* Synthesize memory map */
/* Available RAM block */ /* Available RAM block */
XboxMemoryMap[0].BasePage = 0; SetMemory(XboxMemoryMap,
XboxMemoryMap[0].PageCount = AvailableMemoryMb * 1024 * 1024 / MM_PAGE_SIZE; 0,
XboxMemoryMap[0].MemoryType = LoaderFree; AvailableMemoryMb * 1024 * 1024,
LoaderFree);
/* Video memory */ /* Video memory */
XboxMemoryMap[1].BasePage = AvailableMemoryMb * 1024 * 1024 / MM_PAGE_SIZE; SetMemory(XboxMemoryMap,
XboxMemoryMap[1].PageCount = (InstalledMemoryMb - AvailableMemoryMb) * 1024 * 1024 / MM_PAGE_SIZE; AvailableMemoryMb * 1024 * 1024,
XboxMemoryMap[1].MemoryType = LoaderFirmwarePermanent; (InstalledMemoryMb - AvailableMemoryMb) * 1024 * 1024,
LoaderFirmwarePermanent);
*MemoryMapSize = 2; *MemoryMapSize = PcMemFinalizeMemoryMap(XboxMemoryMap);
return XboxMemoryMap; return XboxMemoryMap;
} }
PVOID PVOID
XboxMemReserveMemory(ULONG MbToReserve) XboxMemReserveMemory(ULONG MbToReserve)
{ {
/* This function is used to reserve video framebuffer in XboxVideoInit() */
if (InstalledMemoryMb == 0) if (InstalledMemoryMb == 0)
{ {
/* Hmm, seems we're not initialized yet */ /* Hmm, seems we're not initialized yet */