diff --git a/reactos/boot/freeldr/freeldr/CMakeLists.txt b/reactos/boot/freeldr/freeldr/CMakeLists.txt index 1eac9b09303..f5b3d1b7de8 100644 --- a/reactos/boot/freeldr/freeldr/CMakeLists.txt +++ b/reactos/boot/freeldr/freeldr/CMakeLists.txt @@ -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) diff --git a/reactos/boot/freeldr/freeldr/arch/amd64/entry.S b/reactos/boot/freeldr/freeldr/arch/amd64/entry.S index 9379008f9de..47080b39cf4 100644 --- a/reactos/boot/freeldr/freeldr/arch/amd64/entry.S +++ b/reactos/boot/freeldr/freeldr/arch/amd64/entry.S @@ -121,7 +121,7 @@ CallRealMode_return: /* 64-bit stack pointer */ stack64: - .double STACK64ADDR + .double STACKADDR PUBLIC FrldrBootDrive FrldrBootDrive: diff --git a/reactos/boot/freeldr/freeldr/arch/i386/entry.S b/reactos/boot/freeldr/freeldr/arch/i386/entry.S index 795cd40afe0..09003cff5f4 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/entry.S +++ b/reactos/boot/freeldr/freeldr/arch/i386/entry.S @@ -257,7 +257,7 @@ stack16: /* 32-bit stack pointer */ stack32: - .long STACK32ADDR + .long STACKADDR .align 4 /* force 4-byte alignment */ gdt: diff --git a/reactos/boot/freeldr/freeldr/arch/i386/i386bug.c b/reactos/boot/freeldr/freeldr/arch/i386/i386bug.c index 1722b6c4294..d31796d16de 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/i386bug.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/i386bug.c @@ -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( diff --git a/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c b/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c index 2b21b698741..76601e4118a 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c @@ -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 * diff --git a/reactos/boot/freeldr/freeldr/debug.c b/reactos/boot/freeldr/freeldr/debug.c index dfde53f27d7..22b8cb83e3b 100644 --- a/reactos/boot/freeldr/freeldr/debug.c +++ b/reactos/boot/freeldr/freeldr/debug.c @@ -444,6 +444,7 @@ char *BugCodeStrings[] = "TEST_BUGCHECK", "MISSING_HARDWARE_REQUIREMENTS", "FREELDR_IMAGE_CORRUPTION", + "MEMORY_INIT_FAILURE", }; ULONG_PTR BugCheckInfo[5]; diff --git a/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h b/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h index 3d5c7ffb4cb..b238a8fd97a 100644 --- a/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h +++ b/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h @@ -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 */ diff --git a/reactos/boot/freeldr/freeldr/include/debug.h b/reactos/boot/freeldr/freeldr/include/debug.h index b88c1bd0b49..77a7eed98ac 100644 --- a/reactos/boot/freeldr/freeldr/include/debug.h +++ b/reactos/boot/freeldr/freeldr/include/debug.h @@ -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[]; diff --git a/reactos/boot/freeldr/freeldr/mm/meminit.c b/reactos/boot/freeldr/freeldr/mm/meminit.c index 80871c79c08..b0db4bdd487 100644 --- a/reactos/boot/freeldr/freeldr/mm/meminit.c +++ b/reactos/boot/freeldr/freeldr/mm/meminit.c @@ -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);