[FREELDR]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 18 Oct 2014 21:12:12 +0000 (21:12 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 18 Oct 2014 21:12:12 +0000 (21:12 +0000)
- 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

reactos/boot/freeldr/freeldr/CMakeLists.txt
reactos/boot/freeldr/freeldr/arch/amd64/entry.S
reactos/boot/freeldr/freeldr/arch/i386/entry.S
reactos/boot/freeldr/freeldr/arch/i386/i386bug.c
reactos/boot/freeldr/freeldr/arch/i386/pcmem.c
reactos/boot/freeldr/freeldr/debug.c
reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h
reactos/boot/freeldr/freeldr/include/debug.h
reactos/boot/freeldr/freeldr/mm/meminit.c

index 1eac9b0..f5b3d1b 100644 (file)
@@ -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)
index 9379008..47080b3 100644 (file)
@@ -121,7 +121,7 @@ CallRealMode_return:
 
        /* 64-bit stack pointer */
 stack64:
-    .double STACK64ADDR
+    .double STACKADDR
 
 PUBLIC FrldrBootDrive
 FrldrBootDrive:
index 795cd40..09003cf 100644 (file)
@@ -257,7 +257,7 @@ stack16:
 
        /* 32-bit stack pointer */
 stack32:
-       .long   STACK32ADDR
+       .long   STACKADDR
 
     .align 4   /* force 4-byte alignment */
 gdt:
index 1722b6c..d31796d 100644 (file)
@@ -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(
index 2b21b69..76601e4 100644 (file)
 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
      *
index dfde53f..22b8cb8 100644 (file)
@@ -444,6 +444,7 @@ char *BugCodeStrings[] =
     "TEST_BUGCHECK",
     "MISSING_HARDWARE_REQUIREMENTS",
     "FREELDR_IMAGE_CORRUPTION",
+    "MEMORY_INIT_FAILURE",
 };
 
 ULONG_PTR BugCheckInfo[5];
index 3d5c7ff..b238a8f 100644 (file)
 //#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 */
index b88c1bd..77a7eed 100644 (file)
@@ -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[];
index 80871c7..b0db4bd 100644 (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);