diff --git a/boot/freeldr/freeldr/CMakeLists.txt b/boot/freeldr/freeldr/CMakeLists.txt index ff7731e6bac..88c1c2a528c 100644 --- a/boot/freeldr/freeldr/CMakeLists.txt +++ b/boot/freeldr/freeldr/CMakeLists.txt @@ -5,6 +5,74 @@ if(SEPARATE_DBG) set(CMAKE_LDR_PE_HELPER_STANDARD_LIBRARIES "-lgcc" CACHE STRING "Standard C Libraries") endif() +if(NOT MSVC) +### +### For GCC +### +function(add_linker_script _target _linker_script_file) + get_filename_component(_file_full_path ${_linker_script_file} ABSOLUTE) + add_target_link_flags(${_target} "-Wl,-T,${_file_full_path}") + + # Unfortunately LINK_DEPENDS is ignored in non-Makefile generators (for now...) + # See also http://www.cmake.org/pipermail/cmake/2010-May/037206.html + add_target_property(${_target} LINK_DEPENDS ${_file_full_path}) +endfunction() + +else() +### +### For MSVC +### +function(add_linker_script _target _linker_script_file) + get_filename_component(_file_full_path ${_linker_script_file} ABSOLUTE) + get_filename_component(_file_name ${_linker_script_file} NAME) + set(_generated_file_path_prefix "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_target}.dir/${_file_name}") + + # Generate the ASM module containing sections specifications and layout. + set(_generated_file "${_generated_file_path_prefix}.S") + add_custom_command( + OUTPUT ${_generated_file} + COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_file_full_path}" "${_generated_file}" + DEPENDS ${_file_full_path}) + set_source_files_properties(${_generated_file} PROPERTIES LANGUAGE "ASM" GENERATED TRUE) + add_asm_files(freeldr_linker_file ${_generated_file}) + + # Generate the C module containing extra sections specifications and layout, + # as well as comment-type linker #pragma directives. + set(_generated_file "${_generated_file_path_prefix}.c") + add_custom_command( + OUTPUT ${_generated_file} + COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_file_full_path}" "${_generated_file}" + DEPENDS ${_file_full_path}) + set_source_files_properties(${_generated_file} PROPERTIES LANGUAGE "C" GENERATED TRUE) + list(APPEND freeldr_linker_file ${_generated_file}) + + # Add both files to the sources of the target. + target_sources(${_target} PRIVATE ${freeldr_linker_file}) + + # Create the additional linker response file. + set(_generated_file "${_generated_file_path_prefix}.rsp") + if(USE_CLANG_CL) + set(_no_std_includes_flag "-nostdinc") + else() + set(_no_std_includes_flag "/X") + endif() + add_custom_command( + #OUTPUT ${_generated_file} + TARGET ${_target} PRE_LINK + COMMAND ${CMAKE_C_COMPILER} /nologo ${_no_std_includes_flag} /D__LINKER__ /EP /c "${_file_full_path}" > "${_generated_file}" + DEPENDS ${_file_full_path} + VERBATIM) + set_source_files_properties(${_generated_file} PROPERTIES GENERATED TRUE) + add_target_link_flags(${_target} "@${_generated_file}") + + # Unfortunately LINK_DEPENDS is ignored in non-Makefile generators (for now...) + # See also http://www.cmake.org/pipermail/cmake/2010-May/037206.html + add_target_property(${_target} LINK_DEPENDS ${_generated_file}) +endfunction() + +endif() + + if(MSVC) # We don't need hotpatching replace_compile_flags("/hotpatch" " ") @@ -238,12 +306,16 @@ if(MSVC) add_target_link_flags(freeldr_pe "/ignore:4078 /ignore:4254 /DRIVER") add_target_link_flags(freeldr_pe_dbg "/ignore:4078 /ignore:4254 /DRIVER") else() - add_target_link_flags(freeldr_pe "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:INIT=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text") - add_target_link_flags(freeldr_pe_dbg "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:INIT=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text") + add_target_link_flags(freeldr_pe "/ignore:4078 /ignore:4254 /DRIVER /FIXED /FILEALIGN:0x200 /ALIGN:0x200") + add_linker_script(freeldr_pe freeldr_i386.msvc.lds) + add_target_link_flags(freeldr_pe_dbg "/ignore:4078 /ignore:4254 /DRIVER /FIXED /FILEALIGN:0x200 /ALIGN:0x200") + add_linker_script(freeldr_pe_dbg freeldr_i386.msvc.lds) endif() else() - add_target_link_flags(freeldr_pe "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lds") - add_target_link_flags(freeldr_pe_dbg "-Wl,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lds") + add_target_link_flags(freeldr_pe "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x200,--section-alignment,0x200") + add_linker_script(freeldr_pe freeldr_i386.lds) + add_target_link_flags(freeldr_pe_dbg "-Wl,--exclude-all-symbols,--file-alignment,0x200,--section-alignment,0x200") + add_linker_script(freeldr_pe_dbg freeldr_i386.lds) endif() set_image_base(freeldr_pe 0x10000) diff --git a/boot/freeldr/freeldr/arch/amd64/entry.S b/boot/freeldr/freeldr/arch/amd64/entry.S index 075778f8847..e5620bd3005 100644 --- a/boot/freeldr/freeldr/arch/amd64/entry.S +++ b/boot/freeldr/freeldr/arch/amd64/entry.S @@ -3,6 +3,12 @@ #include EXTERN BootMain:PROC +// EXTERN cmdline:DWORD + +#ifdef _USE_ML +EXTERN __bss_start__:FWORD +EXTERN __bss_end__:FWORD +#endif .code64 @@ -40,13 +46,24 @@ FrldrStartup: mov eax, dword ptr [BSS_RealModeEntry] mov dword ptr [AddressOfRealModeEntryPoint], eax - /* GO! */ + /* Clean out BSS */ + xor rax, rax + mov rdi, offset __bss_start__ + mov rcx, offset __bss_end__ + 7 + sub rcx, rdi + shr rcx, 3 + rep stosq + + /* Pass the command line to BootMain */ + // mov rcx, offset cmdline xor rcx, rcx + + /* GO! */ call BootMain /* We should never get here */ stop: - jmp stop + jmp short stop nop nop diff --git a/boot/freeldr/freeldr/arch/i386/entry.S b/boot/freeldr/freeldr/arch/i386/entry.S index 90a40272d4f..6e2b1826de0 100644 --- a/boot/freeldr/freeldr/arch/i386/entry.S +++ b/boot/freeldr/freeldr/arch/i386/entry.S @@ -25,6 +25,12 @@ EXTERN _BootMain:PROC EXTERN _InitIdt:PROC EXTERN _i386Idt:DWORD //EXTERN _i386idtptr:FWORD +// EXTERN cmdline:DWORD + +#ifdef _USE_ML +EXTERN __bss_start__:DWORD +EXTERN __bss_end__:DWORD +#endif .code32 @@ -59,6 +65,8 @@ ContinueAddress: _FrldrStartup: +ASSUME /*CS:_TEXT,*/ DS:_DATA, ES:_DATA, FS:_DATA, GS:_DATA, SS:_DATA + /* Store BootDrive and BootPartition */ mov byte ptr ds:[_FrldrBootDrive], dl xor eax, eax @@ -69,11 +77,7 @@ _FrldrStartup: mov eax, dword ptr ds:[BSS_RealModeEntry] mov dword ptr ds:[SwitchToReal16Address], eax - /* Initialize the idt */ - call _InitIdt - -#ifndef _USE_ML - /* Clean out bss */ + /* Clean out BSS */ xor eax, eax mov edi, offset __bss_start__ mov ecx, offset __bss_end__ + 3 @@ -81,11 +85,12 @@ _FrldrStartup: shr ecx, 2 rep stosd + /* Initialize the idt */ + call _InitIdt + /* Pass the command line to BootMain */ - mov eax, offset cmdline -#else + // mov eax, offset cmdline xor eax, eax -#endif /* GO! */ push eax @@ -93,7 +98,7 @@ _FrldrStartup: /* We should never get here */ stop: - jmp stop + jmp short stop nop nop @@ -181,7 +186,7 @@ SwitchToReal: mov ss, ax /* Save 32-bit stack pointer */ - mov dword ptr [stack32], esp + mov dword ptr ds:[stack32], esp /* jmp to 16-bit segment to set the limit correctly */ .byte HEX(0ea) // jmp far RMODE_CS:switch_to_real16 @@ -236,11 +241,7 @@ gdtptr: .word HEX(27) /* Limit */ .long gdt /* Base Address */ -/* Real-mode IDT pointer */ -rmode_idtptr: - .word HEX(3ff) /* Limit */ - .long 0 /* Base Address */ - +// See _i386IdtDescriptor PUBLIC i386idtptr i386idtptr: .word 255 /* Limit */ diff --git a/boot/freeldr/freeldr/freeldr_i386.lds b/boot/freeldr/freeldr/freeldr_i386.lds index 5cb2cb6c7be..56df8f63ee1 100644 --- a/boot/freeldr/freeldr/freeldr_i386.lds +++ b/boot/freeldr/freeldr/freeldr_i386.lds @@ -12,6 +12,11 @@ SECTIONS *(SORT(.rdata*)) } + /* + * LD needs an explicit .edata block to make the binary correctly export + * symbols, otherwise, if .edata is merged with another section (e.g. .rdata) + * the exports are not exported! + */ .edata BLOCK(__file_alignment__) : { *(.edata) diff --git a/boot/freeldr/freeldr/freeldr_i386.msvc.lds b/boot/freeldr/freeldr/freeldr_i386.msvc.lds new file mode 100644 index 00000000000..061221f2b86 --- /dev/null +++ b/boot/freeldr/freeldr/freeldr_i386.msvc.lds @@ -0,0 +1,78 @@ +/*****************************************************************************\ + *** MSVC Linker Script File -- Sections specifications & layout *** +\*****************************************************************************/ + +#ifndef _MSC_VER +#error This file must be used only with the MSVC compiler and linker. +#endif + +#if defined(__LINKER__) +/*********************************\ + ** Linker response file ** +\*********************************/ + +// /LAST:.bss +/LAST:.data + +#elif !defined(_USE_ML) +/*********************************\ + ** C Linker #pragma directives ** +\*********************************/ + +/* + * Notes about automatic LINK.EXE behaviour that cannot be changed: + * + * - If a .data section is present, the .bss section is appended to it in case + * both of these have either Initialized or Uninitialized data (which is the + * case, unless one has manually modified the attributes). + * + * - If the /DRIVER flag is NOT used, and if both the .rdata and the .edata + * sections (read-only data and exports, respectively) have the same + * attributes, the .edata section is appended to the .rdata section. + * Otherwise they are kept separated, unless an explicit /MERGE is used. + */ + +#pragma comment(linker, "/SECTION:.text,ERW /SECTION:.data,RW /MERGE:INIT=.text /MERGE:.edata=.rdata") + +#endif + + +#if defined(_USE_ML) // && !defined(__LINKER__) +/************************\ + ** ASM definitions ** +\************************/ + +#include + +/* +#pragma bss_seg(".bss") +// __declspec(allocate(".bss")) +void* __bss_start__; +#pragma bss_seg() +*/ +_BSS1 SEGMENT 'BSS' ALIAS('.bss') +PUBLIC __bss_start__ +__bss_start__: + .long ? +_BSS1 ENDS + +/* +#pragma bss_seg(".bss$ZZZ") +// __declspec(allocate(".bss$ZZZ")) +void* __bss_end__; +#pragma bss_seg() +*/ +_BSS2 SEGMENT 'BSS' ALIAS('.bss$ZZZ') +PUBLIC __bss_end__ +__bss_end__: + .long ? +_BSS2 ENDS + +END + +#elif !defined(__LINKER__) +/************************\ + ** C definitions ** +\************************/ + +#endif diff --git a/boot/freeldr/freeldr/include/mm.h b/boot/freeldr/freeldr/include/mm.h index adc13d0ebf5..e86424f17ad 100644 --- a/boot/freeldr/freeldr/include/mm.h +++ b/boot/freeldr/freeldr/include/mm.h @@ -21,15 +21,15 @@ extern char __ImageBase; #ifdef __GNUC__ -/* .text, .edata and .bss */ +/* .text/.data/.rdata, .edata and .bss */ #define FREELDR_SECTION_COUNT 3 #else #ifdef _M_AMD64 -/* .text and .pdata */ -#define FREELDR_SECTION_COUNT 2 +/* .text, .rdata/.edata, .pdata and .data/.bss */ +#define FREELDR_SECTION_COUNT 4 #else -/* .text and .edata */ -#define FREELDR_SECTION_COUNT 2 +/* .text, .rdata/.edata and .data/.bss */ +#define FREELDR_SECTION_COUNT 3 #endif #endif