3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <arch/pc/x86common.h>
22 #include <multiboot.h>
26 * Allows freeldr to be loaded as a "multiboot kernel" by
27 * other boot loaders like GRUB.
28 * This code is not referenced from anywhere. GRUB searches for
29 * the header signature and uses the header to load it.
32 #define MB_INFO_FLAGS_OFFSET 0
33 #define MB_INFO_BOOT_DEVICE_OFFSET 12
34 #define MB_INFO_COMMAND_LINE_OFFSET 16
35 #define CMDLINE_SIZE 256
38 * We want to execute at FREELDR_BASE (to be compatible with
39 * bootsector loading), but GRUB only allows loading of
40 * multiboot kernels above 1MB. So we let GRUB load us
41 * there and then relocate ourself to FREELDR_BASE.
43 #define INITIAL_BASE HEX(200000)
47 EXTERN __bss_start__:DWORD
48 EXTERN __bss_end__:DWORD
53 .MBDATA SEGMENT PUBLIC 'DATA'
57 /* Align to 32 bits boundary */
60 /* Multiboot header */
63 .long MULTIBOOT_HEADER_MAGIC
65 .long MULTIBOOT_HEADER_FLAGS
67 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
69 .long MultibootHeader + INITIAL_BASE - FREELDR_BASE
77 .long MultibootEntry + INITIAL_BASE - FREELDR_BASE
85 ASSUME ES:NOTHING, FS:NOTHING, GS:NOTHING
90 /* Check for valid multiboot signature */
91 cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
94 /* Save command line */
95 test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
97 mov esi, dword ptr ds:[ebx + MB_INFO_COMMAND_LINE_OFFSET]
98 mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
99 mov ecx, CMDLINE_SIZE - 1
109 /* See if the boot device was passed in */
110 test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_BOOT_DEVICE
112 /* If no boot device known, assume first partition of first harddisk */
116 /* Load boot drive into DL, boot partition into DH */
117 mov edx, dword ptr ds:[ebx + MB_INFO_BOOT_DEVICE_OFFSET]
122 /* Relocate itself to lower address */
123 mov esi, INITIAL_BASE
124 mov edi, FREELDR_BASE
125 mov ecx, offset __bss_start__ - FREELDR_BASE
129 /* Load segment registers for real-address mode */
131 lgdt fword ptr ds:[gdtptr]
142 /* Jump to relocated code */
148 jmp short mbstop /* We should never get here */
152 /* Disable protected mode */
157 /* Jump to real entry point */
158 ljmp16 0, FREELDR_BASE
162 /* Force 8-byte alignment */
165 .word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 00: NULL descriptor */
166 .word HEX(FFFF), HEX(0000), HEX(9B00), HEX(008F) /* 08: 16-bit flat CS (!) */
167 .word HEX(FFFF), HEX(0000), HEX(9300), HEX(0000) /* 10: 16-bit real mode DS */
169 /* GDT table pointer */
171 .word HEX(17) /* Limit */
172 .long gdt /* Base Address */