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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <multiboot.h>
28 EXTERN(RealEntryPoint)
32 /* Setup segment registers */
49 /* Store the boot drive */
52 /* Store the boot partition */
53 movb %dh,(_BootPartition)
65 /* We should never get here */
72 * Switches the processor to protected mode
75 EXTERN(switch_to_prot)
79 cli /* None of these */
81 /* We don't know what values are currently */
82 /* in the segment registers. So we are */
83 /* going to reload them with sane values. */
84 /* Of course CS has to already be valid. */
85 /* We are currently in real-mode so we */
86 /* need real-mode segment values. */
94 /* Get the return address off the stack */
97 /* Save 16-bit stack pointer */
105 /* Enable Protected Mode */
110 /* Clear prefetch queue & correct CS */
111 ljmp $PMODE_CS, $inpmode
117 /* Setup segment selectors */
126 /* Put the return address back onto the stack */
129 /* Now return in p-mode! */
133 * Switches the processor back to real mode
136 EXTERN(switch_to_real)
140 /* We don't know what values are currently */
141 /* in the segment registers. So we are */
142 /* going to reload them with sane values. */
143 /* Of course CS has to already be valid. */
144 /* We are currently in protected-mode so we */
145 /* need protected-mode segment values. */
153 /* Get the return address off the stack */
156 /* Save 32-bit stack pointer */
159 /* jmp to 16-bit segment to set the limit correctly */
160 ljmp $RMODE_CS, $switch_to_real16
165 /* Restore segment registers to correct limit */
173 /* Disable Protected Mode */
175 andl $CR0_PE_CLR,%eax
178 /* Clear prefetch queue & correct CS */
189 /* Clear out the high 16-bits of ESP */
190 /* This is needed because I have one */
191 /* machine that hangs when booted to dos if */
192 /* anything other than 0x0000 is in the high */
193 /* 16-bits of ESP. Even though real-mode */
194 /* code should only use SP and not ESP. */
199 /* Put the return address back onto the stack */
202 /* Load IDTR with real mode value */
205 sti /* These are ok now */
207 /* Now return in r-mode! */
212 * Needed for enabling the a20 address line
216 .word 0x00eb,0x00eb // jmp $+2, jmp $+2
223 * Enable the A20 address line (to allow access to over 1mb)
234 movb $0xD1,%al // command write
237 mov $0xDF,%al // A20 on
248 * Disable the A20 address line
259 movb $0xD1,%al // command write
262 mov $0xDD,%al // A20 off
274 * Allows freeldr to be loaded as a "multiboot kernel" by
275 * other boot loaders like Grub
278 #define MB_INFO_FLAGS_OFFSET 0
279 #define MB_INFO_BOOT_DEVICE_OFFSET 12
280 #define MB_INFO_COMMAND_LINE_OFFSET 16
283 * We want to execute at 0x8000 (to be compatible with bootsector
284 * loading), but Grub only allows loading of multiboot kernels
285 * above 1MB. So we let Grub load us there and then relocate
288 #define CMDLINE_BASE 0x7000
289 #define FREELDR_BASE 0x8000
290 #define INITIAL_BASE 0x200000
292 /* Align 32 bits boundary */
295 /* Multiboot header */
298 .long MULTIBOOT_HEADER_MAGIC
300 .long MULTIBOOT_HEADER_FLAGS
302 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
304 .long INITIAL_BASE + MultibootHeader - FREELDR_BASE
308 .long INITIAL_BASE + __bss_start__ - FREELDR_BASE
310 .long INITIAL_BASE + __bss_end__ - FREELDR_BASE
312 .long INITIAL_BASE + MultibootEntry - FREELDR_BASE
315 cli /* Even after setting up the our IDT below we are
316 * not ready to handle hardware interrupts (no entries
317 * in IDT), so there's no sti here. Interrupts will be
318 * enabled in due time */
320 /* Although the multiboot spec says we should be called with the
321 * segment registers set to 4GB flat mode, let's be sure and set up
323 lgdt gdtptrhigh + INITIAL_BASE - FREELDR_BASE
324 /* Reload segment selectors */
325 ljmp $PMODE_CS, $(mb1 + INITIAL_BASE - FREELDR_BASE)
331 /* Copy to low mem */
332 movl $INITIAL_BASE,%esi
333 movl $FREELDR_BASE,%edi
334 movl $(__bss_end__ - FREELDR_BASE),%ecx
339 /* Load the GDT and IDT */
343 /* Clear prefetch queue & correct CS,
347 /* Reload segment selectors */
354 movl $STACK32ADDR,%esp
356 /* Check for valid multiboot signature */
357 cmpl $MULTIBOOT_BOOTLOADER_MAGIC,%eax
360 /* See if the boot device was passed in */
361 movl MB_INFO_FLAGS_OFFSET(%ebx),%edx
362 testl $MB_INFO_FLAG_BOOT_DEVICE,%edx
364 /* Retrieve boot device info */
365 movl MB_INFO_BOOT_DEVICE_OFFSET(%ebx),%eax
368 movb %al,_BootPartition
371 mb3: /* No boot device known, assume first partition of first harddisk */
372 movb $0x80,_BootDrive
373 movb $1,_BootPartition
376 /* Check for a command line */
378 testl $MB_INFO_FLAG_COMMAND_LINE,%edx
380 /* Copy command line to low mem*/
381 movl MB_INFO_COMMAND_LINE_OFFSET(%ebx),%esi
382 movl $CMDLINE_BASE,%edi
387 movl $CMDLINE_BASE,%eax
394 mbfail: call switch_to_real
397 mbstop: jmp mbstop /* We should never get here */
401 /* 16-bit stack pointer */
405 /* 32-bit stack pointer */
409 /* 16-bit return address */
413 /* 32-bit return address */
418 .p2align 2 /* force 4-byte alignment */
420 /* NULL Descriptor */
438 /* 16-bit real mode CS */
444 /* 16-bit real mode DS */
450 /* GDT table pointer */
452 .word 0x27 /* Limit */
453 .long gdt /* Base Address */
455 /* Initial GDT table pointer for multiboot */
457 .word 0x27 /* Limit */
458 .long gdt + INITIAL_BASE - FREELDR_BASE /* Base Address */
460 /* Real-mode IDT pointer */
462 .word 0x3ff /* Limit */
463 .long 0 /* Base Address */
468 EXTERN(_BootPartition)