From 6e9cef58d178d66753a11ed62726166a7a2f23c7 Mon Sep 17 00:00:00 2001 From: Dmitry Gorbachev Date: Tue, 20 Sep 2011 08:50:38 +0000 Subject: [PATCH] [FREELDR] Fix loading with GRUB (CMake builds). svn path=/trunk/; revision=53765 --- reactos/boot/freeldr/freeldr/CMakeLists.txt | 10 +- .../boot/freeldr/freeldr/arch/i386/entry.S | 8 +- .../freeldr/freeldr/arch/i386/multiboot.S | 253 +++++++----------- 3 files changed, 111 insertions(+), 160 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/CMakeLists.txt b/reactos/boot/freeldr/freeldr/CMakeLists.txt index 7ff378980ec..57a86a98b7b 100644 --- a/reactos/boot/freeldr/freeldr/CMakeLists.txt +++ b/reactos/boot/freeldr/freeldr/CMakeLists.txt @@ -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() diff --git a/reactos/boot/freeldr/freeldr/arch/i386/entry.S b/reactos/boot/freeldr/freeldr/arch/i386/entry.S index d1f6402889f..61d44b08038 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/entry.S +++ b/reactos/boot/freeldr/freeldr/arch/i386/entry.S @@ -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 diff --git a/reactos/boot/freeldr/freeldr/arch/i386/multiboot.S b/reactos/boot/freeldr/freeldr/arch/i386/multiboot.S index 5c1e7241dd1..72a40c49e2f 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/multiboot.S +++ b/reactos/boot/freeldr/freeldr/arch/i386/multiboot.S @@ -21,195 +21,138 @@ #include #include - /* 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 */ + cld - /* 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) + /* 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 + lodsb + stosb + test al, al + jz mb2 + dec ecx + jnz mb1 - /* Check for valid multiboot signature */ - cmp eax, MULTIBOOT_BOOTLOADER_MAGIC - jne mbfail +mb2: + /* See if the boot device was passed in */ + test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_BOOT_DEVICE - /* 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 + /* 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 - /* 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: + /* 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 - /* 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 + /* Clean out bss */ + xor eax, eax + mov ecx, offset __bss_end__ + 3 + sub ecx, offset __bss_start__ + shr ecx, 2 + rep stosd - /* Load the GDT and IDT */ - lgdt gdtptr - lidt i386idtptr + /* 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 - /* Clear prefetch queue & correct CS, - * jump to low mem */ - //ljmp $PMODE_CS, $mb4 - jmp far ptr PMODE_CS:mb4 + /* 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 + /* Disable protected mode */ + mov eax, cr0 + and eax, CR0_PE_CLR + mov cr0, eax - 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: + /* Jump to real entry point */ + ljmp16 0, FREELDR_BASE - /* GO! */ - push eax - call _BootMain - -mbfail: - int 3 -mbstop: jmp mbstop /* We should never get here */ - -mb_info: - .fill MB_INFO_SIZE, 1, 0 - -cmdline: - .fill CMDLINE_SIZE, 1, 0 - -.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) + /* 16-bit flat CS (!) */ + .word HEX(FFFF) + .word HEX(0000) + .word HEX(9B00) + .word HEX(008F) - /* 32-bit flat CS */ - .word HEX(FFFF) - .word HEX(0000) - .word HEX(9A00) - .word HEX(00CF) + /* 16-bit real mode DS */ + .word HEX(FFFF) + .word HEX(0000) + .word HEX(9300) + .word HEX(0000) - /* 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 */ + /* GDT pointer */ gdtptr: - .word HEX(27) /* Limit */ - .long gdt /* Base Address */ + .word HEX(17) /* Limit */ + .long gdt - 8 /* Base Address */ -/* Initial GDT table pointer for multiboot */ -gdtptrhigh: - .word HEX(27) /* Limit */ - .long gdt + INITIAL_BASE - FREELDR_BASE /* Base Address */ +PUBLIC cmdline +cmdline: + .space CMDLINE_SIZE + +END