MATH_OBJS = libgcc2.o
BASE_OBJS = freeldr.o \
- debug.o \
- multiboot.o \
- version.o
+ debug.o \
+ multiboot.o \
+ version.o \
+ cmdline.o
FREELDR_OBJS= bootmgr.o \
- drivemap.o \
- miscboot.o \
- options.o \
- linuxboot.o \
- oslist.o \
- custom.o
+ drivemap.o \
+ miscboot.o \
+ options.o \
+ linuxboot.o \
+ oslist.o \
+ custom.o
ROSLDR_OBJS = reactos.o
#define ASM
#include <arch.h>
+#include <multiboot.h>
EXTERN(RealEntryPoint)
movb %dh,(_BootPartition)
/* GO! */
+ xorl %eax,%eax
+ pushl %eax
call _BootMain
call switch_to_real
.code16
- int $0x19
+ int $0x19
/* We should never get here */
stop:
- jmp stop
+ jmp stop
nop
nop
lidt i386idtptr
/* Enable Protected Mode */
- mov %cr0,%eax
- orl $CR0_PE_SET,%eax
- mov %eax,%cr0
+ mov %cr0,%eax
+ orl $CR0_PE_SET,%eax
+ mov %eax,%cr0
/* Clear prefetch queue & correct CS */
ljmp $PMODE_CS, $inpmode
movw %ax,%ss
/* Disable Protected Mode */
- mov %cr0,%eax
+ mov %cr0,%eax
andl $CR0_PE_CLR,%eax
- mov %eax,%cr0
+ mov %eax,%cr0
/* Clear prefetch queue & correct CS */
ljmp $0, $inrmode
.code16
empty_8042:
.word 0x00eb,0x00eb // jmp $+2, jmp $+2
- inb $0x64,%al
- testb $0x02,%al
- jnz empty_8042
+ inb $0x64,%al
+ testb $0x02,%al
+ jnz empty_8042
ret
/*
.code16
call empty_8042
- movb $0xD1,%al // command write
- outb %al,$0x64
+ movb $0xD1,%al // command write
+ outb %al,$0x64
call empty_8042
- mov $0xDF,%al // A20 on
- out %al,$0x60
+ mov $0xDF,%al // A20 on
+ out %al,$0x60
call empty_8042
call switch_to_prot
.code32
.code16
call empty_8042
- movb $0xD1,%al // command write
- outb %al,$0x64
+ movb $0xD1,%al // command write
+ outb %al,$0x64
call empty_8042
- mov $0xDD,%al // A20 off
- out %al,$0x60
+ mov $0xDD,%al // A20 off
+ out %al,$0x60
call empty_8042
call switch_to_prot
.code32
ret
+/* Multiboot support
+ *
+ * Allows freeldr to be loaded as a "multiboot kernel" by
+ * other boot loaders like Grub
+ */
+
+#define MB_INFO_FLAGS_OFFSET 0
+#define MB_INFO_BOOT_DEVICE_OFFSET 12
+#define MB_INFO_COMMAND_LINE_OFFSET 16
+
+/*
+ * We want to execute at 0x8000 (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 0x8000
+ */
+#define CMDLINE_BASE 0x7000
+#define FREELDR_BASE 0x8000
+#define INITIAL_BASE 0x200000
+
+ /* Align 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 INITIAL_BASE + MultibootHeader - FREELDR_BASE
+ /* load_addr */
+ .long INITIAL_BASE
+ /* load_end_addr */
+ .long INITIAL_BASE + __bss_start__ - FREELDR_BASE
+ /* bss_end_addr */
+ .long INITIAL_BASE + __bss_end__ - FREELDR_BASE
+ /* entry_addr */
+ .long INITIAL_BASE + MultibootEntry - FREELDR_BASE
+
+MultibootEntry:
+ cli /* Even after setting up the our IDT below we are
+ * not ready to handle hardware interrupts (no entries
+ * in IDT), so there's no sti here. Interrupts will be
+ * enabled in due time */
+
+ /* Although the multiboot spec says we should be called with the
+ * segment registers set to 4GB flat mode, let's be sure and set up
+ * our own */
+ lgdt gdtptrhigh + INITIAL_BASE - FREELDR_BASE
+ /* Reload segment selectors */
+ ljmp $PMODE_CS, $(mb1 + INITIAL_BASE - FREELDR_BASE)
+mb1:
+ movw $PMODE_DS,%dx
+ movw %dx,%ds
+ movw %dx,%es
+
+ /* Copy to low mem */
+ movl $INITIAL_BASE,%esi
+ movl $FREELDR_BASE,%edi
+ movl $(__bss_end__ - FREELDR_BASE),%ecx
+ addl $3,%ecx
+ shrl $2,%ecx
+ rep movsl
+
+ /* Load the GDT and IDT */
+ lgdt gdtptr
+ lidt i386idtptr
+ /* Clear prefetch queue & correct CS,
+ * jump to low mem */
+ ljmp $PMODE_CS, $mb2
+mb2:
+ /* Reload segment selectors */
+ movw $PMODE_DS,%dx
+ movw %dx,%ds
+ movw %dx,%es
+ movw %dx,%fs
+ movw %dx,%gs
+ movw %dx,%ss
+ movl $STACK32ADDR,%esp
+
+ /* Check for valid multiboot signature */
+ cmpl $MULTIBOOT_BOOTLOADER_MAGIC,%eax
+ jne mbfail
+
+ /* See if the boot device was passed in */
+ movl MB_INFO_FLAGS_OFFSET(%ebx),%edx
+ testl $MB_INFO_FLAG_BOOT_DEVICE,%edx
+ jz mb3
+ /* Retrieve boot device info */
+ movl MB_INFO_BOOT_DEVICE_OFFSET(%ebx),%eax
+ shrl $16,%eax
+ incb %al
+ movb %al,_BootPartition
+ movb %ah,_BootDrive
+ jmp mb4
+mb3: /* No boot device known, assume first partition of first harddisk */
+ movb $0x80,_BootDrive
+ movb $1,_BootPartition
+mb4:
+
+ /* Check for a command line */
+ xorl %eax,%eax
+ testl $MB_INFO_FLAG_COMMAND_LINE,%edx
+ jz mb6
+ /* Copy command line to low mem*/
+ movl MB_INFO_COMMAND_LINE_OFFSET(%ebx),%esi
+ movl $CMDLINE_BASE,%edi
+mb5: lodsb
+ stosb
+ testb %al,%al
+ jnz mb5
+ movl $CMDLINE_BASE,%eax
+mb6:
+ /* GO! */
+ pushl %eax
+ call _BootMain
+
+mbfail: call switch_to_real
+ .code16
+ int $0x19
+mbstop: jmp mbstop /* We should never get here */
+
+ .code32
/* 16-bit stack pointer */
stack16:
.word 0x27 /* Limit */
.long gdt /* Base Address */
+/* Initial GDT table pointer for multiboot */
+gdtptrhigh:
+ .word 0x27 /* Limit */
+ .long gdt + INITIAL_BASE - FREELDR_BASE /* Base Address */
+
/* Real-mode IDT pointer */
rmode_idtptr:
.word 0x3ff /* Limit */
#include <bootmgr.h>
#include <drivemap.h>
#include <keycodes.h>
+#include <cmdline.h>
VOID RunLoader(VOID)
U32 GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], U32 OperatingSystemCount)
{
UCHAR DefaultOSText[80];
- U32 SectionId;
- U32 DefaultOS = 0;
- U32 Idx;
+ char* DefaultOSName;
+ U32 SectionId;
+ U32 DefaultOS = 0;
+ U32 Idx;
if (!IniOpenSection("FreeLoader", &SectionId))
{
return 0;
}
- if (IniReadSettingByName(SectionId, "DefaultOS", DefaultOSText, 80))
+ DefaultOSName = CmdLineGetDefaultOS();
+ if (NULL == DefaultOSName)
+ {
+ if (IniReadSettingByName(SectionId, "DefaultOS", DefaultOSText, 80))
+ {
+ DefaultOSName = DefaultOSText;
+ }
+ }
+
+ if (NULL != DefaultOSName)
{
for (Idx=0; Idx<OperatingSystemCount; Idx++)
{
- if (stricmp(DefaultOSText, OperatingSystemList[Idx]) == 0)
+ if (stricmp(DefaultOSName, OperatingSystemList[Idx]) == 0)
{
DefaultOS = Idx;
break;
U32 TimeOut;
U32 SectionId;
+ TimeOut = CmdLineGetTimeOut();
+ if (0 <= TimeOut)
+ {
+ return TimeOut;
+ }
+
if (!IniOpenSection("FreeLoader", &SectionId))
{
return -1;
--- /dev/null
+/* $Id: cmdline.c,v 1.1 2004/11/01 20:49:32 gvg Exp $
+ *
+ * FreeLoader
+ * Copyright (C) 1998-2003 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <freeldr.h>
+#include <cmdline.h>
+#include <rtl.h>
+
+static CMDLINEINFO CmdLineInfo;
+
+static char *
+SkipWhitespace(char *s)
+{
+ while ('\0' != *s && isspace(*s))
+ {
+ s++;
+ }
+
+ return s;
+}
+
+void
+CmdLineParse(char *CmdLine)
+{
+ char *s;
+ char *Name;
+ char *Value;
+ char *End;
+
+ CmdLineInfo.DefaultOperatingSystem = NULL;
+ CmdLineInfo.TimeOut = -1;
+
+ if (NULL == CmdLine)
+ {
+ return;
+ }
+
+ /* Skip over "kernel name" */
+ s = CmdLine;
+ while ('\0' != *s && ! isspace(*s))
+ {
+ s++;
+ }
+ s = SkipWhitespace(s);
+
+ while ('\0' != *s)
+ {
+ Name = s;
+ while (! isspace(*s) && '=' != *s && '\0' != *s)
+ {
+ s++;
+ }
+ End = s;
+ s = SkipWhitespace(s);
+ if ('=' == *s)
+ {
+ s++;
+ *End = '\0';
+ s = SkipWhitespace(s);
+ if ('"' == *s)
+ {
+ s++;
+ Value = s;
+ while ('"' != *s && '\0' != *s)
+ {
+ s++;
+ }
+ }
+ else
+ {
+ Value = s;
+ while (! isspace(*s) && '\0' != *s)
+ {
+ s++;
+ }
+ }
+ if ('\0' != *s)
+ {
+ *s++ = '\0';
+ }
+ if (0 == stricmp(Name, "defaultos"))
+ {
+ CmdLineInfo.DefaultOperatingSystem = Value;
+ }
+ else if (0 == stricmp(Name, "timeout"))
+ {
+ CmdLineInfo.TimeOut = atoi(Value);
+ }
+ }
+ }
+}
+
+char *
+CmdLineGetDefaultOS(void)
+{
+ return CmdLineInfo.DefaultOperatingSystem;
+}
+
+S32
+CmdLineGetTimeOut(void)
+{
+ return CmdLineInfo.TimeOut;
+}
+
+/* EOF */
+
#include <debug.h>
#include <bootmgr.h>
#include <fs.h>
+#include <cmdline.h>
-// Variables BootDrive & BootPartition moved to asmcode.S
-//U32 BootDrive = 0; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
-//U32 BootPartition = 0; // Boot Partition, 1-4
-
-VOID BootMain(VOID)
+VOID BootMain(char *CmdLine)
{
+ CmdLineParse(CmdLine);
EnableA20();
--- /dev/null
+/* $Id: cmdline.h,v 1.1 2004/11/01 20:49:32 gvg Exp $
+ *
+ * FreeLdr boot loader
+ * Copyright (C) 2002, 2003 ReactOS Team
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CMDLINE_H__
+#define __CMDLINE_H__
+
+typedef struct tagCMDLINEINFO
+{
+ char *DefaultOperatingSystem;
+ S32 TimeOut;
+} CMDLINEINFO, *PCMDLINEINFO;
+
+extern void CmdLineParse(char *CmdLine);
+
+extern char *CmdLineGetDefaultOS(void);
+extern S32 CmdLineGetTimeOut(void);
+
+#endif /* __CMDLINE_H__ */
+
+/* EOF */
extern U32 BootPartition; // Boot Partition, 1-4
extern BOOL UserInterfaceUp; // Tells us if the user interface is displayed
-void BootMain(void);
+void BootMain(char *CmdLine);
VOID RunLoader(VOID);
#endif // defined __FREELDR_H
0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data
0000:1000 - 0000:6FFF: Real mode stack area
-0000:7000 - 0000:7FFF: Unused
+0000:7000 - 0000:7FFF: Cmdline (multiboot)
0000:8000 - xxxx:xxxx: FreeLoader program & data area
xxxx:xxxx - 7000:7FFF: Random memory allocation heap
7000:8000 - 7000:FFFF: Protected mode stack area
The BIOS loads the boot sector (2048 bytes) at 0000:7C00. First, the
boot sector relocates itself to 0000:7000 (up to 0000:7800). Then it looks
-for the I386 directory and makes it the current directory. Next it looks for
+for the LOADER directory and makes it the current directory. Next it looks for
FREELDR.SYS and loads it at 0000:8000. Finally it restores the boot drive
number in the DL register and jumps to FreeLoader's entry point at 0000:8000.
+Multiboot
+
+ Freeldr contains a multiboot signature and can itself be loaded by a
+multiboot-compliant loader (like Grub). The multiboot header instructs the
+primary loader to load freeldr.sys at 0x200000 (needs to be above 1MB). Control
+is then transferred to the multiboot entry point. Since freeldr.sys expects to
+be loaded at a base address 0000:8000 it will start by relocating itself there
+and then jumping to the relocated copy.
+
+
+
FreeLoader Initialization
When FreeLoader gets control it saves the boot drive, passed to it in
the DL register, and sets up the stack, enables protected mode, and calls
-BootMain().
\ No newline at end of file
+BootMain().