sortix-mirror/sortix/kernel.cpp
Jonas 'Sortie' Termansen b0df5186e6 Fixed two very nasty bugs in the x86 memory management code.
1) The PML2 was not initialized to zeroes, thus leaving some bits behind that
caused the fork code to go crazy, forking the unforkable, and mapping addresses
that never, ever, should have been mapped, leaving behind a trail of page faults
and general protection faults on some computers, while other computers worked
because the uninitalized memory just wasn't uninitialized enough. Yep, this was
a schrödinbug!

2) Fixed a time bomb. The kernel heap was accidentally put such that whenever a
few megabytes were allocated, it would begin overwriting the physical page stack
causing unthinkable events to unfold and would probably be even more obscure to
debug than 1).

Oh, and some string errors fixed and removed RunApplication from kernel.cpp,
funny thing that even linked in the first place. Guess, the optimizer actually
did work for once. :)
2011-10-20 03:52:08 +02:00

269 lines
9.4 KiB
C++

/******************************************************************************
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
This file is part of Sortix.
Sortix 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 3 of the License, or (at your option) any later
version.
Sortix 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 Sortix. If not, see <http://www.gnu.org/licenses/>.
kernel.cpp
A common interface shared by all devices that can be printed text to.
******************************************************************************/
#include "platform.h"
#include <libmaxsi/memory.h>
#include <libmaxsi/string.h>
#include <libmaxsi/format.h>
#include "log.h"
#include "panic.h"
#include "descriptor_tables.h"
#include "time.h"
#include "keyboard.h"
#include "multiboot.h"
#include "memorymanagement.h"
#include "scheduler.h"
#include "syscall.h"
#include "pci.h"
#include "uart.h"
#include "serialterminal.h"
#include "vgaterminal.h"
#include "elf.h"
#include "initrd.h"
using namespace Maxsi;
void* RunApplication(void* Parameter);
extern "C" size_t stack[4096] = {0};
extern "C" size_t stackend = 0;
namespace Sortix
{
#ifdef PLATFORM_HTTP
namespace HTTP { void Init(); }
#endif
void DoBSoD()
{
#ifdef PLATFORM_SERIAL
UART::WriteChar(27);
UART::WriteChar(91);
UART::WriteChar(48 + 4);
UART::WriteChar(48 + 4);
UART::WriteChar(109);
#endif
Log::Print(" ");
Log::Print(" ");
Log::Print("Windows Boot Manager has experienced a problem. ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" Status: 0xc000000f ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" Info: An error occured during transferring execution. ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print("You can try to recover the system with the Microsoft Windows System Recovery ");
Log::Print("Tools. (You might need to restart the system manually). ");
Log::Print(" ");
Log::Print("If the problem continues, please contact your system administrator or computer ");
Log::Print("manufacturer. ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
#ifdef JSSORTIX
JSSortix::Exit();
#else
while ( true ) { }
#endif
}
void DoMaxsiLogo()
{
Log::Print(" _ \n");
Log::Print(" / \\ \n");
Log::Print(" /\\ /\\ / \\ \n");
Log::Print(" / \\ / \\ | | \n");
Log::Print(" / \\/ \\ | | \n");
Log::Print(" | O O \\_______________________ / | \n");
Log::Print(" | | \n");
Log::Print(" | \\_______/ / \n");
Log::Print(" \\ / \n");
Log::Print(" ------ --------------- ---/ \n");
Log::Print(" / \\ / \\ \n");
Log::Print(" / \\ / \\ \n");
Log::Print(" / \\ / \\ \n");
Log::Print(" /_____________\\ /____________\\ \n");
Log::Print(" \n");
Log::Print(" BOOTING OPERATING SYSTEM... ");
}
void DoWelcome()
{
#ifdef BSOD
DoBSoD();
#endif
DoMaxsiLogo();
}
extern "C" void KernelInit(unsigned long Magic, multiboot_info_t* BootInfo)
{
#ifdef JSSORTIX
// TODO: Make JSVM multiboot compliant.
multiboot_info_t MBInfo; BootInfo = &MBInfo;
multiboot_memory_map_t MBMMap;
MBMMap.addr = 0x100000;
MBMMap.len = 0xC00000;
MBMMap.type = MULTIBOOT_MEMORY_AVAILABLE;
MBMMap.size = sizeof(MBMMap) - sizeof(MBMMap.size);
BootInfo->flags = MULTIBOOT_INFO_MEM_MAP;
BootInfo->mmap_addr = (multiboot_uint32_t) &MBMMap;
BootInfo->mmap_length = sizeof(MBMMap);
#endif
// Initialize the default terminal.
Maxsi::Format::Callback logcallback;
void* logpointer;
#if PLATFORM_SERIAL
// Initialize the serial driver.
UART::Init();
SerialTerminal::Init();
logcallback = SerialTerminal::Print;
logpointer = NULL;
#else
VGATerminal::Init();
logcallback = VGATerminal::Print;
logpointer = NULL;
#endif
// Initialize the kernel log.
Log::Init(logcallback, logpointer);
// Just a test to see if the color system works! Make the BG red!
Log::Print("\e[37;41m\e[2J");
// Display the boot welcome screen.
DoWelcome();
#ifndef JSSORTIX
// Search for PCI devices and load their drivers.
PCI::Init();
#endif
// Initialize the paging and virtual memory.
Memory::Init(BootInfo);
uint8_t* initrd = NULL;
size_t initrdsize = 0;
#ifndef JSSORTIX
uint8_t** modules = (uint8_t**) BootInfo->mods_addr;
for ( uint32_t I = 0; I < BootInfo->mods_count; I++ )
{
initrdsize = modules[2*I+1] - modules[2*I+0];
initrd = modules[2*I+0];
break;
}
#else
// TODO: UGLY HACK because JSVM doesn't support multiboot yet!
initrd = (uint8_t*) 0x180000UL;
initrdsize = 0x80000; // 512 KiB
#endif
if ( initrd == NULL ) { PanicF("No initrd provided"); }
// Initialize the GDT and TSS structures.
GDT::Init();
#ifdef PLATFORM_X64
Log::Print("Halt: CPU X64 cannot boot because interrupts are not yet "
"supported under 64-bit Sortix.\n");
Log::Print("Sorry, it simply isn't possible to fully boot Sortix in x64 mode yet.\n");
Log::Print("X64 may be working when Sortix 0.5 comes out, or try the git master.\n");
while(true);
#endif
// Initialize the interrupt descriptor tables.
IDT::Init();
if ( BootInfo == NULL ) { Panic("kernel.cpp: The bootinfo structure was NULL. Are your bootloader multiboot compliant?"); }
// Initialize the kernel heap.
Maxsi::Memory::Init();
// Initialize the keyboard.
Keyboard::Init();
// Initialize system calls.
Syscall::Init();
// Initialize the scheduler.
Scheduler::Init();
Thread::Entry initstart = NULL;
// Create an address space for the first process.
addr_t addrspace = Memory::Fork();
// Use the new address space!
Memory::SwitchAddressSpace(addrspace);
// Create the first process!
Process* process = new Process(addrspace);
if ( process == 0 ) { Panic("kernel.cpp: Could not allocate the first process!"); }
InitRD::Init(initrd, initrdsize);
const char* initname = "init";
size_t programsize = 0;
byte* program = InitRD::Open(initname, &programsize);
if ( program == NULL ) { PanicF("initrd did not contain '%s'", initname); }
initstart = (Thread::Entry) ELF::Construct(process, program, programsize);
if ( initstart == NULL )
{
Panic("kernel.cpp: Could not construct ELF program");
}
// HACK: This should be determined from other information!
process->_endcodesection = 0x400000UL;
if ( Scheduler::CreateThread(process, initstart) == NULL )
{
Panic("Could not create a sample thread!");
}
// Lastly set up the timer driver and we are ready to run the OS.
Time::Init();
// Run the OS.
Scheduler::MainLoop();
}
}