Multiboot Kernel Compliance

svn path=/trunk/; revision=1945
This commit is contained in:
Brian Palmer 2001-06-05 21:45:51 +00:00
parent 49e30c043c
commit 4531d3752a
8 changed files with 600 additions and 631 deletions

View file

@ -24,12 +24,13 @@ export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -nostdinc -fno-builtin
#FLAGS = -Wall -nostdinc -fno-builtin
FLAGS = -Wall -fno-builtin
# asmcode.o has to be first in the link line because it contains the startup code
OBJS = asmcode.a asmcode.o ros.o boot.o freeldr.o stdlib.o fs.a fs.o fs_fat.o \
OBJS = asmcode.a asmcode.o multiboot.o boot.o freeldr.o stdlib.o fs.a fs.o fs_fat.o \
rosboot.o tui.o menu.o miscboot.o options.o linux.o
ASM_OBJS = asmcode.o ros.o boot.o
ASM_OBJS = asmcode.o multiboot.o boot.o
C_OBJS = freeldr.o stdlib.o fs.a rosboot.o tui.o menu.o miscboot.o options.o linux.o
all: freeldr.sys
@ -61,11 +62,11 @@ fs.o: fs.c freeldr.h fs.h stdlib.h tui.h asmcode.h Makefile
fs_fat.o: fs_fat.c freeldr.h fs.h stdlib.h tui.h Makefile
$(CC) $(FLAGS) -o fs_fat.o -c fs_fat.c
rosboot.o: rosboot.c freeldr.h rosboot.h stdlib.h fs.h tui.h Makefile
rosboot.o: rosboot.c freeldr.h rosboot.h stdlib.h fs.h tui.h multiboot.h Makefile
$(CC) $(FLAGS) -o rosboot.o -c rosboot.c
ros.o: ros.S asmcode.h Makefile
$(CC) $(FLAGS) -o ros.o -c ros.S
multiboot.o: multiboot.S asmcode.h multiboot.h Makefile
$(CC) $(FLAGS) -o multiboot.o -c multiboot.S
tui.o: tui.c freeldr.h stdlib.h tui.h Makefile
$(CC) $(FLAGS) -o tui.o -c tui.c

View file

@ -1116,6 +1116,37 @@ _get_sectors_done:
ret
/*
* Needed for enabling the a20 address line
*/
.code16
empty_8042:
.word 0x00eb,0x00eb // jmp $+2, jmp $+2
inb $0x64,%al
testb $0x02,%al
jnz empty_8042
ret
/*
* Enable the A20 address line (to allow access to over 1mb)
*/
.code32
EXTERN(_enable_a20)
call switch_to_real
.code16
call empty_8042
movb $0xD1,%al // command write
outb %al,$0x64
call empty_8042
mov $0xDF,%al // A20 on
out %al,$0x60
call empty_8042
call switch_to_prot
.code32
ret

View file

@ -96,11 +96,10 @@ void BootMain(void)
{
nOSToBoot = RunMenu();
LoadAndBootLinux(0x80, 0, "vmlinuz", "");
switch (OSList[nOSToBoot].nOSType)
{
case OSTYPE_REACTOS:
LoadAndBootReactOS(nOSToBoot);
LoadAndBootReactOS(OSList[nOSToBoot].name);
break;
case OSTYPE_LINUX:
MessageBox("Cannot boot this OS type yet!");

260
freeldr/freeldr/multiboot.S Normal file
View file

@ -0,0 +1,260 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000, 2001 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.
*/
.text
.code16
#include "asmcode.h"
/*
* Here we assume the kernel is loaded at 1mb
* This boots the kernel
*/
.code32
EXTERN(_boot_ros)
call switch_to_real
.code16
/* Save cursor position */
movw $3,%ax //! Reset video mode
int $0x10
movb $10,%bl
movb $12,%ah
int $0x10
movw $0x1112,%ax // Use 8x8 font
xorb %bl,%bl
int $0x10
movw $0x1200,%ax // Use alternate print screen
movb $0x20,%bl
int $0x10
movb $1,%ah // Define cursor (scan lines 6 to 7)
movw $0x0607,%cx
int $0x10
movb $1,%ah
movw $0x600,%cx
int $0x10
movb $6,%ah // Scroll active page up
movb $0x32,%al // Clear 25 lines
movw $0,%cx // Upper left of scroll
movw $0x314F,%dx // Lower right of scroll
movb $(1*0x10+1),%bh // Use normal attribute on blanked line
int $0x10 // Video-IO
movw $0,%dx
movb $0,%dh
movb $2,%ah
movb $0,%bh
int $0x10
movw $0,%dx
movb $0,%dh
movb $2,%ah
movb $0,%bh
int $0x10
call _multi_boot
// Should never get here
cli
hlt
/*
* After you have setup the _mb_header and _mb_info structures
* then call this routine to transfer control to the kernel.
* This routine must be entered in 16-bit mode.
*/
.code16
EXTERN(_multi_boot)
cli
/*
* Setup various variables
*/
movw %ds,%bx
movzwl %bx,%eax
shll $4,%eax
addl %eax,kernel_gdtbase
/*
* Load the absolute address of the multiboot information structure
*/
movl $_mb_info,%ebx
/*
* load gdt
*/
lgdt kernel_gdtptr
/*
* Enter pmode and clear prefetch queue
*/
movl %cr0,%eax
orl $0x10001,%eax
movl %eax,%cr0
jmp next
next:
/*
* NOTE: This must be position independant (no references to
* non absolute variables)
*/
/*
* Initalize segment registers
*/
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%ss
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
/*
* Initalize eflags
*/
pushl $0
popfl
/*
* Load the multiboot magic value into eax
*/
movl $0x2badb002,%eax
/*
* Jump to start of 32 bit code at 0xc0000000 + 0x1000
*/
pushl $KERNEL_CS
pushl _mb_entry_addr
lretl
//ljmpl $KERNEL_CS,$(0x0200000+0x1000)
//ljmpl $KERNEL_CS,(_mb_entry_addr)
//ljmpl $KERNEL_CS,$(KERNEL_BASE+0x1000)
.p2align 2 /* force 4-byte alignment */
kernel_gdt:
.word 0 // Zero descriptor
.word 0
.word 0
.word 0
.word 0xffff // Kernel code descriptor
.word 0x0000 //
.word 0x9a00 // base 0h limit 4gb
.word 0x00cf
.word 0xffff // Kernel data descriptor
.word 0x0000 //
.word 0x9200 // base 0h limit 4gb
.word 0x00cf
kernel_gdtptr:
.word (3*8)-1 /* Limit */
kernel_gdtbase:
.long kernel_gdt /* Base Address */
EXTERN(_mb_header)
_mb_magic:
.long 0 // unsigned long magic;
_mb_flags:
.long 0 // unsigned long flags;
_mb_checksum:
.long 0 // unsigned long checksum;
_mb_header_addr:
.long 0 // unsigned long header_addr;
_mb_load_addr:
.long 0 // unsigned long load_addr;
_mb_load_end_addr:
.long 0 // unsigned long load_end_addr;
_mb_bss_end_addr:
.long 0 // unsigned long bss_end_addr;
_mb_entry_addr:
.long 0 // unsigned long entry_addr;
//
// Boot information structure
//
EXTERN(_mb_info)
_multiboot_flags:
.long 0
_multiboot_mem_lower:
.long 0
_multiboot_mem_upper:
.long 0
_multiboot_boot_device:
.long 0
_multiboot_cmdline:
.long 0
_multiboot_mods_count:
.long 0
_multiboot_mods_addr:
.long 0
_multiboot_syms:
.rept 12
.byte 0
.endr
_multiboot_mmap_length:
.long 0
_multiboot_mmap_addr:
.long 0
_multiboot_drives_count:
.long 0
_multiboot_drives_addr:
.long 0
_multiboot_config_table:
.long 0
_multiboot_boot_loader_name:
.long 0
_multiboot_apm_table:
.long 0
EXTERN(_multiboot_modules)
.rept (64 * /*multiboot_module_size*/ 16)
.byte 0
.endr
EXTERN(_multiboot_module_strings)
.rept (64*256)
.byte 0
.endr
_multiboot_address_range_descriptor_size:
.long 0
_multiboot_address_ranges:
.rept (64 * /*multiboot_address_range_size*/24)
.byte 0
.endr
EXTERN(_multiboot_kernel_cmdline)
.rept 255
.byte 0
.endr

129
freeldr/freeldr/multiboot.h Normal file
View file

@ -0,0 +1,129 @@
/* multiboot.h - the header for Multiboot */
/* Copyright (C) 1999 Free Software Foundation, Inc.
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 __MULTIBOOT_H
#define __MULTIBOOT_H
/* Macros. */
/* The magic number for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* The flags for the Multiboot header. */
#define MULTIBOOT_HEADER_FLAGS 0x00010003
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* The size of our stack (16KB). */
#define STACK_SIZE 0x4000
/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
#ifdef HAVE_ASM_USCORE
# define EXT_C(sym) _ ## sym
#else
# define EXT_C(sym) sym
#endif
#ifndef ASM
/* Do not include here in boot.S. */
/* Types. */
/* The Multiboot header. */
typedef struct multiboot_header
{
unsigned long magic;
unsigned long flags;
unsigned long checksum;
unsigned long header_addr;
unsigned long load_addr;
unsigned long load_end_addr;
unsigned long bss_end_addr;
unsigned long entry_addr;
} multiboot_header_t;
/* The symbol table for a.out. */
typedef struct aout_symbol_table
{
unsigned long tabsize;
unsigned long strsize;
unsigned long addr;
unsigned long reserved;
} aout_symbol_table_t;
/* The section header table for ELF. */
typedef struct elf_section_header_table
{
unsigned long num;
unsigned long size;
unsigned long addr;
unsigned long shndx;
} elf_section_header_table_t;
/* The Multiboot information. */
typedef struct multiboot_info
{
unsigned long flags;
unsigned long mem_lower;
unsigned long mem_upper;
unsigned long boot_device;
unsigned long cmdline;
unsigned long mods_count;
unsigned long mods_addr;
union
{
aout_symbol_table_t aout_sym;
elf_section_header_table_t elf_sec;
} u;
unsigned long mmap_length;
unsigned long mmap_addr;
} multiboot_info_t;
/* The module structure. */
typedef struct module
{
unsigned long mod_start;
unsigned long mod_end;
unsigned long string;
unsigned long reserved;
} module_t;
/* The memory map. Be careful that the offset 0 is base_addr_low
but no size. */
typedef struct memory_map
{
unsigned long size;
unsigned long base_addr_low;
unsigned long base_addr_high;
unsigned long length_low;
unsigned long length_high;
unsigned long type;
} memory_map_t;
#endif /* ! ASM */
multiboot_header_t mb_header; // Multiboot header structure defined in kernel image file
multiboot_info_t mb_info; // Multiboot info structure passed to kernel
char multiboot_kernel_cmdline[255]; // Command line passed to kernel
module_t multiboot_modules[64]; // Array to hold boot module info loaded for the kernel
char multiboot_module_strings[64][256]; // Array to hold module names
#endif // defined __MULTIBOOT_H

View file

@ -1,374 +0,0 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 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.
*/
.text
.code16
#include "asmcode.h"
/*
* Needed for enabling the a20 address line
*/
empty_8042:
.word 0x00eb,0x00eb // jmp $+2, jmp $+2
inb $0x64,%al
testb $0x02,%al
jnz empty_8042
ret
/*
* Enable the A20 address line (to allow access to over 1mb)
*/
.code32
EXTERN(_enable_a20)
call switch_to_real
.code16
call empty_8042
movb $0xD1,%al // command write
outb %al,$0x64
call empty_8042
mov $0xDF,%al // A20 on
out %al,$0x60
call empty_8042
call switch_to_prot
.code32
ret
.code16
/*
* Reprogram the PIC because they overlap the Intel defined
* exceptions
*/
reprogram_pic:
movb $0x11,%al // initialization sequence
outb %al,$0x20 // send it to 8259A-1
.word 0x00eb,0x00eb // jmp $+2, jmp $+2
outb %al,$0xA0 // and to 8259A-2
.word 0x00eb,0x00eb
movb $0x40,%al // start of hardware int's (0x20)
outb %al,$0x21
.word 0x00eb,0x00eb
movb $0x48,%al // start of hardware int's 2 (0x28)
outb %al,$0xA1
.word 0x00eb,0x00eb
movb $0x04,%al // 8259-1 is master
outb %al,$0x21
.word 0x00eb,0x00eb
movb $0x02,%al // 8259-2 is slave
outb %al,$0xA1
.word 0x00eb,0x00eb
movb $0x01,%al // 8086 mode for both
outb %al,$0x21
.word 0x00eb,0x00eb
outb %al,$0xA1
.word 0x00eb,0x00eb
movb $0xFF,%al // mask off all interrupts for now
outb %al,$0x21
.word 0x00eb,0x00eb
outb %al,$0xA1
ret
/*
* In: EDI = address
* Out: FS = segment
* DI = base
*/
convert_to_seg:
pushl %eax
movl %edi,%eax
//shrl $16,%eax
//shll $12,%eax
//movw %ax,%fs
shrl $4,%eax
movw %ax,%fs
andl $0xf,%edi
//andl $0xFFFF,%edi
popl %eax
ret
/*
* Here we assume the kernel is loaded at 1mb
* This boots the kernel
*/
.code32
EXTERN(_boot_ros)
call switch_to_real
.code16
/* Save cursor position */
movw $3,%ax //! Reset video mode
int $0x10
movb $10,%bl
movb $12,%ah
int $0x10
movw $0x1112,%ax //! Use 8x8 font
xorb %bl,%bl
int $0x10
movw $0x1200,%ax //! Use alternate print screen
movb $0x20,%bl
int $0x10
movb $1,%ah //! Define cursor (scan lines 6 to 7)
movw $0x0607,%cx
int $0x10
movb $1,%ah
movw $0x600,%cx
int $0x10
MOVb $6,%AH //SCROLL ACTIVE PAGE UP
MOVb $0x32,%AL //CLEAR 25 LINES
MOVw $0,%CX //UPPER LEFT OF SCROLL
MOVw $0x314F,%dx //LOWER RIGHT OF SCROLL
MOVb $(1*0x10+1),%bh //USE NORMAL ATTRIBUTE ON BLANKED LINE
INT $0x10 //VIDEO-IO
movw $0,%dx
movb $0,%dh
movb $2,%ah
movb $0,%bh
int $0x10
movw $0,%dx
movb $0,%dh
movb $2,%ah
movb $0,%bh
int $0x10
cli
// The page tables are setup elsewhere
/*
// Map in the lowmem page table (and reuse it for the identity map)
movl _kernel_page_directory_base,%edi
call convert_to_seg
movl _lowmem_page_table_base,%eax
addl $0x07,%eax
movl %eax,%fs:(%edi)
movl %eax,%fs:0xd00(%edi)//(0xd0000000/(1024*1024))(%edi)
// Map the page tables from the page directory
movl _kernel_page_directory_base,%eax
addl $0x07,%eax
movl %eax,%fs:0xf00(%edi)//(0xf0000000/(1024*1024))(%edi)
// Map in the kernel page table
movl _system_page_table_base,%eax
addl $0x07,%eax
movl %eax,%fs:0xc00(%edi)//(0xc0000000/(1024*1024))(%edi)
// Setup the lowmem page table
movl _lowmem_page_table_base,%edi
call convert_to_seg
movl $0,%ebx
l9:
movl %ebx,%eax
shll $12,%eax // ebx = ebx * 4096
addl $07,%eax // user, rw, present
movl %eax,%fs:(%edi,%ebx,4)
incl %ebx
cmpl $1024,%ebx
jl l9
// Setup the system page table
movl _system_page_table_base,%edi
call convert_to_seg
movl $07,%eax
l8:
movl %eax,%edx
addl _start_kernel,%edx
movl %edx,%fs:(%edi)
addl $4,%edi
addl $0x1000,%eax
cmpl $0x100007,%eax
jl l8
*/
/*
* Load the page directory into cr3
*/
movl _kernel_page_directory_base,%eax
movl %eax,%cr3
/*
* Setup various variables
*/
movw %ds,%bx
movzwl %bx,%eax
shll $4,%eax
addl %eax,kernel_gdtbase
//call enable_a20 // enabled elsewhere
call reprogram_pic
/*
* Load stack
*/
movw %ds,%bx
movzwl %bx,%eax
shll $4,%eax
addl $real_stack_end,%eax
movl %eax,real_stack_base
movl real_stack_base,%esp
movl _boot_param_struct_base,%edx
/*
* load gdt
*/
lgdt kernel_gdtptr
/*
* Enter pmode and clear prefetch queue
*/
movl %cr0,%eax
orl $0x80010001,%eax
/*orl $0x80000001,%eax*/
movl %eax,%cr0
jmp next
next:
/*
* NOTE: This must be position independant (no references to
* non absolute variables)
*/
/*
* Initalize segment registers
*/
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%ss
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
/*
* Initalize eflags
*/
pushl $0
popfl
/*
* Jump to start of 32 bit code at 0xc0000000 + 0x1000
*/
pushl %edx
pushl $0
ljmpl $KERNEL_CS,$(KERNEL_BASE+0x1000)
.p2align 2 /* force 4-byte alignment */
kernel_gdt:
.word 0 // Zero descriptor
.word 0
.word 0
.word 0
//.word 0x0000 // User code descriptor
//.word 0x0000 // base: 0h limit: 3gb
//.word 0xfa00
//.word 0x00cc
//.word 0x0000 // User data descriptor
//.word 0x0000 // base: 0h limit: 3gb
//.word 0xf200
//.word 0x00cc
//.word 0x0000
//.word 0x0000
//.word 0x0000
//.word 0x0000
.word 0xffff // Kernel code descriptor
.word 0x0000 //
.word 0x9a00 // base 0h limit 4gb
.word 0x00cf
.word 0xffff // Kernel data descriptor
.word 0x0000 //
.word 0x9200 // base 0h limit 4gb
.word 0x00cf
/* TSS space */
//.rept NR_TASKS
//.word 0
//.word 0
//.word 0
//.word 0
//.endr
kernel_gdtptr:
.word (((6+NR_TASKS)*8)-1) /* Limit */
kernel_gdtbase:
.long kernel_gdt /* Base Address */
EXTERN(_boot_param_struct_base)
.long 0
EXTERN(_start_mem)
.long 0
EXTERN(_kernel_page_directory_base)
.long 0
EXTERN(_system_page_table_base)
.long 0
EXTERN(_lowmem_page_table_base)
.long 0
EXTERN(_start_kernel)
.long 0
EXTERN(_load_base)
.long 0
/* boot_param structure */
EXTERN(_boot_parameters)
.long 0 // Magic
.long 0 // Cursor X
.long 0 // Cursor Y
.long 0 // nr_files
.long 0 // start_mem
.long 0 // end_mem
.rept 64
.long 0 // List of module lengths (terminated by a 0)
.endr
.rept 256
.byte 0 // Kernel parameter string
.endr
/* Our initial stack */
real_stack:
.rept 1024
.byte 0
.endr
real_stack_end:
real_stack_base:
.long 0

View file

@ -1,6 +1,6 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
* Copyright (C) 1999, 2000, 2001 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
@ -24,19 +24,11 @@
#include "stdlib.h"
#include "fs.h"
#include "tui.h"
#include "multiboot.h"
extern boot_param boot_parameters; // Boot parameter structure passed to the kernel
extern int boot_param_struct_base; // Physical address of the boot parameters structure
extern int start_mem; // Start of the continuous range of physical kernel memory
extern int kernel_page_directory_base; // Physical address of the kernel page directory
extern int system_page_table_base; // Physical address of the system page table
extern int lowmem_page_table_base; // Physical address of the low mem page table
extern int start_kernel; // Physical address of the start of kernel code
extern int load_base; // Physical address of the loaded kernel modules
unsigned long next_module_load_base = 0;
static int next_load_base;
void LoadAndBootReactOS(int nOSToBoot)
void LoadAndBootReactOS(char *OperatingSystemName)
{
FILE file;
char name[1024];
@ -47,35 +39,27 @@ void LoadAndBootReactOS(int nOSToBoot)
int nNumFilesLoaded=0;
/*
* Enable a20 so we can load at 1mb and initialize the page tables
* Setup multiboot information structure
*/
//enable_a20(); // enabled in freeldr.c
ReactOSMemInit();
// Setup kernel parameters
boot_param_struct_base = (int)&boot_parameters;
boot_parameters.magic = 0xdeadbeef;
boot_parameters.cursorx = 0;
boot_parameters.cursory = 0;
boot_parameters.nr_files = 0;
boot_parameters.start_mem = start_mem;
boot_parameters.end_mem = load_base;
boot_parameters.kernel_parameters[0] = 0;
next_load_base = load_base;
mb_info.flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES;
mb_info.mem_lower = 640;//(640 * 1024);
mb_info.mem_upper = (8 * 1024);
mb_info.boot_device = 0xffffffff;
mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline;
mb_info.mods_count = 0;
mb_info.mods_addr = (unsigned long)multiboot_modules;
mb_info.mmap_length = 0;
mb_info.mmap_addr = 0;
/*
* Read the optional kernel parameters
* Read the optional kernel parameters (if any)
*/
if(ReadSectionSettingByName(OSList[nOSToBoot].name, "Options", name, value))
{
strcpy(boot_parameters.kernel_parameters,value);
}
ReadSectionSettingByName(OperatingSystemName, "Options", name, multiboot_kernel_cmdline);
/*
* Find the kernel image name
*/
if(!ReadSectionSettingByName(OSList[nOSToBoot].name, "Kernel", name, value))
if(!ReadSectionSettingByName(OperatingSystemName, "Kernel", name, value))
{
MessageBox("Kernel image file not specified for selected operating system.");
return;
@ -85,13 +69,16 @@ void LoadAndBootReactOS(int nOSToBoot)
* Get the boot partition
*/
BootPartition = 0;
if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
if (ReadSectionSettingByName(OperatingSystemName, "BootPartition", name, value))
{
BootPartition = atoi(value);
}
((char *)(&mb_info.boot_device))[1] = (char)BootPartition;
/*
* Make sure the boot drive is set in the .ini file
*/
if(!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
if(!ReadSectionSettingByName(OperatingSystemName, "BootDrive", name, value))
{
MessageBox("Boot drive not specified for selected operating system.");
return;
@ -106,6 +93,7 @@ void LoadAndBootReactOS(int nOSToBoot)
* Set the boot drive and try to open it
*/
BootDrive = atoi(value);
((char *)(&mb_info.boot_device))[0] = (char)BootDrive;
if (!OpenDiskDrive(BootDrive, BootPartition))
{
MessageBox("Failed to open boot drive.");
@ -115,27 +103,62 @@ void LoadAndBootReactOS(int nOSToBoot)
/*
* Parse the ini file and count the kernel and drivers
*/
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
for (i=1; i<=GetNumSectionItems(OperatingSystemName); i++)
{
/*
* Read the setting and check if it's a driver
*/
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
ReadSectionSettingByNumber(OperatingSystemName, i, name, value);
if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0))
nNumDriverFiles++;
}
/*
* Find the kernel image name
* and try to load the kernel off the disk
*/
if(ReadSectionSettingByName(OperatingSystemName, "Kernel", name, value))
{
/*
* Set the name and try to open the PE image
*/
strcpy(szFileName, value);
if (!OpenFile(szFileName, &file))
{
strcat(value, " not found.");
MessageBox(value);
return;
}
/*
* Update the status bar with the current file
*/
strcpy(name, " Reading ");
strcat(name, value);
while (strlen(name) < 80)
strcat(name, " ");
DrawStatusText(name);
/*
* Load the kernel image
*/
MultiBootLoadKernel(&file);
nNumFilesLoaded++;
DrawProgressBar((nNumFilesLoaded * 100) / nNumDriverFiles);
}
/*
* Parse the ini file and load the kernel and
* load all the drivers specified
*/
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
for (i=1; i<=GetNumSectionItems(OperatingSystemName); i++)
{
/*
* Read the setting and check if it's a driver
*/
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0))
ReadSectionSettingByNumber(OperatingSystemName, i, name, value);
if (stricmp(name, "Driver") == 0)
{
/*
* Set the name and try to open the PE image
@ -160,13 +183,11 @@ void LoadAndBootReactOS(int nOSToBoot)
/*
* Load the driver
*/
ReactOSLoadPEImage(&file);
MultiBootLoadModule(&file, szFileName);
nNumFilesLoaded++;
DrawProgressBar((nNumFilesLoaded * 100) / nNumDriverFiles);
// Increment the number of files we loaded
boot_parameters.nr_files++;
}
else if (stricmp(name, "MessageBox") == 0)
{
@ -185,13 +206,6 @@ void LoadAndBootReactOS(int nOSToBoot)
}
}
/*
* End the list of modules we load with a zero length entry
* and update the end of kernel mem
*/
boot_parameters.module_lengths[boot_parameters.nr_files] = 0;
boot_parameters.end_mem = next_load_base;
/*
* Clear the screen and redraw the backdrop and status bar
*/
@ -202,7 +216,7 @@ void LoadAndBootReactOS(int nOSToBoot)
* Wait for user
*/
strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot ");
strcat(name, OSList[nOSToBoot].name);
strcat(name, OperatingSystemName);
strcat(name, ".");
//MessageBox(name);
@ -212,179 +226,114 @@ void LoadAndBootReactOS(int nOSToBoot)
* Now boot the kernel
*/
stop_floppy();
ReactOSBootKernel();
}
void ReactOSMemInit(void)
{
int base;
/* Calculate the start of extended memory */
base = 0x100000;
/* Set the start of the page directory */
kernel_page_directory_base = base;
/*
* Set the start of the continuous range of physical memory
* occupied by the kernel
*/
start_mem = base;
base += 0x1000;
/* Calculate the start of the system page table (0xc0000000 upwards) */
system_page_table_base = base;
base += 0x1000;
/* Calculate the start of the page table to map the first 4mb */
lowmem_page_table_base = base;
base += 0x1000;
/* Set the position for the first module to be loaded */
load_base = base;
/* Set the address of the start of kernel code */
start_kernel = base;
}
void ReactOSBootKernel(void)
{
int i;
int *pPageDirectory = (int *)kernel_page_directory_base;
int *pLowMemPageTable = (int *)lowmem_page_table_base;
int *pSystemPageTable = (int *)system_page_table_base;
/* Zero out the kernel page directory */
for(i=0; i<1024; i++)
pPageDirectory[i] = 0;
/* Map in the lowmem page table */
pPageDirectory[(0x00/4)] = lowmem_page_table_base + 0x07;
/* Map in the lowmem page table (and reuse it for the identity map) */
pPageDirectory[(0xd00/4)] = lowmem_page_table_base + 0x07;
/* Map the page tables from the page directory */
pPageDirectory[(0xf00/4)] = kernel_page_directory_base + 0x07;
/* Map in the kernel page table */
pPageDirectory[(0xc00/4)] = system_page_table_base + 0x07;
/* Setup the lowmem page table */
for(i=0; i<1024; i++)
pLowMemPageTable[i] = (i * 4096) + 0x07;
/* Setup the system page table */
for(i=0; i<1024; i++)
pSystemPageTable[i] = ((i * 4096) + start_kernel) + 0x07;
boot_ros();
}
BOOL ReactOSLoadPEImage(FILE *pImage)
BOOL MultiBootLoadKernel(FILE *KernelImage)
{
unsigned int Idx, ImageBase;
PULONG PEMagic;
PIMAGE_DOS_HEADER PEDosHeader;
PIMAGE_FILE_HEADER PEFileHeader;
PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
PIMAGE_SECTION_HEADER PESectionHeaders;
ImageBase = next_load_base;
boot_parameters.module_lengths[boot_parameters.nr_files] = 0;
DWORD ImageHeaders[2048];
int Idx;
DWORD dwHeaderChecksum;
DWORD dwFileLoadOffset;
DWORD dwDataSize;
DWORD dwBssSize;
/*
* Load the headers
* Load the first 8192 bytes of the kernel image
* so we can search for the multiboot header
*/
ReadFile(pImage, 0x1000, (void *)next_load_base);
ReadFile(KernelImage, 8192, ImageHeaders);
/*
* Get header pointers
* Now find the multiboot header and copy it
*/
PEDosHeader = (PIMAGE_DOS_HEADER) next_load_base;
PEMagic = (PULONG) ((unsigned int) next_load_base +
PEDosHeader->e_lfanew);
PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) next_load_base +
PEDosHeader->e_lfanew + sizeof(ULONG));
PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) next_load_base +
PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) next_load_base +
PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
sizeof(IMAGE_OPTIONAL_HEADER));
/*
* Check file magic numbers
*/
if(PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
for (Idx=0; Idx<2048; Idx++)
{
MessageBox("Incorrect MZ magic");
// Did we find it?
if (ImageHeaders[Idx] == MULTIBOOT_HEADER_MAGIC)
{
// Yes, copy it and break out of this loop
memcpy(&mb_header, &ImageHeaders[Idx], sizeof(multiboot_header_t));
break;
}
}
/*
* If we reached the end of the 8192 bytes without
* finding the multiboot header then return error
*/
if (Idx == 2048)
{
MessageBox("No multiboot header found!");
return FALSE;
}
if(PEDosHeader->e_lfanew == 0)
{
MessageBox("Invalid lfanew offset");
return 0;
}
if(*PEMagic != IMAGE_PE_MAGIC)
{
MessageBox("Incorrect PE magic");
return 0;
}
if(PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
{
MessageBox("Incorrect Architecture");
return 0;
}
/*printf("multiboot header:\n");
printf("0x%x\n", mb_header.magic);
printf("0x%x\n", mb_header.flags);
printf("0x%x\n", mb_header.checksum);
printf("0x%x\n", mb_header.header_addr);
printf("0x%x\n", mb_header.load_addr);
printf("0x%x\n", mb_header.load_end_addr);
printf("0x%x\n", mb_header.bss_end_addr);
printf("0x%x\n", mb_header.entry_addr);
getch();*/
/*
* Get header size and bump next_load_base
* Calculate the checksum and make sure it matches
*/
next_load_base += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
boot_parameters.module_lengths[boot_parameters.nr_files] += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
boot_parameters.end_mem += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
dwHeaderChecksum = mb_header.magic;
dwHeaderChecksum += mb_header.flags;
dwHeaderChecksum += mb_header.checksum;
if (dwHeaderChecksum != 0)
{
MessageBox("Multiboot header checksum invalid!");
return FALSE;
}
/*
* Get the file offset, this should be 0, and move the file pointer
*/
dwFileLoadOffset = (Idx * sizeof(DWORD)) - (mb_header.header_addr - mb_header.load_addr);
fseek(KernelImage, dwFileLoadOffset);
/*
* Load the file image
*/
dwDataSize = (mb_header.load_end_addr - mb_header.load_addr);
ReadFile(KernelImage, dwDataSize, (void*)mb_header.load_addr);
/*
* Copy image sections into virtual section
* Initialize bss area
*/
// memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
// CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData);
// CurrentSize = 0;
for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
{
/*
* Copy current section into current offset of virtual section
*/
if (PESectionHeaders[Idx].Characteristics &
(IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
{
//memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
// (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
// PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
dwBssSize = (mb_header.bss_end_addr - mb_header.load_end_addr);
memset((void*)mb_header.load_end_addr, 0, dwBssSize);
//MessageBox("loading a section");
fseek(pImage, PESectionHeaders[Idx].PointerToRawData);
ReadFile(pImage, PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/, (void *)next_load_base);
//printf("PointerToRawData: %x\n", PESectionHeaders[Idx].PointerToRawData);
//printf("bytes at next_load_base: %x\n", *((unsigned long *)next_load_base));
//getch();
}
else
{
//memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
// '\0', PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
//MessageBox("zeroing a section");
memset((void *)next_load_base, '\0', PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
}
PESectionHeaders[Idx].PointerToRawData = next_load_base - ImageBase;
next_load_base += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment);
boot_parameters.module_lengths[boot_parameters.nr_files] += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment);
boot_parameters.end_mem += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment);
//DrawProgressBar((Idx * 100) / PEFileHeader->NumberOfSections);
}
next_module_load_base = ROUND_UP(mb_header.bss_end_addr, /*PAGE_SIZE*/4096);
return TRUE;
}
}
BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName)
{
DWORD dwModuleSize;
module_t* pModule = &multiboot_modules[mb_info.mods_count];
char* ModuleNameString = multiboot_module_strings[mb_info.mods_count];
dwModuleSize = GetFileSize(ModuleImage);
pModule->mod_start = next_module_load_base;
pModule->mod_end = next_module_load_base + dwModuleSize;
strcpy(ModuleNameString, ModuleName);
pModule->string = (unsigned long)ModuleNameString;
/*
* Load the file image
*/
ReadFile(ModuleImage, dwModuleSize, (void*)next_module_load_base);
next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096);
mb_info.mods_count++;
return TRUE;
}

View file

@ -26,50 +26,24 @@
#define PACKED __attribute__((packed))
void LoadAndBootReactOS(int nOSToBoot);
void ReactOSMemInit(void);
void ReactOSBootKernel(void);
BOOL ReactOSLoadPEImage(FILE *pImage);
#define MB_INFO_FLAG_MEM_SIZE 0x00000001
#define MB_INFO_FLAG_BOOT_DEVICE 0x00000002
#define MB_INFO_FLAG_COMMAND_LINE 0x00000004
#define MB_INFO_FLAG_MODULES 0x00000008
#define MB_INFO_FLAG_AOUT_SYMS 0x00000010
#define MB_INFO_FLAG_ELF_SYMS 0x00000020
#define MB_INFO_FLAG_MEMORY_MAP 0x00000040
#define MB_INFO_FLAG_DRIVES 0x00000080
#define MB_INFO_FLAG_CONFIG_TABLE 0x00000100
#define MB_INFO_FLAG_BOOT_LOADER_NAME 0x00000200
#define MB_INFO_FLAG_APM_TABLE 0x00000400
#define MB_INFO_FLAG_GRAPHICS_TABLE 0x00000800
void LoadAndBootReactOS(char *OperatingSystemName);
BOOL MultiBootLoadKernel(FILE *KernelImage);
BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName);
void enable_a20(void);
void boot_ros(void);
// WARNING:
// This structure is prototyped here but allocated in ros.S
// if you change this prototype make sure to update ros.S
typedef struct
{
/*
* Magic value (useless really)
*/
unsigned int magic;
/*
* Cursor position
*/
unsigned int cursorx;
unsigned int cursory;
/*
* Number of files (including the kernel) loaded
*/
unsigned int nr_files;
/*
* Range of physical memory being used by the system
*/
unsigned int start_mem;
unsigned int end_mem;
/*
* List of module lengths (terminated by a 0)
*/
unsigned int module_lengths[64];
/*
* Kernel parameter string
*/
char kernel_parameters[256];
} boot_param PACKED;
#endif // defined __ROSBOOT_H