[FREELDR]
authorDmitry Gorbachev <gorbachev@reactos.org>
Tue, 20 Sep 2011 08:50:38 +0000 (08:50 +0000)
committerDmitry Gorbachev <gorbachev@reactos.org>
Tue, 20 Sep 2011 08:50:38 +0000 (08:50 +0000)
Fix loading with GRUB (CMake builds).

svn path=/trunk/; revision=53765

reactos/boot/freeldr/freeldr/CMakeLists.txt
reactos/boot/freeldr/freeldr/arch/i386/entry.S
reactos/boot/freeldr/freeldr/arch/i386/multiboot.S

index 7ff3789..57a86a9 100644 (file)
@@ -117,8 +117,7 @@ if(ARCH MATCHES i386)
         disk/scsiport.c)
     if(NOT MSVC)
         list(APPEND FREELDR_COMMON_SOURCE
-            arch/i386/drvmap.S
-            arch/i386/multiboot.S)
+            arch/i386/drvmap.S)
     endif()
 elseif(ARCH MATCHES amd64)
     list(APPEND FREELDR_COMMON_SOURCE
@@ -148,6 +147,9 @@ endif()
 add_library(freeldr_common ${FREELDR_COMMON_SOURCE})
 add_dependencies(freeldr_common bugcodes)
 
+if(ARCH MATCHES i386 AND NOT MSVC)
+    list(APPEND FREELDR_BASE_SOURCE arch/i386/multiboot.S)
+endif()
 
 list(APPEND FREELDR_BASE_SOURCE
     bootmgr.c # This file is compiled with custom definitions
@@ -159,7 +161,7 @@ list(APPEND FREELDR_BASE_SOURCE
 add_executable(freeldr_pe ${FREELDR_BASE_SOURCE})
 
 if(NOT MSVC)
-    set_target_properties(freeldr_pe PROPERTIES LINK_FLAGS "-Wl,--strip-all -Wl,--exclude-all-symbols -Wl,--file-alignment,0x1000 -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lnk")
+    set_target_properties(freeldr_pe PROPERTIES LINK_FLAGS "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lnk")
 else()
     set_target_properties(freeldr_pe PROPERTIES LINK_FLAGS "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text /SUBSYSTEM:BOOT_APPLICATION")
 endif()
@@ -208,7 +210,7 @@ endif()
 add_executable(setupldr_pe ${FREELDR_BASE_SOURCE} ${SETUPLDR_SOURCE})
 
 if(NOT MSVC)
-    set_target_properties(setupldr_pe PROPERTIES LINK_FLAGS "-Wl,--strip-all -Wl,--exclude-all-symbols -Wl,--file-alignment,0x1000 -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lnk" COMPILE_DEFINITIONS "FREELDR_REACTOS_SETUP")
+    set_target_properties(setupldr_pe PROPERTIES LINK_FLAGS "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lnk" COMPILE_DEFINITIONS "FREELDR_REACTOS_SETUP")
 else()
     set_target_properties(setupldr_pe PROPERTIES LINK_FLAGS "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text /SUBSYSTEM:BOOT_APPLICATION" COMPILE_DEFINITIONS "FREELDR_REACTOS_SETUP")
 endif()
index d1f6402..61d44b0 100644 (file)
@@ -70,8 +70,14 @@ _FrldrStartup:
     /* Initialize the idt */
     call _InitIdt
 
+    /* Pass the command line to BootMain */
+#ifdef _USE_ML
+    xor eax, eax
+#else
+    mov eax, offset cmdline
+#endif
+
        /* GO! */
-       xor eax, eax
        push eax
        call _BootMain
 
index 5c1e724..72a40c4 100644 (file)
 #include <arch/pc/x86common.h>
 #include <multiboot.h>
 
-
 /* Multiboot support
  *
  * Allows freeldr to be loaded as a "multiboot kernel" by
- * other boot loaders like Grub
+ * other boot loaders like GRUB.
  * This code is not referenced from anywhere. GRUB searches for
  * the header signature and uses the header to load it.
  */
 
-#define MB_INFO_SIZE                90
 #define MB_INFO_FLAGS_OFFSET        0
 #define MB_INFO_BOOT_DEVICE_OFFSET  12
 #define MB_INFO_COMMAND_LINE_OFFSET 16
 #define CMDLINE_SIZE                256
 
 /*
- * We want to execute at 0x8000 (to be compatible with bootsector
- * loading), but Grub only allows loading of multiboot kernels
- * above 1MB. So we let Grub load us there and then relocate
- * ourself to 0x8000
+ * We want to execute at FREELDR_BASE (to be compatible with
+ * bootsector loading), but GRUB only allows loading of
+ * multiboot kernels above 1MB. So we let GRUB load us
+ * there and then relocate ourself to FREELDR_BASE.
  */
 #define INITIAL_BASE HEX(200000)
 
-       /* Align 32 bits boundary */
-.align 4
+    /* Align to 32 bits boundary */
+    .align 4
 
-       /* Multiboot header */
+    /* Multiboot header */
 MultibootHeader:
-       /* magic */
-       .long MULTIBOOT_HEADER_MAGIC
-       /* flags */
-       .long MULTIBOOT_HEADER_FLAGS
-       /* checksum */
-       .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
-       /* header_addr */
-       .long INITIAL_BASE + MultibootHeader - FREELDR_BASE
-       /* load_addr */
-       .long INITIAL_BASE
-       /* load_end_addr */
-       .long INITIAL_BASE + __bss_start__ - FREELDR_BASE
-       /* bss_end_addr */
-       .long INITIAL_BASE + __bss_end__ - FREELDR_BASE
-       /* entry_addr */
-       .long INITIAL_BASE + MultibootEntry - FREELDR_BASE
+    /* magic */
+    .long MULTIBOOT_HEADER_MAGIC
+    /* flags */
+    .long MULTIBOOT_HEADER_FLAGS
+    /* checksum */
+    .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+    /* header_addr */
+    .long INITIAL_BASE + MultibootHeader - FREELDR_BASE
+    /* load_addr */
+    .long INITIAL_BASE
+    /* load_end_addr */
+    .long INITIAL_BASE + __bss_start__ - FREELDR_BASE
+    /* bss_end_addr */
+    .long 0
+    /* entry_addr */
+    .long INITIAL_BASE + MultibootEntry - FREELDR_BASE
 
 MultibootEntry:
-       cli             /* Even after setting up the our IDT below we are
-                        * not ready to handle hardware interrupts (no entries
-                        * in IDT), so there's no sti here. Interrupts will be
-                        * enabled in due time */
-
-       /* Although the multiboot spec says we should be called with the
-        * segment registers set to 4GB flat mode, let's be sure and set up
-        * our own */
-       lgdt    gdtptrhigh + INITIAL_BASE - FREELDR_BASE
-       /* Reload segment selectors */
-       //ljmp  $PMODE_CS, $(mb1 + INITIAL_BASE - FREELDR_BASE)
-       jmp far ptr PMODE_CS: (mb1 + INITIAL_BASE - FREELDR_BASE)
+    cld
+
+    /* Save command line */
+    test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
+    jz mb2
+    mov esi, [ebx + MB_INFO_COMMAND_LINE_OFFSET]
+    mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
+    mov ecx, CMDLINE_SIZE - 1
 mb1:
-       mov dx, PMODE_DS
-       mov ds, dx
-       mov es, dx
-
-       /* Check for valid multiboot signature */
-       cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
-       jne mbfail
-
-       /* Store multiboot info in a safe place */
-       mov esi, ebx
-       mov edi, offset mb_info + INITIAL_BASE - FREELDR_BASE
-       mov ecx, MB_INFO_SIZE
-       rep movsb
-
-       /* Save commandline */
-       mov edx, [ebx + MB_INFO_FLAGS_OFFSET]
-       test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
-       jz mb3
-       mov esi, [ebx + MB_INFO_COMMAND_LINE_OFFSET]
-       mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
-       mov ecx, CMDLINE_SIZE
-mb2:   lodsb
-       stosb
-       test al, al
-       jz mb3
-       dec ecx
-       jnz mb2
-mb3:
+    lodsb
+    stosb
+    test al, al
+    jz mb2
+    dec ecx
+    jnz mb1
+
+mb2:
+    /* See if the boot device was passed in */
+    test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_BOOT_DEVICE
+
+    /* If no boot device known, assume first partition of first harddisk */
+    mov dx, HEX(0180)
+    jz mb3
+
+    /* Load boot drive into DL, boot partition into DH */
+    mov edx, [ebx + MB_INFO_BOOT_DEVICE_OFFSET]
+    bswap edx
+    inc dh
 
-       /* Copy to low mem */
-       mov esi, INITIAL_BASE
-       mov edi, FREELDR_BASE
-       mov ecx, (offset __bss_end__ - FREELDR_BASE)
-       add ecx, 3
-       shr ecx, 2
-       rep movsd
-
-       /* Load the GDT and IDT */
-       lgdt    gdtptr
-       lidt    i386idtptr
-
-       /* Clear prefetch queue & correct CS,
-        * jump to low mem */
-       //ljmp  $PMODE_CS, $mb4
-       jmp far ptr PMODE_CS:mb4
+mb3:
+    /* Relocate itself to lower address */
+    mov esi, INITIAL_BASE
+    mov edi, FREELDR_BASE
+    mov ecx, (offset __bss_start__ - FREELDR_BASE + 3)
+    shr ecx, 2
+    rep movsd
+
+    /* Clean out bss */
+    xor eax, eax
+    mov ecx, offset __bss_end__ + 3
+    sub ecx, offset __bss_start__
+    shr ecx, 2
+    rep stosd
+
+    /* Load segment registers for real-address mode */
+    lgdt gdtptr
+    mov ax, HEX(10)
+    mov ds, ax
+    mov es, ax
+    mov fs, ax
+    mov gs, ax
+    mov ss, ax
+
+    /* Jump to relocated code */
+    ljmp HEX(08), mb4
+
+.code16
 mb4:
-       /* Reload segment selectors */
-       mov dx, PMODE_DS
-       mov ds, dx
-       mov es, dx
-       mov fs, dx
-       mov gs, dx
-       mov ss, dx
-       mov esp, STACK32ADDR
-
-       mov ebx, offset mb_info
-       /* See if the boot device was passed in */
-       mov edx, [ebx + MB_INFO_FLAGS_OFFSET]
-       test edx, MB_INFO_FLAG_BOOT_DEVICE
-       jz mb5
-       /* Retrieve boot device info */
-       mov eax, [ebx + MB_INFO_BOOT_DEVICE_OFFSET]
-       shr eax, 16
-       inc al
-       mov byte ptr [_FrldrBootPartition], al
-       mov byte ptr [_FrldrBootDrive], ah
-       jmp mb6
-mb5:   /* No boot device known, assume first partition of first harddisk */
-       mov byte ptr [_FrldrBootDrive], HEX(80)
-       mov byte ptr [_FrldrBootPartition], 1
-mb6:
-       /* Check for command line */
-       mov eax, offset cmdline
-       test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
-       jnz mb7
-       xor eax, eax
-mb7:
-
-       /* GO! */
-       push eax
-       call    _BootMain
-
-mbfail:
-    int 3
-mbstop:        jmp     mbstop  /* We should never get here */
-
-mb_info:
-       .fill MB_INFO_SIZE, 1, 0
+    /* Disable protected mode */
+    mov eax, cr0
+    and eax, CR0_PE_CLR
+    mov cr0, eax
 
-cmdline:
-       .fill CMDLINE_SIZE, 1, 0
+    /* Jump to real entry point */
+    ljmp16 0, FREELDR_BASE
 
-.align 4       /* force 4-byte alignment */
+    /* Force 8-byte alignment */
+    .align 8
 gdt:
-       /* NULL Descriptor */
-       .word HEX(0000)
-       .word HEX(0000)
-       .word HEX(0000)
-       .word HEX(0000)
-
-       /* 32-bit flat CS */
-       .word HEX(FFFF)
-       .word HEX(0000)
-       .word HEX(9A00)
-       .word HEX(00CF)
-
-       /* 32-bit flat DS */
-       .word HEX(FFFF)
-       .word HEX(0000)
-       .word HEX(9200)
-       .word HEX(00CF)
-
-       /* 16-bit real mode CS */
-       .word HEX(FFFF)
-       .word HEX(0000)
-       .word HEX(9E00)
-       .word HEX(0000)
-
-       /* 16-bit real mode DS */
-       .word HEX(FFFF)
-       .word HEX(0000)
-       .word HEX(9200)
-       .word HEX(0000)
-
-/* GDT table pointer */
+    /* 16-bit flat CS (!) */
+    .word HEX(FFFF)
+    .word HEX(0000)
+    .word HEX(9B00)
+    .word HEX(008F)
+
+    /* 16-bit real mode DS */
+    .word HEX(FFFF)
+    .word HEX(0000)
+    .word HEX(9300)
+    .word HEX(0000)
+
+    /* GDT pointer */
 gdtptr:
-       .word HEX(27)           /* Limit */
-       .long gdt                       /* Base Address */
+    .word HEX(17)       /* Limit */
+    .long gdt - 8       /* Base Address */
+
+PUBLIC cmdline
+cmdline:
+    .space CMDLINE_SIZE
 
-/* Initial GDT table pointer for multiboot */
-gdtptrhigh:
-       .word HEX(27)           /* Limit */
-       .long gdt + INITIAL_BASE - FREELDR_BASE /* Base Address */
+END