[FREELDR]

- Improve memory layout by moving the 32/64 bit stack to 0x7000-0xF000 and moving the BIOSCALLBUFFER up a bit. This gives us 56 KB additional space for freeldr itself. This allows to compile freeldr with /RTC1 (x86 only, the x64 version would get too big). And yes, it works.
- Implement FrLdrBugCheckWithMessage to get some useful messages on the screen and use it in MmCheckFreeldrImageFile
- Merge the .rtc section into the .text section, when we use RTC1
- Check the location of the Extended BIOS Data Area, add it to the memory descriptors and make sure we have enough space to put freeldr in. If the location of the EBDA is too low, print out a nice message on a blue screen :)

svn path=/trunk/; revision=64815
This commit is contained in:
Timo Kreuzer
2014-10-18 21:12:12 +00:00
parent 8325f695c5
commit 91dd4cbea0
9 changed files with 159 additions and 36 deletions
@@ -216,6 +216,7 @@ if(STACK_PROTECTOR)
elseif(RUNTIME_CHECKS)
target_link_libraries(freeldr_pe runtmchk)
target_link_libraries(freeldr_pe_dbg runtmchk)
add_target_link_flags(freeldr_pe "/MERGE:.rtc=.text")
endif()
add_dependencies(freeldr_pe asm)
@@ -279,6 +280,7 @@ if(STACK_PROTECTOR)
elseif(RUNTIME_CHECKS)
target_link_libraries(setupldr_pe runtmchk)
target_link_libraries(setupldr_pe_dbg runtmchk)
add_target_link_flags(setupldr_pe "/MERGE:.rtc=.text")
endif()
add_dependencies(setupldr_pe asm)
@@ -121,7 +121,7 @@ CallRealMode_return:
/* 64-bit stack pointer */
stack64:
.double STACK64ADDR
.double STACKADDR
PUBLIC FrldrBootDrive
FrldrBootDrive:
@@ -257,7 +257,7 @@ stack16:
/* 32-bit stack pointer */
stack32:
.long STACK32ADDR
.long STACKADDR
.align 4 /* force 4-byte alignment */
gdt:
@@ -86,11 +86,11 @@ i386PrintFrames(PKTRAP_FRAME TrapFrame)
PrintText("Frames:\n");
#ifdef _M_IX86
for (Frame = (FRAME*)TrapFrame->Ebp;
Frame != 0 && (ULONG_PTR)Frame < STACK32ADDR;
Frame != 0 && (ULONG_PTR)Frame < STACKADDR;
Frame = Frame->Next)
#else
for (Frame = (FRAME*)TrapFrame->TrapFrame;
Frame != 0 && (ULONG_PTR)Frame < STACK32ADDR;
Frame != 0 && (ULONG_PTR)Frame < STACKADDR;
Frame = Frame->Next)
#endif
{
@@ -171,6 +171,44 @@ i386PrintExceptionText(ULONG TrapIndex, PKTRAP_FRAME TrapFrame, PKSPECIAL_REGIST
InstructionPointer[6], InstructionPointer[7]);
}
VOID
NTAPI
FrLdrBugCheckWithMessage(
ULONG BugCode,
PCHAR File,
ULONG Line,
PSTR Format,
...)
{
CHAR Buffer[1024];
va_list argptr;
/* Blue screen for the win */
MachVideoClearScreen(SCREEN_ATTR);
i386_ScreenPosX = 0;
i386_ScreenPosY = 0;
PrintText("A problem has been detected and FreeLoader boot has been aborted.\n\n");
PrintText("%ld: %s\n\n", BugCode, BugCodeStrings[BugCode]);
if (File)
{
PrintText("Location: %s:%ld\n\n", File, Line);
}
va_start(argptr, Format);
_vsnprintf(Buffer, sizeof(Buffer), Format, argptr);
va_end(argptr);
Buffer[sizeof(Buffer) - 1] = 0;
i386PrintText(Buffer);
_disable();
__halt();
for (;;);
}
void
NTAPI
FrLdrBugCheckEx(
+61 -6
View File
@@ -28,15 +28,15 @@
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_BASE_PAGE (STACKLOWLIMIT / PAGE_SIZE)
#define STACK_END_PAGE (STACK32ADDR / PAGE_SIZE)
#define BIOSBUF_BASE_PAGE (BIOSCALLBUFFER / 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 (STACK_BASE_PAGE - DISKBUF_BASE_PAGE)
#define STACK_PAGE_COUNT (STACK_END_PAGE - STACK_BASE_PAGE)
#define DISKBUF_PAGE_COUNT (0x10)
#define BIOSBUF_PAGE_COUNT (1)
BIOS_MEMORY_MAP PcBiosMemoryMap[MAX_BIOS_DESCRIPTORS];
@@ -45,11 +45,12 @@ ULONG PcBiosMapCount;
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS + 1] =
{
{ LoaderFirmwarePermanent, 0x00, 1 }, // realmode int vectors
{ LoaderFirmwareTemporary, 0x01, FREELDR_BASE_PAGE - 1 }, // freeldr stack + cmdline
{ LoaderFirmwareTemporary, 0x01, STACK_BASE_PAGE - 1 }, // freeldr stack + cmdline
{ 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
{ LoaderOsloaderStack, STACK_BASE_PAGE, STACK_PAGE_COUNT }, // prot mode stack.
{ LoaderFirmwareTemporary, BIOSBUF_BASE_PAGE, BIOSBUF_PAGE_COUNT }, // BIOSCALLBUFFER
{ LoaderFirmwarePermanent, 0x9F, 0x1 }, // EBDA
{ LoaderFirmwarePermanent, 0xA0, 0x50 }, // ROM / Video
{ LoaderSpecialMemory, 0xF0, 0x10 }, // ROM / Video
{ LoaderSpecialMemory, 0xFFF, 1 }, // unusable memory
@@ -193,10 +194,64 @@ PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSi
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 < 0x9F000)
{
FrLdrBugCheckWithMessage(
MEMORY_INIT_FAILURE,
__FILE__,
__LINE__,
"The BIOS reported a usable memory range up to 0x%x, which is too small!\n",
Size);
}
/* Get the address of the Extended BIOS Data Area (EBDA).
* Int 15h, AH=C1h
* SYSTEM - RETURN EXTENDED-BIOS DATA-AREA SEGMENT ADDRESS (PS)
*
* Return:
* CF set on error
* CF clear if successful
* ES = segment of data area
*/
Regs.x.eax = 0x0000C100;
Int386(0x15, &Regs, &Regs);
/* If the function fails, there is no EBDA */
if (INT386_SUCCESS(Regs))
{
/* Check if this is high enough */
ULONG EbdaBase = (ULONG)Regs.w.es << 4;
if (EbdaBase < 0x9F000)
{
FrLdrBugCheckWithMessage(
MEMORY_INIT_FAILURE,
__FILE__,
__LINE__,
"The location of your EBDA is 0x%lx, which is too low!\n"
"If you see this, please report to the ReactOS team!",
EbdaBase);
}
/* 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);
}
/* Int 15h AX=E820h
* Newer BIOSes - GET SYSTEM MEMORY MAP
*
+1
View File
@@ -444,6 +444,7 @@ char *BugCodeStrings[] =
"TEST_BUGCHECK",
"MISSING_HARDWARE_REQUIREMENTS",
"FREELDR_IMAGE_CORRUPTION",
"MEMORY_INIT_FAILURE",
};
ULONG_PTR BugCheckInfo[5];
@@ -11,13 +11,13 @@
//#endif
#define STACK16ADDR HEX(6F00) /* The 16-bit stack top will be at 0000:6F00 */
#define BSS_START HEX(6F00)
#define STACKLOW HEX(7000)
#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(80000) /* Buffer to store data read in from the disk via the BIOS */
#define STACKLOWLIMIT HEX(90000)
#define STACK32ADDR HEX(98000) /* The 32-bit stack top will be at 9000:8000, or 0xA8000 */
#define STACK64ADDR HEX(98000) /* The 64-bit stack top will be at 98000 */
#define BIOSCALLBUFFER HEX(98000) /* Buffer to store temporary data for any Int386() call */
#define DISKREADBUFFER HEX(8E000) /* Buffer to store data read in from the disk via the BIOS */
#define BIOSCALLBUFFER HEX(9E000) /* Buffer to store temporary data for any Int386() call */
/* 9F000- 9FFFF is reserved for the EBDA */
#define DISKREADBUFFER_SIZE HEX(10000)
#define BIOSCALLBUFSEGMENT (BIOSCALLBUFFER/16) /* Buffer to store temporary data for any Int386() call */
@@ -124,12 +124,22 @@ void
NTAPI
FrLdrBugCheck(ULONG BugCode);
VOID
NTAPI
FrLdrBugCheckWithMessage(
ULONG BugCode,
PCHAR File,
ULONG Line,
PSTR Format,
...);
/* Bugcheck codes */
enum _FRLDR_BUGCHECK_CODES
{
TEST_BUGCHECK,
MISSING_HARDWARE_REQUIREMENTS,
FREELDR_IMAGE_CORRUPTION,
MEMORY_INIT_FAILURE,
};
extern char *BugCodeStrings[];
+38 -21
View File
@@ -159,8 +159,8 @@ ArcGetMemoryDescriptor(const FREELDR_MEMORY_DESCRIPTOR* Current)
}
}
BOOLEAN
static
VOID
MmCheckFreeldrImageFile()
{
PIMAGE_NT_HEADERS NtHeaders;
@@ -172,7 +172,11 @@ MmCheckFreeldrImageFile()
if (!NtHeaders)
{
ERR("Could not get NtHeaders!\n");
return FALSE;
FrLdrBugCheckWithMessage(
FREELDR_IMAGE_CORRUPTION,
__FILE__,
__LINE__,
"Could not get NtHeaders!\n");
}
/* Check the file header */
@@ -184,12 +188,21 @@ MmCheckFreeldrImageFile()
(FileHeader->SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)))
{
ERR("FreeLdr FileHeader is invalid.\n");
BugCheckInfo[0] = FileHeader->Machine;
BugCheckInfo[1] = FileHeader->NumberOfSections;
BugCheckInfo[2] = FileHeader->PointerToSymbolTable;
BugCheckInfo[3] = FileHeader->NumberOfSymbols;
BugCheckInfo[4] = FileHeader->SizeOfOptionalHeader;
return FALSE;
FrLdrBugCheckWithMessage(
FREELDR_IMAGE_CORRUPTION,
__FILE__,
__LINE__,
"FreeLdr FileHeader is invalid.\n"
"Machine == 0x%lx, expected 0x%lx\n"
"NumberOfSections == 0x%lx, expected 0x%lx\n"
"PointerToSymbolTable == 0x%lx, expected 0\n"
"NumberOfSymbols == 0x%lx, expected 0\n"
"SizeOfOptionalHeader == 0x%lx, expected 0x%lx\n",
FileHeader->Machine, IMAGE_FILE_MACHINE_NATIVE,
FileHeader->NumberOfSections, FREELDR_SECTION_COUNT,
FileHeader->PointerToSymbolTable,
FileHeader->NumberOfSymbols,
FileHeader->SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER));
}
/* Check the optional header */
@@ -201,15 +214,22 @@ MmCheckFreeldrImageFile()
(OptionalHeader->SectionAlignment != OptionalHeader->FileAlignment))
{
ERR("FreeLdr OptionalHeader is invalid.\n");
BugCheckInfo[0] = 0x80000000 | (OptionalHeader->Subsystem << 16) | OptionalHeader->Magic;
BugCheckInfo[1] = OptionalHeader->ImageBase;
BugCheckInfo[2] = OptionalHeader->SizeOfImage;
BugCheckInfo[3] = OptionalHeader->SectionAlignment;
BugCheckInfo[4] = OptionalHeader->FileAlignment;
return FALSE;
FrLdrBugCheckWithMessage(
FREELDR_IMAGE_CORRUPTION,
__FILE__,
__LINE__,
"FreeLdr OptionalHeader is invalid.\n"
"Magic == 0x%lx, expected 0x%lx\n"
"Subsystem == 0x%lx, expected 1 (native)\n"
"ImageBase == 0x%lx, expected 0x%lx\n"
"SizeOfImage == 0x%lx, maximum 0x%lx\n"
"SectionAlignment 0x%lx doesn't match FileAlignment 0x%lx\n",
OptionalHeader->Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC,
OptionalHeader->Subsystem,
OptionalHeader->ImageBase, FREELDR_PE_BASE,
OptionalHeader->SizeOfImage, MAX_FREELDR_PE_SIZE,
OptionalHeader->SectionAlignment, OptionalHeader->FileAlignment);
}
return TRUE;
}
BOOLEAN MmInitializeMemoryManager(VOID)
@@ -221,10 +241,7 @@ BOOLEAN MmInitializeMemoryManager(VOID)
TRACE("Initializing Memory Manager.\n");
/* Check the freeldr binary */
if (!MmCheckFreeldrImageFile())
{
FrLdrBugCheck(FREELDR_IMAGE_CORRUPTION);
}
MmCheckFreeldrImageFile();
BiosMemoryMap = MachVtbl.GetMemoryMap(&BiosMemoryMapEntryCount);