// public unsafe static void InitialKernelProtect() // { // KernelMessage.WriteLine("Protecting Memory..."); // // PageDirectoryEntry* pde = (PageDirectoryEntry*)AddrPageDirectory; // // for (int index = 0; index < 1024; index++) // // { // // pde[index].Writable = false; // // } // // PageTable.PageTableEntry* pte = (PageTable.PageTableEntry*)PageTable.AddrPageTable; // // for (int index = 0; index < 1024 * 32; index++) // // pte[index].Writable = false; // // InitialKernelProtect_MakeWritable_ByRegion(0, 90 * 1024 * 1024); // KernelMessage.WriteLine("Reload CR3 to {0:X8}", PageTable.AddrPageDirectory); // Native.SetCR3(PageTable.AddrPageDirectory); // //Native.Invlpg(); // KernelMessage.WriteLine("Protecting Memory done"); // } // public unsafe static void InitialKernelProtect_MakeWritable_ByRegion(uint startVirtAddr, uint endVirtAddr) // { // InitialKernelProtect_MakeWritable_BySize(startVirtAddr, endVirtAddr - startVirtAddr); // } // public unsafe static void InitialKernelProtect_MakeWritable_BySize(uint virtAddr, uint size) // { // var pages = KMath.DivCeil(size, 4096); // for (var i = 0; i < pages; i++) // { // var entry = PageTable.GetTableEntry(virtAddr); // entry->Writable = true; // } // } public static void Tests() { var ar = new KList <uint>(sizeof(uint)); ar.Add(44); ar.Add(55); KernelMessage.WriteLine("CNT: {0}", ManagedMemoy.AllocationCount); foreach (var num in ar) { KernelMessage.WriteLine("VAL: {0}", num); } KernelMessage.WriteLine("CNT: {0}", ManagedMemoy.AllocationCount); ar.Destroy(); KernelMessage.WriteLine("Pages free: {0}", PageFrameManager.PagesAvailable); for (var i = 0; i < 10000; i++) { var s = new int[] { 1, 2, 3, 4, }; s[1] = 5; Memory.FreeObject(s); } KernelMessage.WriteLine("Pages free: {0}", PageFrameManager.PagesAvailable); //Memory.FreeObject(s); }
public static void Setup() { KernelMessage.WriteLine("Setup Native Calls"); prog1Addr = KernelElf.Native.GetPhysAddrOfSymbol("test_proc1"); prog2Addr = KernelElf.Native.GetPhysAddrOfSymbol("test_proc2"); bochsDebugAddr = KernelElf.Native.GetPhysAddrOfSymbol("bochs_debug"); }
unsafe static ElfHelper FromSectionName(string name) { var sec = Main.GetSectionHeader(name); var addr = Main.GetSectionPhysAddr(sec); KernelMessage.WriteLine("Found embedded ELF at {0:X8}", addr); return(FromAddress(addr)); }
public static void Setup() { KernelMessage.WriteLine("Setup ELF Headers"); //KernelMessage.WriteLine("Image Header:"); //KernelMemory.DumpToConsoleLine(Address.KernelElfSection, 124); Main = FromAddress(Address.KernelElfSection); Native = FromSectionName("native"); }
public static void Setup() { KernelMessage.WriteLine("Setup IDT"); IDTAddr = PageFrameManager.AllocatePage(PageFrameRequestFlags.Default)->PhysicalAddress; KernelMessage.WriteLine("Address of IDT: {0:X8}", IDTAddr); // Setup IDT table Mosa.Runtime.Internal.MemoryClear(new IntPtr((uint)IDTAddr), 6); Intrinsic.Store16(new IntPtr((uint)IDTAddr), (Offset.TotalSize * 256) - 1); Intrinsic.Store32(new IntPtr((uint)IDTAddr), 2, IDTAddr + 6); KernelMessage.Write("Set IDT table entries..."); SetTableEntries(); KernelMessage.WriteLine("done"); handlers = new InterruptInfo[256]; for (var i = 0; i <= 255; i++) { var info = new InterruptInfo { Interrupt = i, CountStatistcs = true, Trace = true, Handler = UndefinedHandler }; if (i == (int)KnownInterrupt.ClockTimer) { info.Trace = false; info.CountStatistcs = false; } handlers[i] = info; } SetInterruptHandler(KnownInterrupt.DivideError, InterruptsHandlers.DivideError); SetInterruptHandler(KnownInterrupt.ArithmeticOverflowException, InterruptsHandlers.ArithmeticOverflowException); SetInterruptHandler(KnownInterrupt.BoundCheckError, InterruptsHandlers.BoundCheckError); SetInterruptHandler(KnownInterrupt.InvalidOpcode, InterruptsHandlers.InvalidOpcode); SetInterruptHandler(KnownInterrupt.CoProcessorNotAvailable, InterruptsHandlers.CoProcessorNotAvailable); SetInterruptHandler(KnownInterrupt.DoubleFault, InterruptsHandlers.DoubleFault); SetInterruptHandler(KnownInterrupt.CoProcessorSegmentOverrun, InterruptsHandlers.CoProcessorSegmentOverrun); SetInterruptHandler(KnownInterrupt.InvalidTSS, InterruptsHandlers.InvalidTSS); SetInterruptHandler(KnownInterrupt.SegmentNotPresent, InterruptsHandlers.SegmentNotPresent); SetInterruptHandler(KnownInterrupt.StackException, InterruptsHandlers.StackException); SetInterruptHandler(KnownInterrupt.GeneralProtectionException, InterruptsHandlers.GeneralProtectionException); SetInterruptHandler(KnownInterrupt.PageFault, InterruptsHandlers.PageFault); SetInterruptHandler(KnownInterrupt.CoProcessorError, InterruptsHandlers.CoProcessorError); SetInterruptHandler(KnownInterrupt.SIMDFloatinPointException, InterruptsHandlers.SIMDFloatinPointException); SetInterruptHandler(KnownInterrupt.ClockTimer, InterruptsHandlers.ClockTimer); KernelMessage.Write("Enabling interrupts..."); var idtAddr = (uint)IDTAddr; Native.Lidt(idtAddr); Native.Sti(); KernelMessage.WriteLine("done"); }
public static BootInfoMemory AllocateMemoryMap(USize size, BootInfoMemoryType type) { var map = new BootInfoMemory(); map.Start = PageStartAddr; map.Size = size; map.Type = type; PageStartAddr += size; KernelMessage.WriteLine("Allocated MemoryMap of Type {0} at {1:X8} with Size {2:X8}", (uint)type, map.Start, map.Size); return(map); }
public static void Setup() { KernelMessage.WriteLine("Multiboot Flags: {0:X}", Multiboot.Flags); BootInfo = (BootInfoHeader *)Address.KernelBootInfo; BootInfo->Magic = lonos.kernel.core.BootInfoHeader.BootInfoMagic; BootInfo->HeapStart = KMath.AlignValueCeil(Address.OriginalKernelElfSection + LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000); BootInfo->HeapSize = 0; BootInfo->InstalledPhysicalMemory = 128 * 1024 * 1024; SetupVideoInfo(); SetupMemoryMap(); }
static void MapKernelImage() { var phys = Address.KernelElfSection; var diff = Address.KernelBaseVirt - Address.KernelBasePhys; var endPhys = phys + OriginalKernelElf.TotalFileSize; var addr = phys; KernelMessage.WriteLine("Mapping Kernel Image from physical {0:X8} to virtual {1:X8}", phys, phys + diff); while (addr < endPhys) { PageTable.MapVirtualAddressToPhysical(addr + diff, addr); addr += 0x1000; } }
public unsafe static void DumpElfInfo() { var secArray = OriginalKernelElf.SectionHeaderArray; var secLength = OriginalKernelElf.SectionHeaderCount; KernelMessage.WriteLine("Found {0} Kernel Sections:", secLength); for (uint i = 0; i < secLength; i++) { var sec = OriginalKernelElf.GetSectionHeader(i); var name = OriginalKernelElf.GeSectionName(sec); var sb = new StringBuffer(name); KernelMessage.WriteLine(sb); } }
public unsafe static void Setup() { kmallocAllocator = new Allocator(); var ptr = (byte *)RawVirtualFrameAllocator.RequestRawVirtalMemoryPages(KMath.AlignValueCeil(Allocator.headSize, 4096)); for (var i = 0; i < Allocator.headSize; i++) { *(ptr + i) = 0; } kmallocAllocator.list_heads = (malloc_meta **)ptr; ManagedMemoy.useAllocator = true; KernelMessage.WriteLine("Memory free: {0} MB", (PageFrameManager.PagesAvailable * 4096) / 1024 / 1024); }
/// <summary> /// Video Stage /// </summary> public unsafe static void InitFrameBuffer() { if (!BootInfo.Header->FBPresent || BootInfo.Header->VBEMode < 0x100) { KernelMessage.Path("fb", "not present"); return; } KernelMessage.WriteLine("InitFrameBuffer"); fb = new FrameBuffer(BootInfo.Header->FbInfo.FbAddr, BootInfo.Header->FbInfo.FbWidth, BootInfo.Header->FbInfo.FbHeight, BootInfo.Header->FbInfo.FbPitch, 8); fb.Init(); FrameBufferTextScreen = new FrameBufferTextScreenDevice(fb); Console.SetOutputDevice(FrameBufferTextScreen); }
/// <summary> /// Sets up the PageTable /// </summary> public static void Setup(Addr addrPageDirectory, Addr addrPageTable) { KernelMessage.WriteLine("Setup PageTable"); AddrPageDirectory = addrPageDirectory; AddrPageTable = addrPageTable; // Setup Page Directory PageDirectoryEntry *pde = (PageDirectoryEntry *)AddrPageDirectory; for (int index = 0; index < 1024; index++) { pde[index] = new PageDirectoryEntry(); pde[index].Present = true; pde[index].Writable = true; pde[index].User = true; pde[index].PageTableEntry = (PageTableEntry *)(uint)(AddrPageTable + (index * 4096)); } // Map the first 128MB of memory (32786 4K pages) (why 128MB?) for (int index = 0; index < 1024 * 32; index++) { PageTableEntry *pte = (PageTableEntry *)AddrPageTable; pte[index] = new PageTableEntry(); pte[index].Present = true; pte[index].Writable = true; pte[index].User = true; pte[index].PhysicalAddress = (uint)(index * 4096); } // Unmap the first page for null pointer exceptions MapVirtualAddressToPhysical(0x0, 0x0, false); // Set CR3 register on processor - sets page directory KernelMessage.WriteLine("Set CR3 to {0:X8}", PageTable.AddrPageDirectory); Native.SetCR3(AddrPageDirectory); KernelMessage.Write("Enable Paging... "); // Set CR0.WP Native.SetCR0(Native.GetCR0() | 0x10000); // Set CR0 register on processor - turns on virtual memory Native.SetCR0(Native.GetCR0() | 0x80000000); KernelMessage.WriteLine("Done"); }
public static void ApplyMode(uint mode) { // https://de.wikibooks.org/wiki/Interrupts_80x86/_INT_10#Funktion_00h:_Setze_Bildschirmmodus_(EGA/VGA) KernelMessage.WriteLine("Screen VBE Mode: {0}", mode); switch (mode) { case 1: Rows = 25; Columns = 40; break; case 3: Rows = 25; Columns = 80; break; } }
/// <summary> /// Currently unused, because Kernel is loaded via from kernel.loader /// </summary> /*unsafe static ElfHelper FromMultiBootInfo(MultiBootInfo* multiBootInfo) * { * var helper = new ElfHelper * { * SectionHeaderArray = (ElfSectionHeader*)multiBootInfo->ElfSectionHeader->Addr, * StringTableSectionHeaderIndex = multiBootInfo->ElfSectionHeader->Shndx, * SectionHeaderCount = multiBootInfo->ElfSectionHeader->Count * }; * helper.Init(); * return helper; * }*/ unsafe static ElfHelper FromAddress(Addr elfStart) { var elfHeader = (ElfHeader *)elfStart; if (elfHeader->Ident1 != ElfHeader.Magic1) { KernelMessage.WriteLine("No valid ELF found at {0:X8}", elfStart); // TODO: Throw Excetion } var helper = new ElfHelper { PhyOffset = elfStart, SectionHeaderArray = (ElfSectionHeader *)(elfStart + elfHeader->ShOff), SectionHeaderCount = elfHeader->ShNum, StringTableSectionHeaderIndex = elfHeader->ShStrNdx }; helper.Init(); return(helper); }
public static void SetupStage2() { if (Header->Magic != BootInfoHeader.BootInfoMagic) { Present = false; KernelMessage.WriteLine("bootinfo not present"); return; } Present = true; KernelMessage.WriteLine("bootinfo present"); var mapLen = Header->MemoryMapLength; KernelMessage.WriteLine("Maps: {0}", mapLen); for (uint i = 0; i < mapLen; i++) { var mm = Header->MemoryMapArray[i]; KernelMessage.WriteLine("Map Start={0:X8}, Size={1:X8}, Type={2}", mm.Start, mm.Size, (uint)mm.Type); } }
static void SetupVideoInfo() { KernelMessage.WriteLine("VBE present: {0}", Multiboot.VBEPresent ? "yes" : "no"); if (Multiboot.VBEPresent) { KernelMessage.WriteLine("VBE Mode: {0}", Multiboot.VBEMode); } BootInfo->VBEPresent = Multiboot.VBEPresent; BootInfo->VBEMode = Multiboot.VBEMode; KernelMessage.WriteLine("FrameBuffer present: {0}", Multiboot.FBPresent ? "yes" : "no"); BootInfo->FBPresent = Multiboot.FBPresent; BootInfo->FbInfo = new BootInfoFramebufferInfo(); BootInfo->FbInfo.FbAddr = Multiboot.multiBootInfo->FbAddr; BootInfo->FbInfo.FbPitch = Multiboot.multiBootInfo->FbPitch; BootInfo->FbInfo.FbWidth = Multiboot.multiBootInfo->FbWidth; BootInfo->FbInfo.FbHeight = Multiboot.multiBootInfo->FbHeight; BootInfo->FbInfo.FbBpp = Multiboot.multiBootInfo->FbBpp; BootInfo->FbInfo.FbType = Multiboot.multiBootInfo->FbType; BootInfo->FbInfo.ColorInfo = Multiboot.multiBootInfo->ColorInfo; }
/// <summary> /// Sets up the GDT table and entries /// </summary> public static void Setup(Addr addr) { KernelMessage.Write("Setup GDT..."); gdtTableAddress = addr; table = (DescriptorTable *)gdtTableAddress; table->Clear(); table->AdressOfEntries = gdtTableAddress + DescriptorTable.StructSize; //Null segment var nullEntry = DescriptorTableEntry.CreateNullDescriptor(); table->AddEntry(nullEntry); //code segment var codeEntry = DescriptorTableEntry.CreateCode(0, 0xFFFFFFFF); codeEntry.CodeSegment_Readable = true; codeEntry.PriviligeRing = 0; codeEntry.Present = true; codeEntry.AddressMode = DescriptorTableEntry.EAddressMode.Bits32; codeEntry.Granularity = true; table->AddEntry(codeEntry); //data segment var dataEntry = DescriptorTableEntry.CreateData(0, 0xFFFFFFFF); dataEntry.DataSegment_Writable = true; dataEntry.PriviligeRing = 0; dataEntry.Present = true; dataEntry.AddressMode = DescriptorTableEntry.EAddressMode.Bits32; dataEntry.Granularity = true; table->AddEntry(dataEntry); Flush(); KernelMessage.WriteLine("Done"); }
/// <summary> /// Setups the free memory. /// </summary> unsafe void SetupFreeMemory() { if (!BootInfo.Present) { return; } for (var i = 0; i < KernelMemoryMapManager.Header->Used.Count; i++) { var map = KernelMemoryMapManager.Header->Used.Items[i]; if (map.Start >= BootInfo.Header->InstalledPhysicalMemory) { continue; } KernelMessage.WriteLine("{0:X}", map.Start); var page = GetPhysPage(map.Start); if (page == null) { continue; } page->Status = PageStatus.Used; PagesUsed++; } }
public static void Setup() { KernelMessage.WriteLine("Setup PIC"); byte masterMask = Native.In8(PIC1_Data); byte slaveMask = Native.In8(PIC2_Data); // ICW1 - Set Initialize Controller & Expect ICW4 Native.Out8(PIC1_Command, ICW1_Initialization + ICW1_ICW4); // ICW2 - interrupt offset Native.Out8(PIC1_Data, ICW2_MasterOffset); // ICW3 Native.Out8(PIC1_Data, 4); // ICW4 - Set 8086 Mode Native.Out8(PIC1_Data, ICW4_8086); // OCW1 Native.Out8(PIC1_Data, masterMask); // ICW1 - Set Initialize Controller & Expect ICW4 Native.Out8(PIC2_Command, ICW1_Initialization + ICW1_ICW4); // ICW2 - interrupt offset Native.Out8(PIC2_Data, ICW2_SlaveOffset); // ICW3 Native.Out8(PIC2_Data, 2); // ICW4 - Set 8086 Mode Native.Out8(PIC2_Data, ICW4_8086); // OCW1 Native.Out8(PIC2_Data, slaveMask); }
private static void FreeRawVirtualMemory(uint size) { KernelMessage.WriteLine("NotImplemented");; }
/// <summary> /// Allocate a physical page from the free list /// </summary> /// <returns>The page</returns> Page *Allocate(uint num) { KernelMessage.Write("Request {0} pages...", num); var cnt = 0; if (lastAllocatedPage == null) { lastAllocatedPage = PageArray; } Page *p = lastAllocatedPage->Next; while (true) { if (p == null) { p = PageArray; } if (p->Status == PageStatus.Free) { var head = p; // Found free Page. Check now free range. for (var i = 0; i < num; i++) { if (p == null) { break; // Reached end. SorRange is incomplete } if (p->Status != PageStatus.Free) // Used -> so we can abort the searach { break; } if (i == num - 1) { // all loops successful. So we found our range. head->Tail = p; head->PagesUsed = num; p = head; for (var n = 0; n < num; n++) { p->Status = PageStatus.Used; p->Head = head; p->Tail = head->Tail; p = p->Next; PagesUsed++; } lastAllocatedPage = p; KernelMessage.WriteLine("Allocated from {0:X8} to {1:X8}", (uint)head->PhysicalAddress, (uint)head->Tail->PhysicalAddress); return(head); } p = p->Next; } } if (p->Tail != null) { p = p->Tail; } p = p->Next; if (++cnt > PageCount) { break; } } Panic.Error("PageFrameAllocator: No free Page found"); return(null); }
public static void Main() { //Screen.BackgroundColor = ScreenColor.Green; //Screen.Color = ScreenColor.Red; //Screen.Clear(); //Screen.Goto(0, 0); //Screen.Write('A'); //Serial.SetupPort(Serial.COM1); //Serial.Write(Serial.COM1, "Hello"); BootMemory.Setup(); // Setup Kernel Log var kmsgHandler = new KernelMessageWriter(); KernelMessage.SetHandler(kmsgHandler); KernelMessage.WriteLine("<LOADER:CONSOLE:BEGIN>"); // Parse Boot Informations Multiboot.Setup(); // Parse Kernel ELF section SetupOriginalKernelElf(); // Print all section of Kernel ELF (for information only) DumpElfInfo(); // Copy Section to a final destination SetupKernelSection(); // Collection informations we need to pass to the kernel BootInfo_.Setup(); // Setup Global Descriptor Table var map = BootMemory.AllocateMemoryMap(0x1000, BootInfoMemoryType.GDT); BootInfo_.AddMap(map); GDT.Setup(map.Start); // Now we enable Paging. It's important that we do not cause a Page Fault Exception, // Because IDT is not setup yet, that could handle this kind of exception. map = BootMemory.AllocateMemoryMap(PageTable.InitalPageDirectorySize, BootInfoMemoryType.PageDirectory); BootInfo_.AddMap(map); var map2 = BootMemory.AllocateMemoryMap(PageTable.InitalPageTableSize, BootInfoMemoryType.PageTable); BootInfo_.AddMap(map2); PageTable.Setup(map.Start, map2.Start); // Because Kernel is compiled in virtual address space, we need to remap the pages MapKernelImage(); // Get Entry Point of Kernel uint kernelEntry = GetKernelStartAddr(); if (kernelEntry == 0) { KernelMessage.WriteLine("No kernel entry point found {0:X8}"); KernelMessage.WriteLine("Is the name of entry point correct?"); KernelMessage.WriteLine("Are symbols emitted?"); KernelMessage.WriteLine("System halt!"); while (true) { Native.Nop(); } } KernelMessage.WriteLine("Call Kernel Start at {0:X8}", kernelEntry); // Start Kernel. CallAddress(kernelEntry); // If we hit this code location, the Kernel Main method returned. // This would be a general fault. Normally, this code section will overwritten // by the kernel, so normally, it can never reach this code position. KernelMessage.WriteLine("Unexpected return from Kernel Start"); Debug.Break(); }
public unsafe static void Main() { BootInfo.SetupStage1(); // Field needs to be explicit set, because InitializeAssembly is not invoked yet. Memory.UseKernelWriteProtection = true; Memory.InitialKernelProtect(); ManagedMemoy.InitializeGCMemory(); Mosa.Runtime.StartUp.InitializeAssembly(); //Mosa.Runtime.StartUp.InitializeRuntimeMetadata(); ApiContext.Current = new ApiHost(); // Setup some pseudo devices Devices.InitStage1(); //Setup Output and Debug devices Devices.InitStage2(); // Write first output KernelMessage.WriteLine("<KERNEL:CONSOLE:BEGIN>"); KernelMessage.WriteLine("Starting Lonos Kernel..."); // Detect environment (Memory Maps, Video Mode, etc.) BootInfo.SetupStage2(); KernelMemoryMapManager.Setup(); KernelMemoryMapManager.Allocate(0x1000 * 1000, BootInfoMemoryType.PageDirectory); // Read own ELF-Headers and Sections KernelElf.Setup(); // Initialize the embedded code (actually only a little proof of conecept code) NativeCalls.Setup(); //InitialKernelProtect(); PageFrameManager.Setup(); KernelMessage.WriteLine("free: {0}", PageFrameManager.PagesAvailable); PageFrameManager.AllocatePages(PageFrameRequestFlags.Default, 10); KernelMessage.WriteLine("free: {0}", PageFrameManager.PagesAvailable); RawVirtualFrameAllocator.Setup(); Memory.Setup(); // Now Memory Sub System is working. At this point it's valid // to allocate memory dynamicly Devices.InitFrameBuffer(); // Setup Programmable Interrupt Table PIC.Setup(); // Setup Interrupt Descriptor Table // Important Note: IDT depends on GDT. Never setup IDT before GDT. IDTManager.Setup(); KernelMessage.WriteLine("Initialize Runtime Metadata"); Mosa.Runtime.StartUp.InitializeRuntimeMetadata(); KernelMessage.WriteLine("Performing some tests"); Tests(); KernelMessage.WriteLine("Enter Main Loop"); AppMain(); }