Add ability to be loaded as "multiboot kernel" from other multiboot loaders

svn path=/trunk/; revision=11524
This commit is contained in:
Gé van Geldorp 2004-11-01 20:49:32 +00:00
parent 3ec6acd622
commit a10211cdc2
8 changed files with 361 additions and 41 deletions

View file

@ -271,7 +271,8 @@ MATH_OBJS = libgcc2.o
BASE_OBJS = freeldr.o \
debug.o \
multiboot.o \
version.o
version.o \
cmdline.o
FREELDR_OBJS= bootmgr.o \
drivemap.o \

View file

@ -22,6 +22,7 @@
#define ASM
#include <arch.h>
#include <multiboot.h>
EXTERN(RealEntryPoint)
@ -52,6 +53,8 @@ EXTERN(RealEntryPoint)
movb %dh,(_BootPartition)
/* GO! */
xorl %eax,%eax
pushl %eax
call _BootMain
call switch_to_real
@ -266,8 +269,134 @@ EXTERN(_DisableA20)
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:
@ -323,6 +452,11 @@ gdtptr:
.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 */

View file

@ -34,6 +34,7 @@
#include <bootmgr.h>
#include <drivemap.h>
#include <keycodes.h>
#include <cmdline.h>
VOID RunLoader(VOID)
@ -153,6 +154,7 @@ reboot:
U32 GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], U32 OperatingSystemCount)
{
UCHAR DefaultOSText[80];
char* DefaultOSName;
U32 SectionId;
U32 DefaultOS = 0;
U32 Idx;
@ -162,11 +164,20 @@ U32 GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], U32 OperatingSyste
return 0;
}
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;
@ -183,6 +194,12 @@ S32 GetTimeOut(VOID)
U32 TimeOut;
U32 SectionId;
TimeOut = CmdLineGetTimeOut();
if (0 <= TimeOut)
{
return TimeOut;
}
if (!IniOpenSection("FreeLoader", &SectionId))
{
return -1;

122
freeldr/freeldr/cmdline.c Normal file
View file

@ -0,0 +1,122 @@
/* $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 */

View file

@ -24,13 +24,11 @@
#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();

View file

@ -0,0 +1,37 @@
/* $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 */

View file

@ -75,7 +75,7 @@ extern U32 BootDrive; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
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

View file

@ -4,7 +4,7 @@ Memory layout:
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
@ -34,11 +34,22 @@ ISO-9660 (CD-ROM) Boot Sector
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