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_SIZE 60 /* sizeof(multiboot_info_t) */
33 #define MB_INFO_FLAGS_OFFSET 0
34 #define MB_INFO_BOOT_DEVICE_OFFSET 12
35 #define MB_INFO_COMMAND_LINE_OFFSET 16
36 #define MB_INFO_MMAP_LEN_OFFSET 44
37 #define MB_INFO_MMAP_ADDR_OFFSET 48
38 #define MB_MMAP_SIZE 480 /* 20 * sizeof(memory_map_t) - up to 20 entries */
39 #define CMDLINE_SIZE 256
42 * We want to execute at FREELDR_BASE (to be compatible with
43 * bootsector loading), but GRUB only allows loading of
44 * multiboot kernels above 1MB. So we let GRUB load us
45 * there and then relocate ourself to FREELDR_BASE.
47 #define INITIAL_BASE HEX(200000)
51 EXTERN __bss_start__:DWORD
52 EXTERN __bss_end__:DWORD
57 .MBDATA SEGMENT PUBLIC 'DATA'
61 /* Align to 32 bits boundary */
64 /* Multiboot header */
67 .long MULTIBOOT_HEADER_MAGIC
69 .long MULTIBOOT_HEADER_FLAGS
71 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
73 .long MultibootHeader + INITIAL_BASE - FREELDR_BASE
81 .long MultibootEntry + INITIAL_BASE - FREELDR_BASE
89 ASSUME ES:NOTHING, FS:NOTHING, GS:NOTHING
94 /* Check for valid multiboot signature */
95 cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
98 /* Save multiboot info structure */
100 mov edi, offset MultibootInfo + INITIAL_BASE - FREELDR_BASE
101 mov ecx, (MB_INFO_SIZE / 4)
103 mov dword ptr ds:[MultibootInfo + INITIAL_BASE - FREELDR_BASE + MB_INFO_MMAP_ADDR_OFFSET], 0
104 mov dword ptr ds:[_MultibootInfoPtr + INITIAL_BASE - FREELDR_BASE], offset MultibootInfo
106 /* See if the memory map was passed in */
107 test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_MEMORY_MAP
108 jz mbchk_command_line
109 /* Check memory map length */
110 mov ecx, dword ptr ds:[ebx + MB_INFO_MMAP_LEN_OFFSET]
112 jz mbchk_command_line
113 cmp ecx, MB_MMAP_SIZE
114 jg mbchk_command_line
115 /* Check memory map address */
116 mov esi, dword ptr ds:[ebx + MB_INFO_MMAP_ADDR_OFFSET]
118 jz mbchk_command_line
119 /* Save memory map structure */
120 mov edi, offset MultibootMemoryMap + INITIAL_BASE - FREELDR_BASE
123 /* Relocate memory map address */
124 mov dword ptr ds:[MultibootInfo + INITIAL_BASE - FREELDR_BASE + MB_INFO_MMAP_ADDR_OFFSET], offset MultibootMemoryMap
127 /* Save command line */
128 test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
130 mov esi, dword ptr ds:[ebx + MB_INFO_COMMAND_LINE_OFFSET]
131 mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
132 mov ecx, CMDLINE_SIZE - 1
142 /* See if the boot device was passed in */
143 test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_BOOT_DEVICE
145 /* If no boot device known, assume first partition of first harddisk */
149 /* Load boot drive into DL, boot partition into DH */
150 mov edx, dword ptr ds:[ebx + MB_INFO_BOOT_DEVICE_OFFSET]
155 /* Relocate itself to lower address */
156 mov esi, INITIAL_BASE
157 mov edi, FREELDR_BASE
158 mov ecx, offset __bss_start__ - FREELDR_BASE
162 /* Load segment registers for real-address mode */
164 lgdt fword ptr ds:[gdtptr]
175 /* Jump to relocated code */
181 jmp short mbstop /* We should never get here */
185 /* Disable protected mode */
190 /* Jump to real entry point */
191 ljmp16 0, FREELDR_BASE
195 /* Force 8-byte alignment */
198 .word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 00: NULL descriptor */
199 .word HEX(FFFF), HEX(0000), HEX(9B00), HEX(008F) /* 08: 16-bit flat CS (!) */
200 .word HEX(FFFF), HEX(0000), HEX(9300), HEX(0000) /* 10: 16-bit real mode DS */
202 /* GDT table pointer */
204 .word HEX(17) /* Limit */
205 .long gdt /* Base Address */
207 PUBLIC _MultibootInfoPtr