[FREELDR]

Make the DiskReadBuffer location and size dynamic. Should fix a number of issues with non-standard BIOSes. Many thanks to jeditobe for his help with testing/debugging of this issue.
CORE-8899 #resolve
CORE-9031 #resolve

svn path=/trunk/; revision=66087
This commit is contained in:
Timo Kreuzer 2015-01-25 23:24:27 +00:00
parent 273593de7e
commit 63ae430acc
14 changed files with 376 additions and 225 deletions

View file

@ -7,6 +7,7 @@
* Timo Kreuzer
*/
#define DISKREADBUFFER HEX(8E000)
/*
* Layout of a FAT volume:

View file

@ -307,10 +307,10 @@ DetectPnpBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
{
NodeNumber = (UCHAR)i;
x = PnpBiosGetDeviceNode(&NodeNumber, (PVOID)DISKREADBUFFER);
x = PnpBiosGetDeviceNode(&NodeNumber, DiskReadBuffer);
if (x == 0)
{
DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DISKREADBUFFER;
DeviceNode = (PCM_PNP_BIOS_DEVICE_NODE)DiskReadBuffer;
TRACE("Node: %u Size %u (0x%x)\n",
DeviceNode->Node,

View file

@ -42,6 +42,8 @@ extern CHAR reactos_arc_strings[32][256];
static CHAR Hex[] = "0123456789abcdef";
UCHAR PcBiosDiskCount = 0;
CHAR PcDiskIdentifier[32][20];
PVOID DiskReadBuffer;
SIZE_T DiskReadBufferSize;
static ARC_STATUS DiskClose(ULONG FileId)
@ -119,7 +121,7 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
ULONGLONG SectorOffset;
TotalSectors = (N + Context->SectorSize - 1) / Context->SectorSize;
MaxSectors = PcDiskReadBufferSize / Context->SectorSize;
MaxSectors = DiskReadBufferSize / Context->SectorSize;
SectorOffset = Context->SectorNumber + Context->SectorOffset;
ret = 1;
@ -134,7 +136,7 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
Context->DriveNumber,
SectorOffset,
ReadSectors,
(PVOID)DISKREADBUFFER);
DiskReadBuffer);
if (!ret)
break;
@ -142,7 +144,7 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
if (Length > N)
Length = N;
RtlCopyMemory(Ptr, (PVOID)DISKREADBUFFER, Length);
RtlCopyMemory(Ptr, DiskReadBuffer, Length);
Ptr += Length;
N -= Length;
@ -197,14 +199,14 @@ GetHarddiskInformation(
PCHAR Identifier = PcDiskIdentifier[DriveNumber - 0x80];
/* Read the MBR */
if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
{
ERR("Reading MBR failed\n");
return;
}
Buffer = (ULONG*)DISKREADBUFFER;
Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
Buffer = (ULONG*)DiskReadBuffer;
Mbr = (PMASTER_BOOT_RECORD)DiskReadBuffer;
Signature = Mbr->Signature;
TRACE("Signature: %x\n", Signature);
@ -288,13 +290,13 @@ HwInitializeBiosDisks(VOID)
* harddisks. So, we set the buffer to known contents first, then try to
* read. If the BIOS reports success but the buffer contents haven't
* changed then we fail anyway */
memset((PVOID) DISKREADBUFFER, 0xcd, 512);
while (MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
memset(DiskReadBuffer, 0xcd, 512);
while (MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
{
Changed = FALSE;
for (i = 0; ! Changed && i < 512; i++)
{
Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
Changed = ((PUCHAR)DiskReadBuffer)[i] != 0xcd;
}
if (! Changed)
{
@ -310,7 +312,7 @@ HwInitializeBiosDisks(VOID)
DiskCount++;
DriveNumber++;
memset((PVOID) DISKREADBUFFER, 0xcd, 512);
memset(DiskReadBuffer, 0xcd, 512);
}
DiskReportError(TRUE);
@ -326,13 +328,13 @@ HwInitializeBiosDisks(VOID)
ULONG Checksum = 0;
/* Read the MBR */
if (!MachDiskReadLogicalSectors(FrldrBootDrive, 16ULL, 1, (PVOID)DISKREADBUFFER))
if (!MachDiskReadLogicalSectors(FrldrBootDrive, 16ULL, 1, DiskReadBuffer))
{
ERR("Reading MBR failed\n");
return FALSE;
}
Buffer = (ULONG*)DISKREADBUFFER;
Buffer = (ULONG*)DiskReadBuffer;
/* Calculate the MBR checksum */
for (i = 0; i < 2048 / sizeof(ULONG); i++) Checksum += Buffer[i];

View file

@ -29,32 +29,11 @@ DBG_DEFAULT_CHANNEL(MEMORY);
#define MAX_BIOS_DESCRIPTORS 32
#define STACK_BASE_PAGE (STACKLOW / PAGE_SIZE)
#define FREELDR_BASE_PAGE (FREELDR_BASE / PAGE_SIZE)
#define DISKBUF_BASE_PAGE (DISKREADBUFFER / PAGE_SIZE)
#define STACK_PAGE_COUNT (FREELDR_BASE_PAGE - STACK_BASE_PAGE)
#define FREELDR_PAGE_COUNT (DISKBUF_BASE_PAGE - FREELDR_BASE_PAGE)
#define DISKBUF_PAGE_COUNT (0x10)
#define BIOSBUF_PAGE_COUNT (1)
BIOS_MEMORY_MAP PcBiosMemoryMap[MAX_BIOS_DESCRIPTORS];
ULONG PcBiosMapCount;
ULONG PcDiskReadBufferSize;
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS + 1] =
{
{ LoaderFirmwarePermanent, 0x00, 1 }, // realmode int vectors
{ LoaderFirmwareTemporary, 0x01, STACK_BASE_PAGE - 1 }, // freeldr stack, cmdline, BIOS call buffer
{ LoaderOsloaderStack, STACK_BASE_PAGE, FREELDR_BASE_PAGE - STACK_BASE_PAGE }, // prot mode stack.
{ LoaderLoadedProgram, FREELDR_BASE_PAGE, FREELDR_PAGE_COUNT }, // freeldr image
{ LoaderFirmwareTemporary, DISKBUF_BASE_PAGE, DISKBUF_PAGE_COUNT }, // Disk read buffer for int 13h. DISKREADBUFFER
{ LoaderFirmwarePermanent, 0x9F, 0x1 }, // EBDA
{ LoaderFirmwarePermanent, 0xA0, 0x50 }, // ROM / Video
{ LoaderSpecialMemory, 0xF0, 0x10 }, // ROM / Video
{ LoaderSpecialMemory, 0xFFF, 1 }, // unusable memory
{ 0, 0, 0 }, // end of map
};
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS + 1];
ULONG PcMapCount;
ULONG
AddMemoryDescriptor(
@ -186,38 +165,12 @@ PcMemGetConventionalMemorySize(VOID)
}
static
ULONG
PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
BOOLEAN
GetEbdaLocation(
PULONG BaseAddress,
PULONG Size)
{
REGS Regs;
ULONG MapCount = 0;
ULONGLONG RealBaseAddress, RealSize;
TYPE_OF_MEMORY MemoryType;
ULONG Size;
ASSERT(PcBiosMapCount == 0);
TRACE("GetBiosMemoryMap()\n");
/* Make sure the usable memory is large enough. To do this we check the 16
bit value at address 0x413 inside the BDA, which gives us the usable size
in KB */
Size = (*(PUSHORT)(ULONG_PTR)0x413) * 1024;
if (Size < DISKREADBUFFER || Size - DISKREADBUFFER < MIN_DISKREADBUFFER_SIZE)
{
FrLdrBugCheckWithMessage(
MEMORY_INIT_FAILURE,
__FILE__,
__LINE__,
"The BIOS reported a usable memory range up to 0x%x, which is too small!\n\n"
"If you see this, please report to the ReactOS team!",
Size);
}
PcDiskReadBufferSize = (Size - DISKREADBUFFER) & ~0xfff;
if (PcDiskReadBufferSize > MAX_DISKREADBUFFER_SIZE)
{
PcDiskReadBufferSize = MAX_DISKREADBUFFER_SIZE;
}
TRACE("PcDiskReadBufferSize=0x%x\n", PcDiskReadBufferSize);
/* Get the address of the Extended BIOS Data Area (EBDA).
* Int 15h, AH=C1h
@ -232,37 +185,45 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSi
Int386(0x15, &Regs, &Regs);
/* If the function fails, there is no EBDA */
if (INT386_SUCCESS(Regs))
if (!INT386_SUCCESS(Regs))
{
/* Check if this is high enough */
ULONG EbdaBase = (ULONG)Regs.w.es << 4;
if (EbdaBase < DISKREADBUFFER || EbdaBase - DISKREADBUFFER < MIN_DISKREADBUFFER_SIZE)
{
FrLdrBugCheckWithMessage(
MEMORY_INIT_FAILURE,
__FILE__,
__LINE__,
"The location of your EBDA is 0x%lx, which is too low!\n\n"
"If you see this, please report to the ReactOS team!",
EbdaBase);
}
if (((EbdaBase - DISKREADBUFFER) & ~0xfff) < PcDiskReadBufferSize)
{
PcDiskReadBufferSize = (EbdaBase - DISKREADBUFFER) & ~0xfff;
TRACE("After EBDA check, PcDiskReadBufferSize=0x%x\n", PcDiskReadBufferSize);
}
/* Calculate the (max) size of the EBDA */
Size = 0xA0000 - EbdaBase;
/* Add the descriptor */
MapCount = AddMemoryDescriptor(PcMemoryMap,
MAX_BIOS_DESCRIPTORS,
(EbdaBase / MM_PAGE_SIZE),
(Size / MM_PAGE_SIZE),
LoaderFirmwarePermanent);
return FALSE;
}
/* Get Base address and (maximum) size */
*BaseAddress = (ULONG)Regs.w.es << 4;
*Size = 0xA0000 - *BaseAddress;
return TRUE;
}
static
ULONG
PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
{
REGS Regs;
ULONGLONG RealBaseAddress, EndAddress, RealSize;
TYPE_OF_MEMORY MemoryType;
ULONG Size;
ASSERT(PcBiosMapCount == 0);
TRACE("GetBiosMemoryMap()\n");
/* Make sure the usable memory is large enough. To do this we check the 16
bit value at address 0x413 inside the BDA, which gives us the usable size
in KB */
Size = (*(PUSHORT)(ULONG_PTR)0x413) * 1024;
if (Size < MEMORY_MARGIN)
{
FrLdrBugCheckWithMessage(
MEMORY_INIT_FAILURE,
__FILE__,
__LINE__,
"The BIOS reported a usable memory range up to 0x%x, which is too small!\n\n"
"If you see this, please report to the ReactOS team!",
Size);
}
/* Int 15h AX=E820h
* Newer BIOSes - GET SYSTEM MEMORY MAP
*
@ -322,13 +283,24 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSi
{
MemoryType = LoaderFree;
/* Align up base of memory area */
RealBaseAddress = PcBiosMemoryMap[PcBiosMapCount].BaseAddress & ~(MM_PAGE_SIZE - 1ULL);
/* Align up base of memory range */
RealBaseAddress = ALIGN_UP_BY(PcBiosMemoryMap[PcBiosMapCount].BaseAddress,
PAGE_SIZE);
/* Calculate the length after aligning the base */
RealSize = PcBiosMemoryMap[PcBiosMapCount].BaseAddress +
PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress;
RealSize = (RealSize + MM_PAGE_SIZE - 1) & ~(MM_PAGE_SIZE - 1ULL);
/* Calculate aligned EndAddress */
EndAddress = PcBiosMemoryMap[PcBiosMapCount].BaseAddress +
PcBiosMemoryMap[PcBiosMapCount].Length;
EndAddress = ALIGN_DOWN_BY(EndAddress, PAGE_SIZE);
/* Check if there is anything left */
if (EndAddress <= RealBaseAddress)
{
/* This doesn't span any page, so continue with next range */
continue;
}
/* Calculate the length of the aligned range */
RealSize = EndAddress - RealBaseAddress;
}
else
{
@ -338,18 +310,20 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSi
MemoryType = LoaderSpecialMemory;
/* Align down base of memory area */
RealBaseAddress = PcBiosMemoryMap[PcBiosMapCount].BaseAddress & ~(MM_PAGE_SIZE - 1ULL);
RealBaseAddress = ALIGN_DOWN_BY(PcBiosMemoryMap[PcBiosMapCount].BaseAddress,
PAGE_SIZE);
/* Calculate the length after aligning the base */
RealSize = PcBiosMemoryMap[PcBiosMapCount].BaseAddress +
PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress;
RealSize = (RealSize + MM_PAGE_SIZE - 1) & ~(MM_PAGE_SIZE - 1ULL);
RealSize = ALIGN_UP_BY(RealSize, PAGE_SIZE);
}
/* Check if we can add this descriptor */
if ((RealSize >= MM_PAGE_SIZE) && (MapCount < MaxMemoryMapSize))
if ((RealSize >= MM_PAGE_SIZE) && (PcMapCount < MaxMemoryMapSize))
{
/* Add the descriptor */
MapCount = AddMemoryDescriptor(PcMemoryMap,
PcMapCount = AddMemoryDescriptor(PcMemoryMap,
MAX_BIOS_DESCRIPTORS,
(PFN_NUMBER)(RealBaseAddress / MM_PAGE_SIZE),
(PFN_NUMBER)(RealSize / MM_PAGE_SIZE),
@ -366,12 +340,72 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSi
TRACE("End Of System Memory Map!\n\n");
break;
}
}
return MapCount;
TRACE("GetBiosMemoryMap end, PcBiosMapCount = %ld\n", PcBiosMapCount);
return PcBiosMapCount;
}
VOID
ReserveMemory(
ULONG_PTR BaseAddress,
SIZE_T Size,
TYPE_OF_MEMORY MemoryType,
PCHAR Usage)
{
ULONG_PTR BasePage, PageCount;
ULONG i;
BasePage = BaseAddress / PAGE_SIZE;
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, Size);
for (i = 0; i < PcMapCount; i++)
{
/* Check for conflicting descriptor */
if ((PcMemoryMap[i].BasePage < BasePage + PageCount) &&
(PcMemoryMap[i].BasePage + PcMemoryMap[i].PageCount > BasePage))
{
/* Check if the memory is free */
if (PcMemoryMap[i].MemoryType != LoaderFree)
{
FrLdrBugCheckWithMessage(
MEMORY_INIT_FAILURE,
__FILE__,
__LINE__,
"Failed to reserve memory in the range 0x%Ix - 0x%Ix for %s",
BaseAddress,
Size,
Usage);
}
}
}
/* Add the memory descriptor */
PcMapCount = AddMemoryDescriptor(PcMemoryMap,
MAX_BIOS_DESCRIPTORS,
BasePage,
PageCount,
MemoryType);
}
VOID
SetMemory(
ULONG_PTR BaseAddress,
SIZE_T Size,
TYPE_OF_MEMORY MemoryType)
{
ULONG_PTR BasePage, PageCount;
BasePage = BaseAddress / PAGE_SIZE;
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, Size);
/* Add the memory descriptor */
PcMapCount = AddMemoryDescriptor(PcMemoryMap,
MAX_BIOS_DESCRIPTORS,
BasePage,
PageCount,
MemoryType);
}
PFREELDR_MEMORY_DESCRIPTOR
PcMemGetMemoryMap(ULONG *MemoryMapSize)
@ -379,13 +413,16 @@ PcMemGetMemoryMap(ULONG *MemoryMapSize)
ULONG i, EntryCount;
ULONG ExtendedMemorySizeAtOneMB;
ULONG ExtendedMemorySizeAtSixteenMB;
ULONG EbdaBase, EbdaSize;
TRACE("PcMemGetMemoryMap()\n");
EntryCount = PcMemGetBiosMemoryMap(PcMemoryMap, MAX_BIOS_DESCRIPTORS);
/* If the BIOS didn't provide a memory map, synthesize one */
if (0 == EntryCount)
if (EntryCount == 0)
{
GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB, &ExtendedMemorySizeAtSixteenMB);
GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB,
&ExtendedMemorySizeAtSixteenMB);
/* Conventional memory */
AddMemoryDescriptor(PcMemoryMap,
@ -395,7 +432,7 @@ PcMemGetMemoryMap(ULONG *MemoryMapSize)
LoaderFree);
/* Extended memory */
EntryCount = AddMemoryDescriptor(PcMemoryMap,
PcMapCount = AddMemoryDescriptor(PcMemoryMap,
MAX_BIOS_DESCRIPTORS,
1024 * 1024 / PAGE_SIZE,
ExtendedMemorySizeAtOneMB * 1024 / PAGE_SIZE,
@ -404,16 +441,65 @@ PcMemGetMemoryMap(ULONG *MemoryMapSize)
if (ExtendedMemorySizeAtSixteenMB != 0)
{
/* Extended memory at 16MB */
EntryCount = AddMemoryDescriptor(PcMemoryMap,
PcMapCount = AddMemoryDescriptor(PcMemoryMap,
MAX_BIOS_DESCRIPTORS,
0x1000000 / PAGE_SIZE,
ExtendedMemorySizeAtSixteenMB * 64 * 1024 / PAGE_SIZE,
LoaderFree);
}
/* Check if we have an EBDA and get it's location */
if (GetEbdaLocation(&EbdaBase, &EbdaSize))
{
/* Add the descriptor */
PcMapCount = AddMemoryDescriptor(PcMemoryMap,
MAX_BIOS_DESCRIPTORS,
(EbdaBase / PAGE_SIZE),
ADDRESS_AND_SIZE_TO_SPAN_PAGES(EbdaBase, EbdaSize),
LoaderFirmwarePermanent);
}
}
/* Setup some protected ranges */
SetMemory(0x000000, 0x01000, LoaderFirmwarePermanent); // Realmode IVT / BDA
SetMemory(0x0A0000, 0x50000, LoaderFirmwarePermanent); // Video memory
SetMemory(0x0F0000, 0x10000, LoaderSpecialMemory); // ROM
SetMemory(0xFFF000, 0x01000, LoaderSpecialMemory); // unusable memory (do we really need this?)
/* Reserve some static ranges for freeldr */
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=%p, DiskReadBufferSize=%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 < EntryCount; i++)
for (i = 0; i < PcMapCount; i++)
{
TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n",
PcMemoryMap[i].BasePage,
@ -421,9 +507,9 @@ PcMemGetMemoryMap(ULONG *MemoryMapSize)
MmGetSystemMemoryMapTypeString(PcMemoryMap[i].MemoryType));
}
*MemoryMapSize = EntryCount;
*MemoryMapSize = PcMapCount;
return PcMemoryMap;
}
/* EOF */

View file

@ -198,17 +198,17 @@ DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
while (N > 0)
{
Length = N;
if (Length > PcDiskReadBufferSize)
Length = PcDiskReadBufferSize;
if (Length > DiskReadBufferSize)
Length = DiskReadBufferSize;
Sectors = (Length + Context->SectorSize - 1) / Context->SectorSize;
ret = MachDiskReadLogicalSectors(
Context->DriveNumber,
Context->SectorNumber + Context->SectorOffset + i,
Sectors,
(PVOID)DISKREADBUFFER);
DiskReadBuffer);
if (!ret)
return EIO;
RtlCopyMemory(Ptr, (PVOID)DISKREADBUFFER, Length);
RtlCopyMemory(Ptr, DiskReadBuffer, Length);
Ptr += Length;
*Count += Length;
N -= Length;
@ -257,14 +257,14 @@ GetHarddiskIdentifier(PCHAR Identifier,
PARTITION_TABLE_ENTRY PartitionTableEntry;
/* Read the MBR */
if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
{
ERR("Reading MBR failed\n");
return;
}
Buffer = (ULONG*)DISKREADBUFFER;
Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
Buffer = (ULONG*)DiskReadBuffer;
Mbr = (PMASTER_BOOT_RECORD)DiskReadBuffer;
Signature = Mbr->Signature;
TRACE("Signature: %x\n", Signature);
@ -351,13 +351,13 @@ DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
* harddisks. So, we set the buffer to known contents first, then try to
* read. If the BIOS reports success but the buffer contents haven't
* changed then we fail anyway */
memset((PVOID) DISKREADBUFFER, 0xcd, PcDiskReadBufferSize);
while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, DiskReadBuffer))
{
Changed = FALSE;
for (i = 0; ! Changed && i < PcDiskReadBufferSize; i++)
for (i = 0; ! Changed && i < DiskReadBufferSize; i++)
{
Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
Changed = ((PUCHAR)DiskReadBuffer)[i] != 0xcd;
}
if (! Changed)
{
@ -366,7 +366,7 @@ DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
break;
}
DiskCount++;
memset((PVOID) DISKREADBUFFER, 0xcd, PcDiskReadBufferSize);
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
}
DiskReportError(TRUE);
TRACE("BIOS reports %d harddisk%s\n",

View file

@ -119,13 +119,13 @@ PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNu
}
// Now try to read in the block
if (!MachDiskReadLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER))
if (!MachDiskReadLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, DiskReadBuffer))
{
FrLdrTempFree(CacheBlock->BlockData, TAG_CACHE_DATA);
FrLdrTempFree(CacheBlock, TAG_CACHE_BLOCK);
return NULL;
}
RtlCopyMemory(CacheBlock->BlockData, (PVOID)DISKREADBUFFER, CacheDrive->BlockSize * CacheDrive->BytesPerSector);
RtlCopyMemory(CacheBlock->BlockData, DiskReadBuffer, CacheDrive->BlockSize * CacheDrive->BytesPerSector);
// Add it to our list of blocks managed by the cache
InsertTailList(&CacheDrive->CacheBlockHead, &CacheBlock->ListEntry);

View file

@ -202,11 +202,11 @@ BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMA
ULONG Index;
// Read master boot record
if (!MachDiskReadLogicalSectors(DriveNumber, LogicalSectorNumber, 1, (PVOID)DISKREADBUFFER))
if (!MachDiskReadLogicalSectors(DriveNumber, LogicalSectorNumber, 1, DiskReadBuffer))
{
return FALSE;
}
RtlCopyMemory(BootRecord, (PVOID)DISKREADBUFFER, sizeof(MASTER_BOOT_RECORD));
RtlCopyMemory(BootRecord, DiskReadBuffer, sizeof(MASTER_BOOT_RECORD));
TRACE("Dumping partition table for drive 0x%x:\n", DriveNumber);

View file

@ -569,8 +569,8 @@ BOOLEAN Ext2ReadVolumeSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG S
//{
// return FALSE;
//}
//ReturnValue = MachDiskReadLogicalSectors(DriveNumber, SectorNumber + Ext2VolumeStartSector, SectorCount, (PVOID)DISKREADBUFFER);
//RtlCopyMemory(Buffer, (PVOID)DISKREADBUFFER, SectorCount * DiskGeometry.BytesPerSector);
//ReturnValue = MachDiskReadLogicalSectors(DriveNumber, SectorNumber + Ext2VolumeStartSector, SectorCount, DiskReadBuffer);
//RtlCopyMemory(Buffer, DiskReadBuffer, SectorCount * DiskGeometry.BytesPerSector);
//return ReturnValue;
return CacheReadDiskSectors(DriveNumber, SectorNumber + Ext2VolumeStartSector, SectorCount, Buffer);
@ -607,11 +607,11 @@ BOOLEAN Ext2ReadSuperBlock(VOID)
// Now try to read the super block
// If this fails then abort
if (!MachDiskReadLogicalSectors(Ext2DriveNumber, Ext2VolumeStartSector, 8, (PVOID)DISKREADBUFFER))
if (!MachDiskReadLogicalSectors(Ext2DriveNumber, Ext2VolumeStartSector, 8, DiskReadBuffer))
{
return FALSE;
}
RtlCopyMemory(Ext2SuperBlock, (PVOID)((ULONG_PTR)DISKREADBUFFER + 1024), 1024);
RtlCopyMemory(Ext2SuperBlock, ((PUCHAR)DiskReadBuffer + 1024), 1024);
TRACE("Dumping super block:\n");
TRACE("total_inodes: %d\n", Ext2SuperBlock->total_inodes);

View file

@ -35,4 +35,4 @@ extern ULONG SecondLevelIcacheSize;
extern ULONG SecondLevelIcacheFillSize;
extern ULONG gDiskReadBuffer, gFileSysBuffer;
#define DISKREADBUFFER gDiskReadBuffer
#define DiskReadBuffer gDiskReadBuffer

View file

@ -63,6 +63,5 @@ VOID PcHwIdle(VOID);
extern BIOS_MEMORY_MAP PcBiosMemoryMap[];
extern ULONG PcBiosMapCount;
extern ULONG PcDiskReadBufferSize;
/* EOF */

View file

@ -4,11 +4,11 @@
#endif
/* Memory layout */
//#ifdef _M_AMD64
#ifdef _M_AMD64
#define PML4_ADDRESS HEX(1000) /* One page PML4 page table */
#define PDP_ADDRESS HEX(2000) /* One page PDP page table */
#define PD_ADDRESS HEX(3000) /* One page PD page table */
//#endif
#endif
#define BIOSCALLBUFFER HEX(4000) /* Buffer to store temporary data for any Int386() call */
#define STACK16ADDR HEX(6F00) /* The 16-bit stack top will be at 0000:6F00 */
#define BSS_START HEX(6F00)
@ -16,15 +16,13 @@
#define STACKADDR HEX(F000) /* The 32/64-bit stack top will be at 0000:F000, or 0xF000 */
#define FREELDR_BASE HEX(F800)
#define FREELDR_PE_BASE HEX(10000)
#define DISKREADBUFFER HEX(8E000) /* Buffer to store data read in from the disk via the BIOS */
/* 9F000- 9FFFF is reserved for the EBDA */
#define MEMORY_MARGIN HEX(90000) /* We need this much memory */
#define BIOSCALLBUFSEGMENT (BIOSCALLBUFFER/16) /* Buffer to store temporary data for any Int386() call */
#define BIOSCALLBUFOFFSET HEX(0000) /* Buffer to store temporary data for any Int386() call */
#define BIOSCALLBUFSIZE PAGE_SIZE /* max is sizeof(VESA_SVGA_INFO) = 512 */
#define MAX_FREELDR_PE_SIZE (DISKREADBUFFER - FREELDR_PE_BASE)
#define MIN_DISKREADBUFFER_SIZE HEX(1000)
#define MAX_DISKREADBUFFER_SIZE HEX(C000)
#define MAX_FREELDR_PE_SIZE (MEMORY_MARGIN - FREELDR_PE_BASE - PAGE_SIZE)
#define MAX_DISKREADBUFFER_SIZE HEX(10000)
/* These addresses specify the realmode "BSS section" layout */
#define BSS_RealModeEntry (BSS_START + 0)

View file

@ -125,6 +125,8 @@ BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
VOID DiskStopFloppyMotor(VOID); // Implemented in i386disk.c
extern UCHAR FrldrBootDrive;
extern ULONG FrldrBootPartition;
extern PVOID DiskReadBuffer;
extern SIZE_T DiskReadBufferSize;
BOOLEAN DiskGetBootPath(char *BootPath, unsigned Size);

View file

@ -123,6 +123,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(SIZE_T MemorySize, PVOID DesiredAdd
extern PVOID FrLdrDefaultHeap;
extern PVOID FrLdrTempHeap;
extern SIZE_T FrLdrImageSize;
PVOID
FrLdrHeapCreate(

View file

@ -23,6 +23,17 @@
DBG_DEFAULT_CHANNEL(MEMORY);
PVOID PageLookupTableAddress = NULL;
PFN_NUMBER TotalPagesInLookupTable = 0;
PFN_NUMBER FreePagesInLookupTable = 0;
PFN_NUMBER LastFreePageHint = 0;
PFN_NUMBER MmLowestPhysicalPage = 0xFFFFFFFF;
PFN_NUMBER MmHighestPhysicalPage = 0;
PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap;
ULONG BiosMemoryMapEntryCount;
SIZE_T FrLdrImageSize;
#if DBG
typedef struct
{
@ -50,18 +61,43 @@ FREELDR_MEMORY_TYPE MemoryTypeArray[] =
{ LoaderReserve, "Reserve" },
};
ULONG MemoryTypeCount = sizeof(MemoryTypeArray) / sizeof(MemoryTypeArray[0]);
PCSTR
MmGetSystemMemoryMapTypeString(
TYPE_OF_MEMORY Type)
{
ULONG Index;
for (Index = 1; Index < MemoryTypeCount; Index++)
{
if (MemoryTypeArray[Index].Type == Type)
{
return MemoryTypeArray[Index].TypeString;
}
}
return MemoryTypeArray[0].TypeString;
}
VOID
DbgDumpMemoryMap(
PFREELDR_MEMORY_DESCRIPTOR List)
{
ULONG i;
DbgPrint("Dumping Memory map:\n");
for (i = 0; List[i].PageCount != 0; i++)
{
DbgPrint("%02d %08x - %08x: %s\n",
i,
List[i].BasePage * PAGE_SIZE,
(List[i].BasePage + List[i].PageCount) * PAGE_SIZE,
MmGetSystemMemoryMapTypeString(List[i].MemoryType));
}
DbgPrint("\n");
}
#endif
PVOID PageLookupTableAddress = NULL;
PFN_NUMBER TotalPagesInLookupTable = 0;
PFN_NUMBER FreePagesInLookupTable = 0;
PFN_NUMBER LastFreePageHint = 0;
PFN_NUMBER MmLowestPhysicalPage = 0xFFFFFFFF;
PFN_NUMBER MmHighestPhysicalPage = 0;
PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap;
ULONG BiosMemoryMapEntryCount;
ULONG
AddMemoryDescriptor(
IN OUT PFREELDR_MEMORY_DESCRIPTOR List,
@ -70,78 +106,117 @@ AddMemoryDescriptor(
IN PFN_NUMBER PageCount,
IN TYPE_OF_MEMORY MemoryType)
{
ULONG i, c;
PFN_NUMBER NextBase;
TRACE("AddMemoryDescriptor(0x%lx-0x%lx [0x%lx pages])\n",
BasePage, BasePage + PageCount, PageCount);
ULONG Index, DescriptCount;
PFN_NUMBER EndPage;
TRACE("AddMemoryDescriptor(0x%Ix, 0x%Ix, %u)\n",
BasePage, PageCount, MemoryType);
/* Scan through all existing descriptors */
for (i = 0, c = 0; (c < MaxCount) && (List[c].PageCount != 0); c++)
EndPage = BasePage + PageCount;
/* Skip over all descriptor below the new range */
Index = 0;
while ((List[Index].PageCount != 0) &&
((List[Index].BasePage + List[Index].PageCount) <= BasePage))
{
/* Count entries completely below the new range */
if (List[i].BasePage + List[i].PageCount <= BasePage) i++;
Index++;
}
/* Check if the list is full */
if (c >= MaxCount) return c;
/* Is there an existing descriptor starting before the new range */
while ((i < c) && (List[i].BasePage <= BasePage))
/* Count the descriptors */
DescriptCount = Index;
while (List[DescriptCount].PageCount != 0)
{
/* The end of the existing one is the minimum for the new range */
NextBase = List[i].BasePage + List[i].PageCount;
/* Bail out, if everything is trimmed away */
if ((BasePage + PageCount) <= NextBase) return c;
/* Trim the naew range at the lower end */
PageCount -= (NextBase - BasePage);
BasePage = NextBase;
/* Go to the next entry and repeat */
i++;
DescriptCount++;
}
ASSERT(PageCount > 0);
/* Are there still entries above? */
if (i < c)
/* Check if the existing range conflicts with the new range */
while ((List[Index].PageCount != 0) &&
(List[Index].BasePage < EndPage))
{
/* Shift the following entries one up */
RtlMoveMemory(&List[i+1], &List[i], (c - i) * sizeof(List[0]));
TRACE("AddMemoryDescriptor conflict @%lu: new=[%lx:%lx], existing=[%lx,%lx]\n",
Index, BasePage, PageCount, List[Index].BasePage, List[Index].PageCount);
/* Insert the new range */
List[i].BasePage = BasePage;
List[i].PageCount = min(PageCount, List[i+1].BasePage - BasePage);
List[i].MemoryType = MemoryType;
c++;
/*
* We have 4 overlapping cases:
*
* Case (a) (b) (c) (d)
* Existing range |---| |-----| |---| |---|
* New range |---| |---| |-----| |---|
*
*/
TRACE("Inserting at i=%ld: (0x%lx:0x%lx)\n",
i, List[i].BasePage, List[i].PageCount);
/* Check if the range was trimmed */
if (PageCount > List[i].PageCount)
/* Check if the existing range starts before the new range (a)/(b) */
if (List[Index].BasePage < BasePage)
{
/* Recursively process the trimmed part */
c = AddMemoryDescriptor(List,
MaxCount,
BasePage + List[i].PageCount,
PageCount - List[i].PageCount,
MemoryType);
/* Check if the existing range extends beyond the new range (b) */
if (List[Index].BasePage + List[Index].PageCount > EndPage)
{
/* Split the descriptor */
RtlMoveMemory(&List[Index + 1],
&List[Index],
(DescriptCount - Index) * sizeof(List[0]));
List[Index + 1].BasePage = EndPage;
List[Index + 1].PageCount = List[Index].BasePage +
List[Index].PageCount -
List[Index + 1].BasePage;
List[Index].PageCount = BasePage - List[Index].BasePage;
Index++;
DescriptCount++;
break;
}
else
{
/* Crop the existing range and continue with the next range */
List[Index].PageCount = BasePage - List[Index].BasePage;
Index++;
}
}
/* Check if the existing range is fully covered by the new range (c) */
else if ((List[Index].BasePage + List[Index].PageCount) <=
EndPage)
{
/* Delete this descriptor */
RtlMoveMemory(&List[Index],
&List[Index + 1],
(DescriptCount - Index) * sizeof(List[0]));
DescriptCount--;
}
/* Otherwise the existing range ends after the new range (d) */
else
{
/* Crop the existing range at the start and bail out */
List[Index].PageCount -= EndPage - List[Index].BasePage;
List[Index].BasePage = EndPage;
break;
}
}
else
/* Make sure we can still add a new descriptor */
if (DescriptCount >= MaxCount)
{
/* We can simply add the range here */
TRACE("Adding i=%ld: (0x%lx:0x%lx)\n", i, BasePage, PageCount);
List[i].BasePage = BasePage;
List[i].PageCount = PageCount;
List[i].MemoryType = MemoryType;
c++;
FrLdrBugCheckWithMessage(
MEMORY_INIT_FAILURE,
__FILE__,
__LINE__,
"Ran out of static memory descriptors!");
}
/* Return the new count */
return c;
/* Insert the new descriptor */
if (Index < DescriptCount)
{
RtlMoveMemory(&List[Index + 1],
&List[Index],
(DescriptCount - Index) * sizeof(List[0]));
}
List[Index].BasePage = BasePage;
List[Index].PageCount = PageCount;
List[Index].MemoryType = MemoryType;
DescriptCount++;
#ifdef DBG
DbgDumpMemoryMap(List);
#endif
return DescriptCount;
}
const FREELDR_MEMORY_DESCRIPTOR*
@ -230,6 +305,9 @@ MmCheckFreeldrImageFile()
OptionalHeader->SizeOfImage, MAX_FREELDR_PE_SIZE,
OptionalHeader->SectionAlignment, OptionalHeader->FileAlignment);
}
/* Calculate the full image size */
FrLdrImageSize = (ULONG_PTR)&__ImageBase + OptionalHeader->SizeOfImage - FREELDR_BASE;
}
BOOLEAN MmInitializeMemoryManager(VOID)
@ -287,22 +365,6 @@ BOOLEAN MmInitializeMemoryManager(VOID)
return TRUE;
}
#if DBG
PCSTR MmGetSystemMemoryMapTypeString(TYPE_OF_MEMORY Type)
{
ULONG Index;
for (Index=1; Index<MemoryTypeCount; Index++)
{
if (MemoryTypeArray[Index].Type == Type)
{
return MemoryTypeArray[Index].TypeString;
}
}
return MemoryTypeArray[0].TypeString;
}
#endif
PFN_NUMBER MmGetPageNumberFromAddress(PVOID Address)
{