private static unsafe Process CreateProcessFromElf(ElfSections elf, string path, uint argumentBufferSize = 0) { var proc = CreateEmptyProcess(new ProcessCreateOptions() { User = true }); KernelMessage.WriteLine("Create proc: {0}, PID: {1}", path, proc.ProcessID); proc.Path = path; proc.PageTable = PageTable.CreateInstance(); var allocator = new UserInitialPageAllocator() { DebugName = "UserInitial" }; allocator.Setup(new MemoryRegion(500 * 1024 * 1024, 60 * 1024 * 1014), AddressSpaceKind.Virtual); proc.UserPageAllocator = allocator; // Setup User PageTable proc.PageTableAllocAddr = VirtualPageManager.AllocatePages( KMath.DivCeil(proc.PageTable.InitalMemoryAllocationSize, 4096), new AllocatePageOptions { Pool = PageAllocationPool.Identity }); PageTable.KernelTable.SetWritable(proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize); proc.PageTable.UserProcSetup(proc.PageTableAllocAddr); proc.PageTable.Map(proc.PageTableAllocAddr, proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize); proc.PageTable.MapCopy(PageTable.KernelTable, BootInfoMemoryType.KernelTextSegment); proc.PageTable.SetExecutable(BootInfoMemoryType.KernelTextSegment); proc.PageTable.MapCopy(PageTable.KernelTable, Address.InterruptControlBlock, 4096); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.GDT)); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.IDT)); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.TSS)); var tmpKernelElfHeaders = SetupElfHeader(proc, elf); // Setup ELF Sections for (uint i = 0; i < elf.ProgramHeaderCount; i++) { var section = elf.GetProgramHeader(i); var memSize = section->MemSz; var fileSize = section->FileSz; var virtAddr = section->VAddr; var srcAddr = elf.GetProgramPhysAddr(section); if (memSize == 0) { continue; } KernelMessage.WriteLine("Setup Program Section VAddr {0:X8} SrcAddr {1:X8} Size {2:X8}", virtAddr, srcAddr, memSize); if (virtAddr == Addr.Zero) { var mem = allocator.AllocatePagesAddr(KMath.DivCeil(memSize, 4096)); tmpKernelElfHeaders[i].Addr = mem; virtAddr = mem; } // Map the Sections proc.PageTable.MapCopy(PageTable.KernelTable, srcAddr, virtAddr, memSize); if (i == 0) // TODO: Flags { proc.PageTable.SetReadonly(virtAddr, memSize); } if (memSize > fileSize) { MemoryOperation.Clear(srcAddr + fileSize, memSize - fileSize); } //if (name->Equals(".text")) // proc.PageTable.SetExecutable(virtAddr, size); } KernelMessage.WriteLine("proc sections are ready"); for (uint i = 0; i < elf.SectionHeaderCount; i++) { var section = elf.GetSectionHeader(i); var size = section->Size; var virtAddr = section->Addr; var srcAddr = elf.GetSectionPhysAddr(section); if (size == 0) { continue; } var name = elf.GetSectionName(section); if (virtAddr == Addr.Zero) { } else { if (name->Equals(".bss")) { MemoryOperation.Clear(srcAddr, size); proc.BrkBase = virtAddr + size; KernelMessage.WriteLine("sbrk_base: {0:X8}", proc.BrkBase); } } } // Detect Thread-Main var entryPoint = GetMainEntryPointFromElf(elf); KernelMessage.WriteLine("EntryPoint: {0:X8}", entryPoint); var defaultDispatchEntryPoint = GetDispatchEntryPointFromElf(elf); if (defaultDispatchEntryPoint != Addr.Zero) { KernelMessage.WriteLine("DispatchEntryPoint: {0:X8}", defaultDispatchEntryPoint); proc.Service.Init(defaultDispatchEntryPoint); } var mainThread = Scheduler.CreateThread(proc, new ThreadStartOptions(entryPoint) { ArgumentBufferSize = argumentBufferSize, AllowUserModeIOPort = true, DebugName = "UserProcMainThread", }); KernelMessage.WriteLine("Created Process {0} ProcessID={1}", path, proc.ProcessID); return(proc); }
private static unsafe Process StartProcessFromElf(ElfSections elf, string path, uint argumentBufferSize = 0) { var proc = CreateEmptyProcess(new ProcessCreateOptions() { User = true }); KernelMessage.WriteLine("Create proc: {0}, PID: {1}", path, proc.ProcessID); proc.Path = path; proc.PageTable = PageTable.CreateInstance(); var allocator = new UserInitialPageAllocator() { DebugName = "UserInitial" }; allocator.Setup(new MemoryRegion(500 * 1024 * 1024, 60 * 1024 * 1014), AddressSpaceKind.Virtual); proc.UserPageAllocator = allocator; // Setup User PageTable proc.PageTableAllocAddr = VirtualPageManager.AllocatePages( KMath.DivCeil(proc.PageTable.InitalMemoryAllocationSize, 4096), new AllocatePageOptions { Pool = PageAllocationPool.Identity }); PageTable.KernelTable.SetWritable(proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize); proc.PageTable.UserProcSetup(proc.PageTableAllocAddr); proc.PageTable.Map(proc.PageTableAllocAddr, proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize); proc.PageTable.MapCopy(PageTable.KernelTable, BootInfoMemoryType.KernelTextSegment); proc.PageTable.SetExecutable(BootInfoMemoryType.KernelTextSegment); proc.PageTable.MapCopy(PageTable.KernelTable, Address.InterruptControlBlock, 4096); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.GDT)); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.IDT)); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.TSS)); var tmpKernelElfHeaders = SetupElfHeader(proc, elf); // Setup ELF Sections for (uint i = 0; i < elf.SectionHeaderCount; i++) { var section = elf.GetSectionHeader(i); var name = elf.GeSectionName(section); var size = section->Size; var virtAddr = section->Addr; var srcAddr = elf.GetSectionPhysAddr(section); if (size == 0) { continue; } if (virtAddr == Addr.Zero) { var mem = allocator.AllocatePagesAddr(KMath.DivCeil(size, 4096)); tmpKernelElfHeaders[i].Addr = mem; virtAddr = mem; } var sb = new StringBuffer(); sb.Append("Map section "); sb.Append(name); sb.Append(" virt={0:X8} src={1:X8} size={2:X8}", virtAddr, srcAddr, size); KernelMessage.WriteLine(sb); //MemoryOperation.Copy4(elf.GetSectionPhysAddr(section), section->Addr, section->Size); // Map the Sections proc.PageTable.MapCopy(PageTable.KernelTable, srcAddr, virtAddr, size); if (name->Equals(".text")) { proc.PageTable.SetExecutable(virtAddr, size); } } KernelMessage.WriteLine("proc sections are ready"); // Detect Thread-Main var entryPoint = GetEntryPointFromElf(elf); KernelMessage.WriteLine("EntryPoint: {0:X8}", entryPoint); var mainThread = Scheduler.CreateThread(proc, new ThreadStartOptions(entryPoint) { ArgumentBufferSize = argumentBufferSize, AllowUserModeIOPort = true, DebugName = "UserProcMainThread", }); KernelMessage.WriteLine("Starting {0} on Thread {1}", path, mainThread.ThreadID); proc.Start(); return(proc); }