reactos/boot/freeldr/freeldr/arch/i386/multiboot.S
Hermès Bélusca-Maïto 6b1e1df5c9
[FREELDR] Re-integrate the ASM files (and corresponding C code) in MSVC builds, that were previously compiled just for GCC builds. (#1224)
- Multiboot support added back in FreeLdr MSVC builds so that it can be
  booted using e.g. GRUB. See CORE-15563.

- Re-introduce the disk drive mapper code.
2019-01-27 00:51:26 +01:00

179 lines
4.3 KiB
ArmAsm

/*
* FreeLoader
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <asm.inc>
#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.
* This code is not referenced from anywhere. GRUB searches for
* the header signature and uses the header to load it.
*/
#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 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)
#ifdef _USE_ML
EXTERN __bss_start__:DWORD
EXTERN __bss_end__:DWORD
#endif
#ifdef _USE_ML
.MBDATA SEGMENT PUBLIC 'DATA'
ASSUME nothing
#endif
/* Align to 32 bits boundary */
.align 4
/* Multiboot header */
MultibootHeader:
/* magic */
.long MULTIBOOT_HEADER_MAGIC
/* flags */
.long MULTIBOOT_HEADER_FLAGS
/* checksum */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
/* header_addr */
.long MultibootHeader + INITIAL_BASE - FREELDR_BASE
/* load_addr */
.long INITIAL_BASE
/* load_end_addr */
.long 0
/* bss_end_addr */
.long 0
/* entry_addr */
.long MultibootEntry + INITIAL_BASE - FREELDR_BASE
#ifdef _USE_ML
.MBDATA ENDS
#endif
.code32
ASSUME ES:NOTHING, FS:NOTHING, GS:NOTHING
MultibootEntry:
cld
/* Check for valid multiboot signature */
cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
jne mbfail
/* Save command line */
test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
jz mb2
mov esi, dword ptr ds:[ebx + MB_INFO_COMMAND_LINE_OFFSET]
mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
mov ecx, CMDLINE_SIZE - 1
mb1:
lodsb
stosb
test al, al
jz mb2
dec ecx
jnz mb1
mb2:
/* See if the boot device was passed in */
test dword ptr ds:[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, dword ptr ds:[ebx + MB_INFO_BOOT_DEVICE_OFFSET]
bswap edx
inc dh
mb3:
/* Relocate itself to lower address */
mov esi, INITIAL_BASE
mov edi, FREELDR_BASE
mov ecx, offset __bss_start__ - FREELDR_BASE
shr ecx, 2
rep movsd
/* Load segment registers for real-address mode */
#ifdef _USE_ML
lgdt fword ptr ds:[gdtptr]
#else
lgdt ds:[gdtptr]
#endif
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
mbfail:
int 3
mbstop:
jmp short mbstop /* We should never get here */
.code16
mb4:
/* Disable protected mode */
mov eax, cr0
and eax, CR0_PE_CLR
mov cr0, eax
/* Jump to real entry point */
ljmp16 0, FREELDR_BASE
.endcode16
/* Force 8-byte alignment */
.align 8
gdt:
.word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 00: NULL descriptor */
.word HEX(FFFF), HEX(0000), HEX(9B00), HEX(008F) /* 08: 16-bit flat CS (!) */
.word HEX(FFFF), HEX(0000), HEX(9300), HEX(0000) /* 10: 16-bit real mode DS */
/* GDT table pointer */
gdtptr:
.word HEX(17) /* Limit */
.long gdt /* Base Address */
PUBLIC cmdline
cmdline:
.space CMDLINE_SIZE
END