From 4531d3752a7c90a69b06a60749e7524bd1852908 Mon Sep 17 00:00:00 2001 From: Brian Palmer Date: Tue, 5 Jun 2001 21:45:51 +0000 Subject: [PATCH] Multiboot Kernel Compliance svn path=/trunk/; revision=1945 --- freeldr/freeldr/Makefile | 13 +- freeldr/freeldr/asmcode.S | 31 +++ freeldr/freeldr/freeldr.c | 3 +- freeldr/freeldr/multiboot.S | 260 +++++++++++++++++++++++++ freeldr/freeldr/multiboot.h | 129 +++++++++++++ freeldr/freeldr/ros.S | 374 ------------------------------------ freeldr/freeldr/rosboot.c | 363 +++++++++++++++------------------- freeldr/freeldr/rosboot.h | 58 ++---- 8 files changed, 600 insertions(+), 631 deletions(-) create mode 100644 freeldr/freeldr/multiboot.S create mode 100644 freeldr/freeldr/multiboot.h delete mode 100644 freeldr/freeldr/ros.S diff --git a/freeldr/freeldr/Makefile b/freeldr/freeldr/Makefile index e28173816b8..b05b180a069 100644 --- a/freeldr/freeldr/Makefile +++ b/freeldr/freeldr/Makefile @@ -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 diff --git a/freeldr/freeldr/asmcode.S b/freeldr/freeldr/asmcode.S index ae91d6e997e..e4c6f1d9ec4 100644 --- a/freeldr/freeldr/asmcode.S +++ b/freeldr/freeldr/asmcode.S @@ -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 + diff --git a/freeldr/freeldr/freeldr.c b/freeldr/freeldr/freeldr.c index b38d1892914..c36415fe96d 100644 --- a/freeldr/freeldr/freeldr.c +++ b/freeldr/freeldr/freeldr.c @@ -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!"); diff --git a/freeldr/freeldr/multiboot.S b/freeldr/freeldr/multiboot.S new file mode 100644 index 00000000000..d22044a7db3 --- /dev/null +++ b/freeldr/freeldr/multiboot.S @@ -0,0 +1,260 @@ +/* + * FreeLoader + * Copyright (C) 1999, 2000, 2001 Brian Palmer + * + * 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 diff --git a/freeldr/freeldr/multiboot.h b/freeldr/freeldr/multiboot.h new file mode 100644 index 00000000000..cb73ccd14a6 --- /dev/null +++ b/freeldr/freeldr/multiboot.h @@ -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 \ No newline at end of file diff --git a/freeldr/freeldr/ros.S b/freeldr/freeldr/ros.S deleted file mode 100644 index b10b735b3eb..00000000000 --- a/freeldr/freeldr/ros.S +++ /dev/null @@ -1,374 +0,0 @@ -/* - * FreeLoader - * Copyright (C) 1999, 2000 Brian Palmer - * - * 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 diff --git a/freeldr/freeldr/rosboot.c b/freeldr/freeldr/rosboot.c index 371fe14b4c7..6b0756b820f 100644 --- a/freeldr/freeldr/rosboot.c +++ b/freeldr/freeldr/rosboot.c @@ -1,6 +1,6 @@ /* * FreeLoader - * Copyright (C) 1999, 2000 Brian Palmer + * Copyright (C) 1999, 2000, 2001 Brian Palmer * * 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; -} \ No newline at end of file +} + +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; +} diff --git a/freeldr/freeldr/rosboot.h b/freeldr/freeldr/rosboot.h index 19b449e56f4..499a513e62f 100644 --- a/freeldr/freeldr/rosboot.h +++ b/freeldr/freeldr/rosboot.h @@ -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 \ No newline at end of file