[FREELDR]

Fix loading with GRUB (CMake builds).

svn path=/trunk/; revision=53765
This commit is contained in:
Dmitry Gorbachev 2011-09-20 08:50:38 +00:00
parent 78f25bbeea
commit 6e9cef58d1
3 changed files with 111 additions and 160 deletions

View file

@ -117,8 +117,7 @@ if(ARCH MATCHES i386)
disk/scsiport.c) disk/scsiport.c)
if(NOT MSVC) if(NOT MSVC)
list(APPEND FREELDR_COMMON_SOURCE list(APPEND FREELDR_COMMON_SOURCE
arch/i386/drvmap.S arch/i386/drvmap.S)
arch/i386/multiboot.S)
endif() endif()
elseif(ARCH MATCHES amd64) elseif(ARCH MATCHES amd64)
list(APPEND FREELDR_COMMON_SOURCE list(APPEND FREELDR_COMMON_SOURCE
@ -148,6 +147,9 @@ endif()
add_library(freeldr_common ${FREELDR_COMMON_SOURCE}) add_library(freeldr_common ${FREELDR_COMMON_SOURCE})
add_dependencies(freeldr_common bugcodes) 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 list(APPEND FREELDR_BASE_SOURCE
bootmgr.c # This file is compiled with custom definitions 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}) add_executable(freeldr_pe ${FREELDR_BASE_SOURCE})
if(NOT MSVC) 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() 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") 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() endif()
@ -208,7 +210,7 @@ endif()
add_executable(setupldr_pe ${FREELDR_BASE_SOURCE} ${SETUPLDR_SOURCE}) add_executable(setupldr_pe ${FREELDR_BASE_SOURCE} ${SETUPLDR_SOURCE})
if(NOT MSVC) 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() 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") 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() endif()

View file

@ -70,8 +70,14 @@ _FrldrStartup:
/* Initialize the idt */ /* Initialize the idt */
call _InitIdt call _InitIdt
/* GO! */ /* Pass the command line to BootMain */
#ifdef _USE_ML
xor eax, eax xor eax, eax
#else
mov eax, offset cmdline
#endif
/* GO! */
push eax push eax
call _BootMain call _BootMain

View file

@ -21,30 +21,28 @@
#include <arch/pc/x86common.h> #include <arch/pc/x86common.h>
#include <multiboot.h> #include <multiboot.h>
/* Multiboot support /* Multiboot support
* *
* Allows freeldr to be loaded as a "multiboot kernel" by * 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 * This code is not referenced from anywhere. GRUB searches for
* the header signature and uses the header to load it. * the header signature and uses the header to load it.
*/ */
#define MB_INFO_SIZE 90
#define MB_INFO_FLAGS_OFFSET 0 #define MB_INFO_FLAGS_OFFSET 0
#define MB_INFO_BOOT_DEVICE_OFFSET 12 #define MB_INFO_BOOT_DEVICE_OFFSET 12
#define MB_INFO_COMMAND_LINE_OFFSET 16 #define MB_INFO_COMMAND_LINE_OFFSET 16
#define CMDLINE_SIZE 256 #define CMDLINE_SIZE 256
/* /*
* We want to execute at 0x8000 (to be compatible with bootsector * We want to execute at FREELDR_BASE (to be compatible with
* loading), but Grub only allows loading of multiboot kernels * bootsector loading), but GRUB only allows loading of
* above 1MB. So we let Grub load us there and then relocate * multiboot kernels above 1MB. So we let GRUB load us
* ourself to 0x8000 * there and then relocate ourself to FREELDR_BASE.
*/ */
#define INITIAL_BASE HEX(200000) #define INITIAL_BASE HEX(200000)
/* Align 32 bits boundary */ /* Align to 32 bits boundary */
.align 4 .align 4
/* Multiboot header */ /* Multiboot header */
@ -62,154 +60,99 @@ MultibootHeader:
/* load_end_addr */ /* load_end_addr */
.long INITIAL_BASE + __bss_start__ - FREELDR_BASE .long INITIAL_BASE + __bss_start__ - FREELDR_BASE
/* bss_end_addr */ /* bss_end_addr */
.long INITIAL_BASE + __bss_end__ - FREELDR_BASE .long 0
/* entry_addr */ /* entry_addr */
.long INITIAL_BASE + MultibootEntry - FREELDR_BASE .long INITIAL_BASE + MultibootEntry - FREELDR_BASE
MultibootEntry: MultibootEntry:
cli /* Even after setting up the our IDT below we are cld
* 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)
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 command line */ /* Save command line */
mov edx, [ebx + MB_INFO_FLAGS_OFFSET]
test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
jz mb3 jz mb2
mov esi, [ebx + MB_INFO_COMMAND_LINE_OFFSET] mov esi, [ebx + MB_INFO_COMMAND_LINE_OFFSET]
mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
mov ecx, CMDLINE_SIZE mov ecx, CMDLINE_SIZE - 1
mb2: lodsb mb1:
lodsb
stosb stosb
test al, al test al, al
jz mb3 jz mb2
dec ecx dec ecx
jnz mb2 jnz mb1
mb3:
/* Copy to low mem */ 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
mb3:
/* Relocate itself to lower address */
mov esi, INITIAL_BASE mov esi, INITIAL_BASE
mov edi, FREELDR_BASE mov edi, FREELDR_BASE
mov ecx, (offset __bss_end__ - FREELDR_BASE) mov ecx, (offset __bss_start__ - FREELDR_BASE + 3)
add ecx, 3
shr ecx, 2 shr ecx, 2
rep movsd rep movsd
/* Load the GDT and IDT */ /* Clean out bss */
lgdt gdtptr
lidt i386idtptr
/* Clear prefetch queue & correct CS,
* jump to low mem */
//ljmp $PMODE_CS, $mb4
jmp far ptr PMODE_CS:mb4
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 xor eax, eax
mb7: mov ecx, offset __bss_end__ + 3
sub ecx, offset __bss_start__
shr ecx, 2
rep stosd
/* GO! */ /* Load segment registers for real-address mode */
push eax lgdt gdtptr
call _BootMain mov ax, HEX(10)
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mbfail: /* Jump to relocated code */
int 3 ljmp HEX(08), mb4
mbstop: jmp mbstop /* We should never get here */
mb_info: .code16
.fill MB_INFO_SIZE, 1, 0 mb4:
/* Disable protected mode */
mov eax, cr0
and eax, CR0_PE_CLR
mov cr0, eax
cmdline: /* Jump to real entry point */
.fill CMDLINE_SIZE, 1, 0 ljmp16 0, FREELDR_BASE
.align 4 /* force 4-byte alignment */ /* Force 8-byte alignment */
.align 8
gdt: gdt:
/* NULL Descriptor */ /* 16-bit flat CS (!) */
.word HEX(0000)
.word HEX(0000)
.word HEX(0000)
.word HEX(0000)
/* 32-bit flat CS */
.word HEX(FFFF) .word HEX(FFFF)
.word HEX(0000) .word HEX(0000)
.word HEX(9A00) .word HEX(9B00)
.word HEX(00CF) .word HEX(008F)
/* 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 */ /* 16-bit real mode DS */
.word HEX(FFFF) .word HEX(FFFF)
.word HEX(0000) .word HEX(0000)
.word HEX(9200) .word HEX(9300)
.word HEX(0000) .word HEX(0000)
/* GDT table pointer */ /* GDT pointer */
gdtptr: gdtptr:
.word HEX(27) /* Limit */ .word HEX(17) /* Limit */
.long gdt /* Base Address */ .long gdt - 8 /* Base Address */
/* Initial GDT table pointer for multiboot */ PUBLIC cmdline
gdtptrhigh: cmdline:
.word HEX(27) /* Limit */ .space CMDLINE_SIZE
.long gdt + INITIAL_BASE - FREELDR_BASE /* Base Address */
END