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>
27 * Allows freeldr to be loaded as a "multiboot kernel" by
28 * other boot loaders like Grub
29 * This code is not referenced from anywhere. GRUB searches for
30 * the header signature and uses the header to load it.
33 #define MB_INFO_SIZE 90
34 #define MB_INFO_FLAGS_OFFSET 0
35 #define MB_INFO_BOOT_DEVICE_OFFSET 12
36 #define MB_INFO_COMMAND_LINE_OFFSET 16
37 #define CMDLINE_SIZE 256
40 * We want to execute at 0x8000 (to be compatible with bootsector
41 * loading), but Grub only allows loading of multiboot kernels
42 * above 1MB. So we let Grub load us there and then relocate
45 #define INITIAL_BASE HEX(200000)
47 /* Align 32 bits boundary */
50 /* Multiboot header */
53 .long MULTIBOOT_HEADER_MAGIC
55 .long MULTIBOOT_HEADER_FLAGS
57 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
59 .long INITIAL_BASE + MultibootHeader - FREELDR_BASE
63 .long INITIAL_BASE + __bss_start__ - FREELDR_BASE
65 .long INITIAL_BASE + __bss_end__ - FREELDR_BASE
67 .long INITIAL_BASE + MultibootEntry - FREELDR_BASE
70 cli /* Even after setting up the our IDT below we are
71 * not ready to handle hardware interrupts (no entries
72 * in IDT), so there's no sti here. Interrupts will be
73 * enabled in due time */
75 /* Although the multiboot spec says we should be called with the
76 * segment registers set to 4GB flat mode, let's be sure and set up
78 lgdt gdtptrhigh + INITIAL_BASE - FREELDR_BASE
79 /* Reload segment selectors */
80 //ljmp $PMODE_CS, $(mb1 + INITIAL_BASE - FREELDR_BASE)
81 jmp far ptr PMODE_CS: (mb1 + INITIAL_BASE - FREELDR_BASE)
87 /* Check for valid multiboot signature */
88 cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
91 /* Store multiboot info in a safe place */
93 mov edi, offset mb_info + INITIAL_BASE - FREELDR_BASE
97 /* Save commandline */
98 mov edx, [ebx + MB_INFO_FLAGS_OFFSET]
99 test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
101 mov esi, [ebx + MB_INFO_COMMAND_LINE_OFFSET]
102 mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
103 mov ecx, CMDLINE_SIZE
112 /* Copy to low mem */
113 mov esi, INITIAL_BASE
114 mov edi, FREELDR_BASE
115 mov ecx, (offset __bss_end__ - FREELDR_BASE)
120 /* Load the GDT and IDT */
124 /* Clear prefetch queue & correct CS,
126 //ljmp $PMODE_CS, $mb4
127 jmp far ptr PMODE_CS:mb4
129 /* Reload segment selectors */
138 mov ebx, offset mb_info
139 /* See if the boot device was passed in */
140 mov edx, [ebx + MB_INFO_FLAGS_OFFSET]
141 test edx, MB_INFO_FLAG_BOOT_DEVICE
143 /* Retrieve boot device info */
144 mov eax, [ebx + MB_INFO_BOOT_DEVICE_OFFSET]
147 mov byte ptr [_FrldrBootPartition], al
148 mov byte ptr [_FrldrBootDrive], ah
150 mb5: /* No boot device known, assume first partition of first harddisk */
151 mov byte ptr [_FrldrBootDrive], HEX(80)
152 mov byte ptr [_FrldrBootPartition], 1
154 /* Check for command line */
155 mov eax, offset cmdline
156 test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
167 mbstop: jmp mbstop /* We should never get here */
170 .fill MB_INFO_SIZE, 1, 0
173 .fill CMDLINE_SIZE, 1, 0
175 .align 4 /* force 4-byte alignment */
177 /* NULL Descriptor */
195 /* 16-bit real mode CS */
201 /* 16-bit real mode DS */
207 /* GDT table pointer */
209 .word HEX(27) /* Limit */
210 .long gdt /* Base Address */
212 /* Initial GDT table pointer for multiboot */
214 .word HEX(27) /* Limit */
215 .long gdt + INITIAL_BASE - FREELDR_BASE /* Base Address */