private static void OnTimerInterrupt(FOS_System.Object state) { #if SCHEDULER_HANDLER_TRACE || SCHEDULER_HANDLER_MIN_TRACE BasicConsole.Write("T"); #endif //LockupCounter++; //if (LockupCounter > 2000) //{ // Enable(); //} if (!Enabled || !Initialised) { return; } //LockupCounter = 0; #if SCHEDULER_HANDLER_TRACE || SCHEDULER_HANDLER_MIN_TRACE BasicConsole.Write("E"); #endif //UpdateCountdown -= MSFreq; //if (UpdateCountdown <= 0) //{ // UpdateCountdown = UpdatePeriod; UpdateCurrentState(); //} }
private static void EnterCritical(FOS_System.String caller) { //BasicConsole.WriteLine("Entering critical section..."); if (AccessLockInitialised) { if (AccessLock == null) { BasicConsole.WriteLine("HeapAccessLock is initialised but null?!"); BasicConsole.DelayOutput(10); } else { if (AccessLock.Locked && OutputTrace) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning: Heap about to try to re-enter spin lock..."); BasicConsole.Write("Enter lock caller: "); BasicConsole.WriteLine(caller); BasicConsole.SetTextColour(BasicConsole.default_colour); } AccessLock.Enter(); } } //else //{ // BasicConsole.WriteLine("HeapAccessLock not initialised - ignoring lock conditions."); // BasicConsole.DelayOutput(5); //} }
public ELFFile(File file) { theFile = file; if (theFile == null) { Console.Default.ErrorColour(); Console.Default.Write("Error constructing ELF file! theFile is null"); BasicConsole.Write("Error constructing ELF file! theFile is null"); if (file == null) { Console.Default.Write(" and file is null"); BasicConsole.Write(" and file is null"); } else { Console.Default.Write(" and file is NOT null"); BasicConsole.Write(" and file is NOT null"); } Console.Default.WriteLine("."); BasicConsole.WriteLine("."); Console.Default.DefaultColour(); ExceptionMethods.Throw(new FOS_System.Exception("Error loading ELF file! Supplied file is null.")); } theStream = new CachedFileStream(theFile.GetStream()); ReadHeader(); if (IsValidFile()) { ReadSectionHeaders(); ReadSegmentHeaders(); } }
public static void UpdateCurrentState() { #if SCHEDULER_HANDLER_TRACE BasicConsole.SetTextColour(BasicConsole.warning_colour); if (Processes.ProcessManager.Processes.Count > 1) { BasicConsole.WriteLine("Scheduler interrupt started..."); } #endif if (ProcessManager.CurrentProcess == null || ProcessManager.CurrentThread == null || ProcessManager.CurrentThread_State == null) { return; } UpdateInactiveThreads(); UpdateActiveThreads(); while (ActiveQueue.Count == 0) { //#if SCHEDULER_HANDLER_TRACE BasicConsole.WriteLine("WARNING: Scheduler preventing infinite loop by early-updating sleeping threads."); //#endif UpdateInactiveThreads(); } Thread nextThread = (Thread)ActiveQueue.PeekMin(); #if SCHEDULER_HANDLER_TRACE || SCHEDULER_HANDLER_MIN_TRACE BasicConsole.Write("Active: "); BasicConsole.Write(nextThread.Owner.Name); BasicConsole.Write(" - "); BasicConsole.WriteLine(nextThread.Name); #endif ProcessManager.SwitchProcess(nextThread.Owner.Id, (int)nextThread.Id); if (!ProcessManager.CurrentThread_State->Started) { SetupThreadForStart(); } #if SCHEDULER_HANDLER_TRACE if (Processes.ProcessManager.Processes.Count > 1) { BasicConsole.WriteLine("Scheduler interrupt ended."); } BasicConsole.SetTextColour(BasicConsole.default_colour); #endif }
protected void AnalysePortStatus(byte j, ushort val) { #if UHCI_TRACE BasicConsole.WriteLine("UHCI: Anaylse port status"); BasicConsole.DelayOutput(5); #endif HCPort port = GetPort(j); if ((val & UHCI_Consts.PORT_LOWSPEED_DEVICE) != 0) { #if UHCI_TRACE BasicConsole.Write("UHCI: Lowspeed device"); #endif port.speed = USBPortSpeed.Low; // Save lowspeed/fullspeed information in data } else { #if UHCI_TRACE BasicConsole.Write("UHCI: Fullspeed device"); #endif port.speed = USBPortSpeed.Full; // Save lowspeed/fullspeed information in data } if (((val & UHCI_Consts.PORT_CS) != 0) && !port.connected) { #if UHCI_TRACE BasicConsole.WriteLine(" attached."); #endif port.connected = true; ResetPort(j); // reset on attached SetupUSBDevice(j); } else if (port.connected) { #if UHCI_TRACE BasicConsole.WriteLine(" removed."); #endif port.connected = false; if (port.deviceInfo != null) { port.deviceInfo.FreePort(); } } #if UHCI_TRACE else { BasicConsole.WriteLine(" not attached."); } #endif }
public static void Main() { while (!Terminate) { //bool reenable = Hardware.Processes.Scheduler.Enabled; try { //if (reenable) //{ // Hardware.Processes.Scheduler.Disable(); //} #if GCTASK_TRACE BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.Write("GC cleaning..."); BasicConsole.WriteLine(Hardware.Processes.ProcessManager.CurrentProcess.Name); BasicConsole.SetTextColour(BasicConsole.default_colour); #endif FOS_System.GC.Cleanup(); #if GCTASK_TRACE BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("GC stopped (1)."); BasicConsole.SetTextColour(BasicConsole.default_colour); #endif } catch { #if GCTASK_TRACE BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("GC error."); BasicConsole.SetTextColour(BasicConsole.default_colour); #endif } #if GCTASK_TRACE BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("GC stopped (2)."); BasicConsole.SetTextColour(BasicConsole.default_colour); #endif //if (reenable) //{ // Hardware.Processes.Scheduler.Enable(); //} Processes.SystemCalls.SleepThread(1000); } }
/// <summary> /// Initializes all available partitions looking for valid /// file systems. /// </summary> public static void InitPartitions() { for (int i = 0; i < Partitions.Count; i++) { try { Partition aPartition = (Partition)Partitions[i]; if (!aPartition.Mapped) { //BasicConsole.WriteLine("Attempting to create FAT File System..."); FileSystem newFS = null; if (aPartition is Disk.ISO9660.PrimaryVolumeDescriptor) { newFS = new ISO9660.ISO9660FileSystem((Disk.ISO9660.PrimaryVolumeDescriptor)aPartition); } else { newFS = new FOS_System.IO.FAT.FATFileSystem(aPartition); } if (newFS.IsValid) { FOS_System.String mappingPrefix = FOS_System.String.New(3); mappingPrefix[0] = (char)((int)('A') + i); mappingPrefix[1] = ':'; mappingPrefix[2] = PathDelimiter; newFS.TheMapping = new FileSystemMapping(mappingPrefix, newFS); FileSystemMappings.Add(newFS.TheMapping); aPartition.Mapped = true; } //else //{ // BasicConsole.WriteLine("Partition not formatted as valid FAT file-system."); //} } } catch { BasicConsole.Write("Error initialising partition: "); BasicConsole.WriteLine(i); BasicConsole.WriteLine(ExceptionMethods.CurrentException.Message); //BasicConsole.DelayOutput(20); } } }
public void LoadSegments(ELFFile fileToLoadFrom, ref bool OK, ref bool DynamicLinkingRequired, uint memBaseAddress) { uint fileBaseAddress = fileToLoadFrom.BaseAddress; List Segments = fileToLoadFrom.Segments; for (int i = 0; i < Segments.Count; i++) { ELFSegment segment = (ELFSegment)Segments[i]; if (segment.Header.Type == ELFSegmentType.Interp || segment.Header.Type == ELFSegmentType.Dynamic) { DynamicLinkingRequired = true; } else if (segment.Header.Type == ELFSegmentType.Load) { int bytesRead = segment.Read(fileToLoadFrom.TheStream); if (bytesRead != segment.Header.FileSize) { OK = false; ExceptionMethods.Throw(new FOS_System.Exception("Error loading ELF segments! Failed to load correct segment bytes from file.")); } byte *destMemPtr = (segment.Header.VAddr - fileBaseAddress) + memBaseAddress; byte *pageAlignedDestMemPtr = (byte *)((uint)destMemPtr & 0xFFFFF000); Console.Default.Write(" Loading segment from "); Console.Default.Write_AsDecimal((uint)segment.Header.VAddr); Console.Default.Write(" to "); Console.Default.WriteLine_AsDecimal((uint)destMemPtr); BasicConsole.Write(" Loading segment from "); BasicConsole.Write((uint)segment.Header.VAddr); BasicConsole.Write(" to "); BasicConsole.WriteLine((uint)destMemPtr); Hardware.Processes.Thread.Sleep(1000); uint copyOffset = (uint)(destMemPtr - pageAlignedDestMemPtr); uint copyFromOffset = 0; bool executable = (segment.Header.Flags & ELFFlags.Executable) != 0; for (uint pageOffset = 0; pageOffset < segment.Header.MemSize; pageOffset += 4096) { uint physPageAddr = Hardware.VirtMemManager.FindFreePhysPage(); uint virtPageAddr = (uint)pageAlignedDestMemPtr + pageOffset; Hardware.VirtMemManager.Map( physPageAddr, virtPageAddr, 4096, theProcess.UserMode ? Hardware.VirtMem.VirtMemImpl.PageFlags.None : Hardware.VirtMem.VirtMemImpl.PageFlags.KernelOnly); ProcessManager.CurrentProcess.TheMemoryLayout.AddDataPage(physPageAddr, virtPageAddr); if (executable) { theProcess.TheMemoryLayout.AddCodePage(physPageAddr, virtPageAddr); } else { theProcess.TheMemoryLayout.AddDataPage(physPageAddr, virtPageAddr); } uint copySize = FOS_System.Math.Min((uint)bytesRead, 4096 - copyOffset); if (copySize > 0) { Utilities.MemoryUtils.MemCpy_32( (byte *)(virtPageAddr + copyOffset), ((byte *)Utilities.ObjectUtilities.GetHandle(segment.Data)) + FOS_System.Array.FieldsBytesSize + pageOffset - copyFromOffset, copySize); bytesRead -= (int)copySize; } for (uint j = copySize + copyOffset; j < 4096; j++) { *(byte *)(virtPageAddr + j) = 0; } if (copyOffset > 0) { copyFromOffset += copyOffset; copyOffset = 0; } } } } }
public static void DeferredSyscallsThread_Main() { while (!Terminating) { if (DeferredSyscallsInfo_Queued.Count == 0) { SystemCalls.SleepThread(SystemCalls.IndefiniteSleepThread); } while (DeferredSyscallsInfo_Queued.Count > 0) { // Scheduler must be disabled during pop/push from circular buffer or we can // end up in an infinite lock. Consider what happens if a process invokes // a deferred system call during the pop/push here and at the end of this loop. #if DSC_TRACE BasicConsole.WriteLine("DSC: Pausing scheduler..."); #endif Scheduler.Disable(/*"DSC 1"*/); #if DSC_TRACE BasicConsole.WriteLine("DSC: Popping queued info object..."); #endif DeferredSyscallInfo info = (DeferredSyscallInfo)DeferredSyscallsInfo_Queued.Pop(); #if DSC_TRACE BasicConsole.WriteLine("DSC: Resuming scheduler..."); #endif Scheduler.Enable(); #if DSC_TRACE BasicConsole.WriteLine("DSC: Getting process & thread..."); #endif Process CallerProcess = ProcessManager.GetProcessById(info.ProcessId); Thread CallerThread = ProcessManager.GetThreadById(info.ThreadId, CallerProcess); #if DSC_TRACE BasicConsole.Write("DSC: Process: "); BasicConsole.WriteLine(CallerProcess.Name); BasicConsole.Write("DSC: Thread: "); BasicConsole.WriteLine(CallerThread.Name); #endif ProcessManager.EnableKernelAccessToProcessMemory(CallerProcess); #if DSC_TRACE BasicConsole.WriteLine("DSC: Getting data..."); #endif SystemCallNumbers SysCallNumber = (SystemCallNumbers)CallerThread.SysCallNumber; uint Param1 = CallerThread.Param1; uint Param2 = CallerThread.Param2; uint Param3 = CallerThread.Param3; uint Return2 = CallerThread.Return2; uint Return3 = CallerThread.Return3; uint Return4 = CallerThread.Return4; #if DSC_TRACE BasicConsole.WriteLine("DSC: Getting data done."); #endif ProcessManager.DisableKernelAccessToProcessMemory(CallerProcess); #if DSC_TRACE BasicConsole.WriteLine("DSC: Calling..."); #endif SystemCallResults result = HandleDeferredSystemCall( CallerProcess, CallerThread, SysCallNumber, Param1, Param2, Param3, ref Return2, ref Return3, ref Return4); #if DSC_TRACE BasicConsole.WriteLine("DSC: Ending call..."); #endif if (result != SystemCallResults.Deferred) { EndDeferredSystemCall(CallerProcess, CallerThread, result, Return2, Return3, Return4); } #if DSC_TRACE BasicConsole.WriteLine("DSC: Resetting info object..."); #endif info.ProcessId = 0; info.ThreadId = 0; // See comment at top of loop for why this is necessary #if DSC_TRACE BasicConsole.WriteLine("DSC: Pausing scheduler..."); #endif Scheduler.Disable(/*"DSC 2"*/); #if DSC_TRACE BasicConsole.WriteLine("DSC: Queuing info object..."); #endif DeferredSyscallsInfo_Unqueued.Push(info); #if DSC_TRACE BasicConsole.WriteLine("DSC: Resuming scheduler..."); #endif Scheduler.Enable(); } } }
public static void *Alloc(UInt32 size, UInt32 boundary, FOS_System.String caller) { #if HEAP_TRACE if (OutputTrace) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Attempt to alloc mem...."); BasicConsole.SetTextColour(BasicConsole.default_colour); } #endif if (PreventAllocation) { bool BCPOEnabled = BasicConsole.PrimaryOutputEnabled; BasicConsole.PrimaryOutputEnabled = true; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.Write("Allocation of memory prevented! Reason: "); BasicConsole.WriteLine(PreventReason); BasicConsole.Write(" > Caller: "); BasicConsole.WriteLine(caller); BasicConsole.DelayOutput(5); BasicConsole.SetTextColour(BasicConsole.default_colour); BasicConsole.PrimaryOutputEnabled = BCPOEnabled; return(null); } EnterCritical("Alloc"); HeapBlock *b; byte * bm; UInt32 bcnt; UInt32 x, y, z; UInt32 bneed; byte nid; if (boundary > 1) { size += (boundary - 1); } /* iterate blocks */ for (b = fblock; (UInt32)b != 0; b = b->next) { /* check if block has enough room */ if (b->size - (b->used * b->bsize) >= size) { bcnt = b->size / b->bsize; bneed = (size / b->bsize) * b->bsize < size ? size / b->bsize + 1 : size / b->bsize; bm = (byte *)&b[1]; for (x = (b->lfb + 1 >= bcnt ? 0 : b->lfb + 1); x != b->lfb; ++x) { /* just wrap around */ if (x >= bcnt) { x = 0; } if (bm[x] == 0) { /* count free blocks */ for (y = 0; bm[x + y] == 0 && y < bneed && (x + y) < bcnt; ++y) { ; } /* we have enough, now allocate them */ if (y == bneed) { /* find ID that does not match left or right */ nid = GetNID(bm[x - 1], bm[x + y]); /* allocate by setting id */ for (z = 0; z < y; ++z) { bm[x + z] = nid; } /* optimization */ b->lfb = (x + bneed) - 2; /* count used blocks NOT bytes */ b->used += y; void *result = (void *)(x * b->bsize + (UInt32)(&b[1])); if (boundary > 1) { result = (void *)((((UInt32)result) + (boundary - 1)) & ~(boundary - 1)); //#if HEAP_TRACE // ExitCritical(); // BasicConsole.WriteLine(((FOS_System.String)"Allocated address ") + (uint)result + " on boundary " + boundary + " for " + caller); // EnterCritical("Alloc:Boundary condition"); //#endif } ExitCritical(); return(result); } /* x will be incremented by one ONCE more in our FOR loop */ x += (y - 1); continue; } } } } { bool BCPOEnabled = BasicConsole.PrimaryOutputEnabled; BasicConsole.PrimaryOutputEnabled = true; BasicConsole.Write("Heap ("); BasicConsole.Write(name); BasicConsole.WriteLine(") out of memory!"); if (fblock == null) { BasicConsole.WriteLine(" !! fblock == null"); } else if (GetTotalFreeMem() < size) { if (GetTotalMem() == 0) { BasicConsole.WriteLine(" !! Out of free mem because total mem is zero."); } else if (GetTotalMem() <= 8092) { BasicConsole.WriteLine(" !! Out of free mem because total mem is <= 8092 bytes."); } else { BasicConsole.WriteLine(" !! Genuinely out of memory."); } } BasicConsole.PrimaryOutputEnabled = BCPOEnabled; } ExitCritical(); return(null); }
public override void MapKernel() { #if PAGING_TRACE BasicConsole.Write("Mapping 1st 1MiB..."); #endif uint VirtToPhysOffset = GetKernelVirtToPhysOffset(); //Identity and virtual map the first 1MiB uint physAddr = 0; uint virtAddr = VirtToPhysOffset; for (; physAddr < 0x100000; physAddr += 4096, virtAddr += 4096) { Map(physAddr, physAddr, PageFlags.Present | PageFlags.Writeable); Map(physAddr, virtAddr, PageFlags.Present | PageFlags.Writeable); } #if PAGING_TRACE BasicConsole.WriteLine("Done."); BasicConsole.WriteLine("Mapping kernel..."); #endif //Map in the main kernel memory //Map all the required pages in between these two pointers. uint KernelMemStartPtr = (uint)GetKernelMemStartPtr(); uint KernelMemEndPtr = (uint)GetKernelMemEndPtr(); #if PAGING_TRACE BasicConsole.WriteLine("Start pointer : " + (FOS_System.String)KernelMemStartPtr); BasicConsole.WriteLine("End pointer : " + (FOS_System.String)KernelMemEndPtr); #endif // Round the start pointer down to nearest page KernelMemStartPtr = ((KernelMemStartPtr / 4096) * 4096); // Round the end pointer up to nearest page KernelMemEndPtr = (((KernelMemEndPtr / 4096) + 1) * 4096); #if PAGING_TRACE BasicConsole.WriteLine("Start pointer : " + (FOS_System.String)KernelMemStartPtr); BasicConsole.WriteLine("End pointer : " + (FOS_System.String)KernelMemEndPtr); #endif physAddr = KernelMemStartPtr - VirtToPhysOffset; #if PAGING_TRACE BasicConsole.WriteLine("Phys addr : " + (FOS_System.String)physAddr); BasicConsole.DelayOutput(5); #endif for (; KernelMemStartPtr <= KernelMemEndPtr; KernelMemStartPtr += 4096, physAddr += 4096) { Map(physAddr, KernelMemStartPtr, PageFlags.Present | PageFlags.Writeable | PageFlags.KernelOnly); } #if PAGING_TRACE BasicConsole.WriteLine("Done."); BasicConsole.DelayOutput(5); #endif }
public static void Main() { OwnerThread = ProcessManager.CurrentThread; Thread.Sleep_Indefinitely(); while (!Terminate) { //Scheduler.Disable(); Awake = false; //BasicConsole.WriteLine("Playing notes..."); while (LiveNoteRequests.Count > 0) { //BasicConsole.WriteLine("Playing note..."); NoteRequest theReq = (NoteRequest)LiveNoteRequests.Pop(); try { Hardware.Timers.PIT.MusicalNote note = theReq.note; Hardware.Timers.PIT.MusicalNoteValue duration = theReq.duration; int bpm = theReq.bpm; int dur_ms = (int)duration * 60 * 1000 / (bpm * 16); long do_ms = dur_ms; if (dur_ms >= 2000) { dur_ms -= 2000; do_ms = 2000; } else { dur_ms = 0; } NoteState state = new NoteState() { dur_ms = dur_ms }; if (note != Timers.PIT.MusicalNote.Silent) { Hardware.Timers.PIT.ThePIT.PlaySound((int)note); } Playing = true; state.handlerId = Hardware.Timers.PIT.ThePIT.RegisterHandler(new Hardware.Timers.PITHandler(SysCall_StopNoteHandler, state, 1000000L * do_ms, true)); while (Playing) { Thread.Sleep(50); } } catch { BasicConsole.Write("Error processing note request! "); if (ExceptionMethods.CurrentException != null) { BasicConsole.Write(ExceptionMethods.CurrentException.Message); } BasicConsole.WriteLine(); Playing = false; Hardware.Timers.PIT.ThePIT.MuteSound(); BasicConsole.DelayOutput(15); } finally { DeadNoteRequests.Push(theReq); } } //BasicConsole.WriteLine("Finished playing notes."); if (!Awake) { //BasicConsole.WriteLine("Sleeping non-critical interrupts thread..."); //Scheduler.Enable(); if (!Thread.Sleep_Indefinitely()) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Failed to sleep play notes thread!"); BasicConsole.SetTextColour(BasicConsole.default_colour); } } } }
protected override void _IssueTransfer(USBTransfer transfer) { #if UHCI_TRACE BasicConsole.WriteLine("UHCI: Issue Transfer"); BasicConsole.DelayOutput(5); #endif UHCITransaction firstTransaction = (UHCITransaction)((USBTransaction)transfer.transactions[0]).underlyingTz; UHCITransaction lastTransaction = (UHCITransaction)((USBTransaction)transfer.transactions[transfer.transactions.Count - 1]).underlyingTz; UHCI_qTD.SetIntOnComplete(lastTransaction.qTD, true); // We want an interrupt after complete transfer CreateQH((UHCI_QueueHead_Struct *)transfer.underlyingTransferData, (uint)transfer.underlyingTransferData, firstTransaction.qTD); #if UHCI_TRACE BasicConsole.WriteLine(" Queue head data:"); BasicConsole.DumpMemory(transfer.underlyingTransferData, sizeof(UHCI_QueueHead_Struct)); BasicConsole.WriteLine(" Transactions data:"); for (int i = 0; i < transfer.transactions.Count; i++) { BasicConsole.Write(" "); BasicConsole.Write(i); BasicConsole.WriteLine(" : "); BasicConsole.WriteLine(" - qTD:"); BasicConsole.DumpMemory( ((UHCITransaction)((USBTransaction)transfer.transactions[i]).underlyingTz).qTD, sizeof(UHCI_qTD_Struct)); BasicConsole.WriteLine(" - qTDBuffer:"); BasicConsole.DumpMemory( ((UHCITransaction)((USBTransaction)transfer.transactions[i]).underlyingTz).qTDBuffer, 16); } BasicConsole.DelayOutput(60); BasicConsole.WriteLine("UHCI: Issuing transfer..."); #endif for (byte i = 0; i < UHCI_Consts.NUMBER_OF_UHCI_RETRIES && !transfer.success; i++) { TransactionsCompleted = 0; for (int j = 0; j < transfer.transactions.Count; j++) { USBTransaction elem = (USBTransaction)transfer.transactions[j]; UHCITransaction uT = (UHCITransaction)(elem.underlyingTz); uT.qTD->u1 = uT.qTD->u1 & 0xFF00FFFF; UHCI_qTD.SetActive(uT.qTD, true); } // stop scheduler USBSTS.Write_UInt16(UHCI_Consts.STS_MASK); USBCMD.Write_UInt16((ushort)(USBCMD.Read_UInt16() & ~UHCI_Consts.CMD_RS)); while ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) == 0) { Hardware.Devices.Timer.Default.Wait(10); } // update scheduler uint qhPhysAddr = ((uint)VirtMemManager.GetPhysicalAddress(transfer.underlyingTransferData) | UHCI_Consts.BIT_QH); FrameList[0] = qhPhysAddr; FRBASEADD.Write_UInt32((uint)VirtMemManager.GetPhysicalAddress(FrameList)); FRNUM.Write_UInt16(0); // start scheduler USBSTS.Write_UInt16(UHCI_Consts.STS_MASK); USBCMD.Write_UInt16((ushort)(USBCMD.Read_UInt16() | UHCI_Consts.CMD_RS)); while ((USBSTS.Read_UInt16() & UHCI_Consts.STS_HCHALTED) != 0) { Hardware.Devices.Timer.Default.Wait(10); } #if UHCI_TRACE BasicConsole.WriteLine(((FOS_System.String) "USBINT val: ") + USBINTR.Read_UInt16()); #endif // run transactions bool active = true; int timeout = 100; //5 seconds while (active && timeout > 0) { active = false; for (int j = 0; j < transfer.transactions.Count; j++) { USBTransaction elem = (USBTransaction)transfer.transactions[j]; UHCITransaction uT = (UHCITransaction)(elem.underlyingTz); active = active || ((uT.qTD->u1 & 0x00FF0000) == 0x00800000); } Hardware.Devices.Timer.Default.Wait(50); timeout--; } #if UHCI_TRACE BasicConsole.WriteLine("Finished waiting."); #endif FrameList[0] = UHCI_Consts.BIT_T; if (timeout == 0 || TransactionsCompleted != transfer.transactions.Count) { #if UHCI_TRACE BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("UHCI: Error! Transactions wait timed out or wrong number of transactions completed."); BasicConsole.SetTextColour(BasicConsole.default_colour); BasicConsole.WriteLine(((FOS_System.String) "Transactions completed: ") + TransactionsCompleted); if (timeout == 0) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("UHCI: Error! Transfer timed out."); BasicConsole.SetTextColour(BasicConsole.default_colour); } #endif transfer.success = false; bool completeDespiteNoInterrupt = true; for (int j = 0; j < transfer.transactions.Count; j++) { USBTransaction elem = (USBTransaction)transfer.transactions[j]; UHCITransaction uT = (UHCITransaction)(elem.underlyingTz); #if UHCI_TRACE BasicConsole.WriteLine(((FOS_System.String) "u1=") + uT.qTD->u1 + ", u2=" + uT.qTD->u2); BasicConsole.WriteLine(((FOS_System.String) "Status=") + (byte)(uT.qTD->u1 >> 16)); #endif completeDespiteNoInterrupt = completeDespiteNoInterrupt && isTransactionSuccessful(uT); } transfer.success = completeDespiteNoInterrupt; #if UHCI_TRACE BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine(((FOS_System.String) "Complete despite no interrupts: ") + completeDespiteNoInterrupt); BasicConsole.SetTextColour(BasicConsole.default_colour); BasicConsole.DelayOutput(5); #endif } else { transfer.success = true; } if (transfer.success) { // check conditions and save data for (int j = 0; j < transfer.transactions.Count; j++) { USBTransaction elem = (USBTransaction)transfer.transactions[j]; UHCITransaction uT = (UHCITransaction)(elem.underlyingTz); transfer.success = transfer.success && isTransactionSuccessful(uT); // executed w/o error if (uT.inBuffer != null && uT.inLength != 0) { MemoryUtils.MemCpy_32((byte *)uT.inBuffer, (byte *)uT.qTDBuffer, uT.inLength); } } } #if UHCI_TRACE if (!transfer.success) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("UHCI: Transfer failed."); BasicConsole.SetTextColour(BasicConsole.default_colour); } else { BasicConsole.SetTextColour((char)0x0200); BasicConsole.WriteLine("Transfer succeeded."); BasicConsole.SetTextColour(BasicConsole.default_colour); } #endif } }
public static void Main() { BasicConsole.WriteLine("Window Manager: Started."); // Initialise heap & GC Hardware.Processes.ProcessManager.CurrentProcess.InitHeap(); // Start thread for calling GC Cleanup method if (SystemCalls.StartThread(GCCleanupTask.Main, out GCThreadId) != SystemCallResults.OK) { BasicConsole.WriteLine("Window Manager: GC thread failed to create!"); } // Initialise connected pipes list ConnectedPipes = new List(); // Start thread for handling background input processing if (SystemCalls.StartThread(InputProcessing, out InputProcessingThreadId) != SystemCallResults.OK) { BasicConsole.WriteLine("Window Manager: InputProcessing thread failed to create!"); } BasicConsole.Write("WM > InputProcessing thread id: "); BasicConsole.WriteLine(InputProcessingThreadId); BasicConsole.Write("WM > Register RegisterPipeOutpoint syscall handler"); SystemCalls.RegisterSyscallHandler(SystemCallNumbers.RegisterPipeOutpoint, SyscallHandler); // Start thread for handling background output processing if (SystemCalls.StartThread(OutputProcessing, out OutputProcessingThreadId) != SystemCallResults.OK) { BasicConsole.WriteLine("Window Manager: OutputProcessing thread failed to create!"); } BasicConsole.WriteLine("WM > Init keyboard"); Keyboard.InitDefault(); BasicConsole.WriteLine("WM > Register IRQ 1 handler"); SystemCalls.RegisterIRQHandler(1, HandleIRQ); BasicConsole.WriteLine("WM > Wait for pipe to be created"); // Wait for pipe to be created ready_count++; SystemCalls.SleepThread(SystemCalls.IndefiniteSleepThread); PipeInfo CurrentPipeInfo = null; while (!Terminating) { try { if (CurrentPipeIdx > -1) { if (CurrentPipeIndex_Changed) { CurrentPipeInfo = ((PipeInfo)ConnectedPipes[CurrentPipeIdx]); CurrentPipeIndex_Changed = false; CurrentPipeInfo.TheConsole.Update(); } CurrentPipeInfo.TheConsole.Write(CurrentPipeInfo.StdOut.Read(false)); } } catch { if (ExceptionMethods.CurrentException is Pipes.Exceptions.RWFailedException) { SystemCalls.SleepThread(50); } else { BasicConsole.WriteLine("WM > Exception running window manager."); BasicConsole.WriteLine(ExceptionMethods.CurrentException.Message); } } } }
public static void *NewObj(FOS_System.Type theType) { if (!Enabled) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning! GC returning null pointer because GC not enabled."); BasicConsole.Write("Last disabler: "); BasicConsole.WriteLine(lastDisabler); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } #if GC_TRACE if (OutputTrace) { BasicConsole.WriteLine("NewObj"); } #endif EnterCritical("NewObj"); try { InsideGC = true; //Alloc space for GC header that prefixes object data //Alloc space for new object uint totalSize = theType.Size; totalSize += (uint)sizeof(GCHeader); GCHeader *newObjPtr = (GCHeader *)Heap.AllocZeroed(totalSize, "GC : NewObject"); if ((UInt32)newObjPtr == 0) { InsideGC = false; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new object because the heap returned a null pointer."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } NumObjs++; //Initialise the GCHeader SetSignature(newObjPtr); newObjPtr->RefCount = 1; //Initialise the object _Type field FOS_System.ObjectWithType newObj = (FOS_System.ObjectWithType)Utilities.ObjectUtilities.GetObject(newObjPtr + 1); newObj._Type = theType; //Move past GCHeader byte *newObjBytePtr = (byte *)(newObjPtr + 1); InsideGC = false; return(newObjBytePtr); } finally { ExitCritical(); } }
public static void *NewArr(int length, FOS_System.Type elemType) { if (!Enabled) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning! GC returning null pointer because GC not enabled."); BasicConsole.Write("Last disabler: "); BasicConsole.WriteLine(lastDisabler); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } #if GC_TRACE if (OutputTrace) { BasicConsole.WriteLine("NewArr"); } #endif EnterCritical("NewArr"); try { if (length < 0) { ExceptionMethods.Throw_OverflowException(); } InsideGC = true; //Alloc space for GC header that prefixes object data //Alloc space for new array object //Alloc space for new array elems uint totalSize = ((FOS_System.Type) typeof(FOS_System.Array)).Size; if (elemType.IsValueType) { totalSize += elemType.Size * (uint)length; } else { totalSize += elemType.StackSize * (uint)length; } totalSize += (uint)sizeof(GCHeader); GCHeader *newObjPtr = (GCHeader *)Heap.AllocZeroed(totalSize, "GC : NewArray"); if ((UInt32)newObjPtr == 0) { InsideGC = false; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new array because the heap returned a null pointer."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } NumObjs++; //Initialise the GCHeader SetSignature(newObjPtr); newObjPtr->RefCount = 1; FOS_System.Array newArr = (FOS_System.Array)Utilities.ObjectUtilities.GetObject(newObjPtr + 1); newArr._Type = (FOS_System.Type) typeof(FOS_System.Array); newArr.length = length; newArr.elemType = elemType; //Move past GCHeader byte *newObjBytePtr = (byte *)(newObjPtr + 1); InsideGC = false; return(newObjBytePtr); } finally { ExitCritical(); } }
private static void UpdateList(Thread t, bool skipRemove) { Scheduler.Disable(/*"Scheduler UpdateList"*/); #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.Write("S > UpdateList: "); BasicConsole.WriteLine(t.Name); #endif if (!skipRemove) { #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: No skip remove"); #endif switch (t.LastActiveState) { case Thread.ActiveStates.NotStarted: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: LastActiveState: NotStarted"); #endif ActiveQueue.Delete(t); break; case Thread.ActiveStates.Terminated: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: LastActiveState: Terminated"); #endif break; case Thread.ActiveStates.Active: #if SCHEDULER_TRACE BasicConsole.WriteLine("Scheduler > Deleting thread from Active queue..."); #endif //try //{ #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: LastActiveState: Active (1x1)"); #endif ActiveQueue.Delete(t); #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: LastActiveState: Active - done."); #endif //} //catch //{ // BasicConsole.WriteLine("Error removing from active list:"); // BasicConsole.WriteLine(ExceptionMethods.CurrentException.Message); //} break; case Thread.ActiveStates.Inactive: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: LastActiveState: Inactive"); #endif InactiveQueue.Delete(t); break; case Thread.ActiveStates.Suspended: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: LastActiveState: Suspended"); #endif //SuspendedList.Remove(t); break; } } #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: Handling active state"); #endif switch (t.ActiveState) { case Thread.ActiveStates.NotStarted: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: ActiveState: Not Started"); #endif //if (!ActiveQueue.Insert(t)) //{ // BasicConsole.WriteLine(t.Name); //} ActiveQueue.Insert(t); break; case Thread.ActiveStates.Terminated: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: ActiveState: Terminated"); #endif break; case Thread.ActiveStates.Active: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: ActiveState: Active"); #endif //if (!ActiveQueue.Insert(t)) //{ // BasicConsole.WriteLine(t.Name); //} ActiveQueue.Insert(t); break; case Thread.ActiveStates.Inactive: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: ActiveState: Inactive"); #endif //if (!InactiveQueue.Insert(t)) //{ // BasicConsole.WriteLine(t.Name); //} InactiveQueue.Insert(t); break; case Thread.ActiveStates.Suspended: #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: ActiveState: Suspended"); #endif //SuspendedList.Add(t); break; } #if SCHEDULER_UPDATE_LIST_TRACE BasicConsole.WriteLine("S > UpdateList: Done."); #endif Scheduler.Enable(); }
public bool IsValidFile() { #region CHECK : Signature if (!CheckSiganture()) { Console.Default.WarningColour(); Console.Default.WriteLine("ELF signature check failed!"); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF signature check failed!"); return(false); } else { Console.Default.Colour(0x2F); Console.Default.WriteLine("ELF signature check passed."); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF signature check passed."); } #endregion #region CHECK : File Class if (!CheckFileClass()) { Console.Default.WarningColour(); Console.Default.WriteLine("ELF file class check failed!"); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF file class check failed!"); return(false); } else { Console.Default.Colour(0x2F); Console.Default.WriteLine("ELF file class check passed."); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF file class check passed."); } #endregion #region CHECK : Data Encoding if (!CheckDataEncoding()) { Console.Default.WarningColour(); Console.Default.WriteLine("ELF data encoding check failed!"); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF data encoding check failed!"); return(false); } else { Console.Default.Colour(0x2F); Console.Default.WriteLine("ELF data encoding check passed."); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF data encoding check passed."); } #endregion #region CHECK : File Type if (!CheckFileType()) { Console.Default.WarningColour(); Console.Default.WriteLine("ELF file type check failed!"); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF file type check failed!"); return(false); } else { Console.Default.Colour(0x2F); Console.Default.WriteLine("ELF file type check passed."); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF file type check passed."); } #endregion #region CHECK : Machine if (!CheckMachine()) { Console.Default.WarningColour(); Console.Default.WriteLine("ELF machine check failed!"); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF machine check failed!"); return(false); } else { Console.Default.Colour(0x2F); Console.Default.WriteLine("ELF machine check passed."); Console.Default.DefaultColour(); BasicConsole.WriteLine("ELF machine check passed."); } #endregion #region INFO : Header Version Console.Default.Write("ELF Header version: "); Console.Default.WriteLine_AsDecimal(Header.HeaderVersion); BasicConsole.Write("ELF Header version: "); BasicConsole.WriteLine(Header.HeaderVersion); #endregion return(true); }
public static void *NewString(int length) { if (!Enabled) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning! GC returning null pointer because GC not enabled."); BasicConsole.Write("Last disabler: "); BasicConsole.WriteLine(lastDisabler); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } #if GC_TRACE if (OutputTrace) { BasicConsole.WriteLine("NewString"); } #endif EnterCritical("NewString"); try { if (length < 0) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new string because \"length\" is less than 0."); BasicConsole.DelayOutput(5); BasicConsole.SetTextColour(BasicConsole.default_colour); ExceptionMethods.Throw_OverflowException(); } InsideGC = true; //Alloc space for GC header that prefixes object data //Alloc space for new string object //Alloc space for new string chars uint totalSize = ((FOS_System.Type) typeof(FOS_System.String)).Size; totalSize += /*char size in bytes*/ 2 * (uint)length; totalSize += (uint)sizeof(GCHeader); GCHeader *newObjPtr = (GCHeader *)Heap.AllocZeroed(totalSize, "GC : NewString"); if ((UInt32)newObjPtr == 0) { InsideGC = false; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new string because the heap returned a null pointer."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } NumStrings++; //Initialise the GCHeader SetSignature(newObjPtr); //RefCount to 0 initially because of FOS_System.String.New should be used // - In theory, New should be called, creates new string and passes it back to caller // Caller is then required to store the string in a variable resulting in inc. // ref count so ref count = 1 in only stored location. // Caller is not allowed to just "discard" (i.e. use Pop IL op or C# that generates // Pop IL op) so ref count will always at some point be incremented and later // decremented by managed code. OR the variable will stay in a static var until // the OS exits... newObjPtr->RefCount = 0; FOS_System.String newStr = (FOS_System.String)Utilities.ObjectUtilities.GetObject(newObjPtr + 1); newStr._Type = (FOS_System.Type) typeof(FOS_System.String); newStr.length = length; //Move past GCHeader byte *newObjBytePtr = (byte *)(newObjPtr + 1); InsideGC = false; return(newObjBytePtr); } finally { ExitCritical(); } }
public static void SwitchProcess(uint processId, int threadId) { //Switch the current memory layout across. // Don't touch register state etc, just the memory layout bool dontSwitchOutIn = false; if (CurrentProcess != null && CurrentProcess.Id == processId) { if (CurrentThread != null && (CurrentThread.Id == threadId || threadId == THREAD_DONT_CARE)) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("No switch. (1)"); #endif return; } else { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("No switch. (2)"); #endif dontSwitchOutIn = true; } } if (!dontSwitchOutIn) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.Write("Switching out: "); BasicConsole.WriteLine(CurrentProcess.Name); #endif CurrentProcess.UnloadHeap(); CurrentProcess.UnloadMemLayout(); CurrentProcess = GetProcessById(processId); // Process not found if (CurrentProcess == null) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Process not found."); #endif return; } #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.Write("Switching in: "); BasicConsole.WriteLine(CurrentProcess.Name); #endif CurrentProcess.LoadMemLayout(); CurrentProcess.LoadHeap(); } CurrentThread = null; CurrentThread_State = null; if (threadId == THREAD_DONT_CARE) { if (CurrentProcess.Threads.Count > 0) { CurrentThread = (Thread)CurrentProcess.Threads[0]; } } else { CurrentThread = GetThreadById((uint)threadId, CurrentProcess); } // No threads in the process (?!) or process not found if (CurrentThread == null) { #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread not found."); #endif return; } #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread found."); #endif CurrentThread_State = CurrentThread.State; #if PROCESSMANAGER_SWITCH_TRACE BasicConsole.WriteLine("Thread state updated."); #endif }
public void Load(bool UserMode) { bool OK = true; try { bool DynamicLinkingRequired = false; ThreadStartMethod mainMethod = (ThreadStartMethod)Utilities.ObjectUtilities.GetObject(theFile.Header.EntryPoint); theProcess = ProcessManager.CreateProcess( mainMethod, theFile.TheFile.Name, UserMode); uint threadStackVirtAddr = (uint)((Thread)theProcess.Threads[0]).State->ThreadStackTop - 4092; uint threadStackPhysAddr = (uint)Hardware.VirtMemManager.GetPhysicalAddress(threadStackVirtAddr); ProcessManager.CurrentProcess.TheMemoryLayout.AddDataPage(threadStackPhysAddr, threadStackVirtAddr); // Load the ELF segments (i.e. the program code and data) BaseAddress = theFile.BaseAddress; LoadSegments(theFile, ref OK, ref DynamicLinkingRequired, BaseAddress); //BasicConsole.WriteLine(); #region Relocations // Useful articles / specifications on Relocations: // - Useful / practical explanation of various relocation types: http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries/#id20 // - Orcale : ELF Specification copy: http://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-54839.html if (DynamicLinkingRequired) { Console.Default.WriteLine("Dynamic Linking"); BasicConsole.WriteLine("Dynamic Linking"); ELFDynamicSection dynamicSection = theFile.DynamicSection; ELFDynamicSymbolTableSection dynamicSymbolsSection = theFile.DynamicSymbolsSection; ELFStringTable DynamicsStringTable = new ELFStringTable( dynamicSection.StrTabDynamic.Val_Ptr, dynamicSection.StrTabSizeDynamic.Val_Ptr); for (uint i = 0; i < dynamicSection.Dynamics.Count; i++) { ELFDynamicSection.Dynamic theDyn = dynamicSection[i]; //BasicConsole.WriteLine(" - Dynamic : "); //BasicConsole.Write(" - Tag : "); //BasicConsole.WriteLine((int)theDyn.Tag); //BasicConsole.Write(" - Value or Pointer : "); //BasicConsole.WriteLine(theDyn.Val_Ptr); if (theDyn.Tag == ELFDynamicSection.DynamicTag.Needed) { BasicConsole.Write(" - Needed library name : "); FOS_System.String libFullPath = DynamicsStringTable[theDyn.Val_Ptr]; Console.Default.WriteLine(libFullPath); BasicConsole.WriteLine(libFullPath); FOS_System.String libFileName = (FOS_System.String)libFullPath.Split('\\').Last(); libFileName = (FOS_System.String)libFileName.Split('/').Last(); FOS_System.String libTestPath = theFile.TheFile.Parent.GetFullPath() + libFileName; File sharedObjectFile = File.Open(libTestPath); if (sharedObjectFile == null) { Console.Default.WarningColour(); Console.Default.WriteLine("Failed to find needed library file!"); BasicConsole.WriteLine("Failed to find needed library file!"); Console.Default.DefaultColour(); OK = false; } else { Console.Default.WriteLine("Found library file. Loading library..."); BasicConsole.WriteLine("Found library file. Loading library..."); ELFSharedObject sharedObject = DynamicLinkerLoader.LoadLibrary_FromELFSO(sharedObjectFile, this); SharedObjectDependencies.Add(sharedObject); Console.Default.WriteLine("Library loaded."); BasicConsole.WriteLine("Library loaded."); } } } Console.Default.WriteLine("Library Relocations"); BasicConsole.WriteLine("Library Relocations"); // Perform relocation / dynamic linking of all libraries for (int i = 0; i < SharedObjectDependencies.Count; i++) { ELFSharedObject SO = (ELFSharedObject)SharedObjectDependencies[i]; //BasicConsole.WriteLine("Shared Object base address : " + (FOS_System.String)SO.BaseAddress); //BasicConsole.WriteLine("Shared Object file base address : " + (FOS_System.String)SO.TheFile.BaseAddress); List SOSections = SO.TheFile.Sections; for (int j = 0; j < SOSections.Count; j++) { ELFSection SOSection = (ELFSection)SOSections[j]; if (SOSection is ELFRelocationTableSection) { //BasicConsole.WriteLine(" - Normal Relocation"); ELFRelocationTableSection relocTableSection = (ELFRelocationTableSection)SOSection; ELFSymbolTableSection symbolTable = (ELFSymbolTableSection)SO.TheFile.Sections[relocTableSection.SymbolTableSectionIndex]; ELFStringTableSection symbolNamesTable = (ELFStringTableSection)SO.TheFile.Sections[symbolTable.StringsSectionIndex]; List Relocations = relocTableSection.Relocations; for (int k = 0; k < Relocations.Count; k++) { // Reference: http://docs.oracle.com/cd/E19683-01/817-3677/chapter6-26/index.html ELFRelocationTableSection.Relocation relocation = (ELFRelocationTableSection.Relocation)Relocations[k]; if (relocation.Type == ELFRelocationTableSection.RelocationType.R_386_NONE) { continue; } uint *resolvedRelLocation = (uint *)(SO.BaseAddress + (relocation.Offset - SO.TheFile.BaseAddress)); ELFSymbolTableSection.Symbol symbol = (ELFSymbolTableSection.Symbol)symbolTable[relocation.Symbol]; FOS_System.String symbolName = symbolNamesTable[symbol.NameIdx]; //BasicConsole.WriteLine("Relocation:"); ////BasicConsole.WriteLine(" > Symbol index : " + (FOS_System.String)relocation.Symbol); //BasicConsole.WriteLine(" > Type : " + (FOS_System.String)(uint)relocation.Type); //BasicConsole.WriteLine(" > Offset : " + (FOS_System.String)(uint)relocation.Offset); //BasicConsole.WriteLine(((FOS_System.String)" > Resolved location address: ") + (uint)resolvedRelLocation); ////BasicConsole.WriteLine(((FOS_System.String)" > Resolved location start value: ") + *resolvedRelLocation); //BasicConsole.Write(" > Symbol name : "); //BasicConsole.WriteLine(symbolName); uint newValue = 0; switch (relocation.Type) { case ELFRelocationTableSection.RelocationType.R_386_32: newValue = GetSymbolAddress(symbol, symbolName) + *resolvedRelLocation; break; case ELFRelocationTableSection.RelocationType.R_386_PC32: newValue = GetSymbolAddress(symbol, symbolName) + *resolvedRelLocation - (uint)resolvedRelLocation; break; case ELFRelocationTableSection.RelocationType.R_386_RELATIVE: newValue = SO.BaseAddress + *resolvedRelLocation; break; //TODO: Support more relocation types default: Console.Default.WarningColour(); Console.Default.Write("WARNING: Unrecognised relocation type! ("); Console.Default.Write_AsDecimal((uint)relocation.Type); Console.Default.WriteLine(")"); Console.Default.DefaultColour(); BasicConsole.Write("WARNING: Unrecognised relocation type! ("); BasicConsole.Write((uint)relocation.Type); BasicConsole.WriteLine(")"); break; } *resolvedRelLocation = newValue; //BasicConsole.WriteLine(" > New value: " + (FOS_System.String)(newValue)); //BasicConsole.WriteLine(" > Resolved location end value: " + (FOS_System.String)(*resolvedRelLocation)); } } else if (SOSection is ELFRelocationAddendTableSection) { //BasicConsole.WriteLine(" - Addend Relocation"); ELFRelocationAddendTableSection relocTableSection = (ELFRelocationAddendTableSection)SOSection; ELFSymbolTableSection symbolTable = (ELFSymbolTableSection)SO.TheFile.Sections[relocTableSection.SymbolTableSectionIndex]; ELFStringTableSection symbolNamesTable = (ELFStringTableSection)SO.TheFile.Sections[symbolTable.StringsSectionIndex]; List Relocations = relocTableSection.Relocations; for (int k = 0; k < Relocations.Count; k++) { ELFRelocationAddendTableSection.RelocationAddend relocation = (ELFRelocationAddendTableSection.RelocationAddend)Relocations[k]; if (relocation.Type == ELFRelocationTableSection.RelocationType.R_386_NONE) { continue; } ELFSymbolTableSection.Symbol symbol = (ELFSymbolTableSection.Symbol)symbolTable[relocation.Symbol]; FOS_System.String symbolName = symbolNamesTable[symbol.NameIdx]; uint *resolvedRelLocation = (uint *)(SO.BaseAddress + (relocation.Offset - SO.TheFile.BaseAddress)); //BasicConsole.WriteLine("Relocation:"); ////BasicConsole.WriteLine(" > Symbol index : " + (FOS_System.String)relocation.Symbol); //BasicConsole.WriteLine(" > Type : " + (FOS_System.String)(uint)relocation.Type); //BasicConsole.WriteLine(" > Offset : " + (FOS_System.String)(uint)relocation.Offset); //BasicConsole.WriteLine(((FOS_System.String)" > Resolved location address: ") + (uint)resolvedRelLocation); ////BasicConsole.WriteLine(((FOS_System.String)" > Resolved location start value: ") + *resolvedRelLocation); //BasicConsole.Write(" > Symbol name : "); //BasicConsole.WriteLine(symbolName); uint newValue = 0; switch (relocation.Type) { //TODO: Support more relocation types default: Console.Default.WarningColour(); Console.Default.Write("WARNING: Unrecognised relocation type! ("); Console.Default.Write_AsDecimal((uint)relocation.Type); Console.Default.WriteLine(")"); Console.Default.DefaultColour(); BasicConsole.Write("WARNING: Unrecognised relocation type! ("); BasicConsole.Write((uint)relocation.Type); BasicConsole.WriteLine(")"); break; } *resolvedRelLocation = newValue; //BasicConsole.WriteLine(" > New value: " + (FOS_System.String)(newValue)); //BasicConsole.WriteLine(" > Resolved location end value: " + (FOS_System.String)(*resolvedRelLocation)); } } } } Console.Default.WriteLine("Executable Relocations"); BasicConsole.WriteLine("Executable Relocations"); //BasicConsole.WriteLine("Executable base address : " + (FOS_System.String)BaseAddress); //BasicConsole.WriteLine("Executable file base address : " + (FOS_System.String)theFile.BaseAddress); // Perform dynamic linking of executable List ExeSections = theFile.Sections; for (int j = 0; j < ExeSections.Count; j++) { ELFSection ExeSection = (ELFSection)ExeSections[j]; if (ExeSection is ELFRelocationTableSection) { //BasicConsole.WriteLine(" - Normal Relocations"); ELFRelocationTableSection relocTableSection = (ELFRelocationTableSection)ExeSection; ELFSymbolTableSection symbolTable = (ELFSymbolTableSection)theFile.Sections[relocTableSection.SymbolTableSectionIndex]; ELFStringTableSection symbolNamesTable = (ELFStringTableSection)theFile.Sections[symbolTable.StringsSectionIndex]; List Relocations = relocTableSection.Relocations; for (int k = 0; k < Relocations.Count; k++) { ELFRelocationTableSection.Relocation relocation = (ELFRelocationTableSection.Relocation)Relocations[k]; if (relocation.Type == ELFRelocationTableSection.RelocationType.R_386_NONE) { continue; } uint *resolvedRelLocation = (uint *)(BaseAddress + (relocation.Offset - theFile.BaseAddress)); ELFSymbolTableSection.Symbol symbol = (ELFSymbolTableSection.Symbol)symbolTable[relocation.Symbol]; FOS_System.String symbolName = symbolNamesTable[symbol.NameIdx]; //BasicConsole.WriteLine("Relocation:"); ////BasicConsole.WriteLine(" > Symbol index : " + (FOS_System.String)relocation.Symbol); //BasicConsole.WriteLine(" > Type : " + (FOS_System.String)(uint)relocation.Type); //BasicConsole.WriteLine(" > Offset : " + (FOS_System.String)(uint)relocation.Offset); //BasicConsole.WriteLine(((FOS_System.String)" > Resolved location address: ") + (uint)resolvedRelLocation); ////BasicConsole.WriteLine(((FOS_System.String)" > Resolved location start value: ") + *resolvedRelLocation); //BasicConsole.Write(" > Symbol name : "); //BasicConsole.WriteLine(symbolName); bool setFromNewValue = true; uint newValue = 0; switch (relocation.Type) { //TODO: Support more relocation types case ELFRelocationTableSection.RelocationType.R_386_JMP_SLOT: newValue = GetSymbolAddress(symbol, symbolName); break; case ELFRelocationTableSection.RelocationType.R_386_COPY: // Created by the link-editor for dynamic executables to preserve a read-only text segment. // Its offset member refers to a location in a writable segment. The symbol table index // specifies a symbol that should exist both in the current object file and in a shared object. // During execution, the runtime linker copies data associated with the shared object's symbol // to the location specified by the offset. // See Copy Relocations: // http://docs.oracle.com/cd/E19683-01/817-3677/6mj8mbtbs/index.html#chapter4-84604 setFromNewValue = false; uint symbolAddress = 0; uint symbolSize = 0; if (GetSymbolAddressAndSize(symbol, symbolName, ref symbolAddress, ref symbolSize)) { byte *symbolValuePtr = (byte *)symbolAddress; //BasicConsole.Write(" > Symbol size : "); //BasicConsole.WriteLine(symbolSize); for (int i = 0; i < symbolSize; i++) { resolvedRelLocation[i] = symbolValuePtr[i]; } } else { BasicConsole.WriteLine("Failed to get symbol address and size for R_386_COPY relocation!"); } break; default: Console.Default.WarningColour(); Console.Default.Write("WARNING: Unrecognised relocation type! ("); Console.Default.Write_AsDecimal((uint)relocation.Type); Console.Default.WriteLine(")"); Console.Default.DefaultColour(); BasicConsole.Write("WARNING: Unrecognised relocation type! ("); BasicConsole.Write((uint)relocation.Type); BasicConsole.WriteLine(")"); break; } if (setFromNewValue) { *resolvedRelLocation = newValue; //BasicConsole.WriteLine(" > New value: " + (FOS_System.String)(newValue)); //BasicConsole.WriteLine(" > Resolved location end value: " + (FOS_System.String)(*resolvedRelLocation)); } } } else if (ExeSection is ELFRelocationAddendTableSection) { //BasicConsole.WriteLine(" - Addend Relocations"); ELFRelocationAddendTableSection relocTableSection = (ELFRelocationAddendTableSection)ExeSection; ELFSymbolTableSection symbolTable = (ELFSymbolTableSection)theFile.Sections[relocTableSection.SymbolTableSectionIndex]; ELFStringTableSection symbolNamesTable = (ELFStringTableSection)theFile.Sections[symbolTable.StringsSectionIndex]; List Relocations = relocTableSection.Relocations; for (int k = 0; k < Relocations.Count; k++) { ELFRelocationAddendTableSection.RelocationAddend relocation = (ELFRelocationAddendTableSection.RelocationAddend)Relocations[k]; if (relocation.Type == ELFRelocationTableSection.RelocationType.R_386_NONE) { continue; } uint *resolvedRelLocation = (uint *)(BaseAddress + (relocation.Offset - theFile.BaseAddress)); ELFSymbolTableSection.Symbol symbol = (ELFSymbolTableSection.Symbol)symbolTable[relocation.Symbol]; FOS_System.String symbolName = symbolNamesTable[symbol.NameIdx]; //BasicConsole.WriteLine("Relocation:"); ////BasicConsole.WriteLine(" > Symbol index : " + (FOS_System.String)relocation.Symbol); //BasicConsole.WriteLine(" > Type : " + (FOS_System.String)(uint)relocation.Type); //BasicConsole.WriteLine(" > Offset : " + (FOS_System.String)(uint)relocation.Offset); //BasicConsole.WriteLine(((FOS_System.String)" > Resolved location address: ") + (uint)resolvedRelLocation); ////BasicConsole.WriteLine(((FOS_System.String)" > Resolved location start value: ") + *resolvedRelLocation); //BasicConsole.Write(" > Symbol name : "); //BasicConsole.WriteLine(symbolName); uint newValue = 0; switch (relocation.Type) { //TODO: Support more relocation types default: Console.Default.WarningColour(); Console.Default.Write("WARNING: Unrecognised relocation type! ("); Console.Default.Write_AsDecimal((uint)relocation.Type); Console.Default.WriteLine(")"); Console.Default.DefaultColour(); BasicConsole.Write("WARNING: Unrecognised relocation type! ("); BasicConsole.Write((uint)relocation.Type); BasicConsole.WriteLine(")"); break; } *resolvedRelLocation = newValue; //BasicConsole.WriteLine(" > New value: " + (FOS_System.String)(newValue)); //BasicConsole.WriteLine(" > Resolved location end value: " + (FOS_System.String)(*resolvedRelLocation)); } } } // TODO: Call Init functions of libraries } // Unmap processes' memory from current processes' memory for (int i = 0; i < SharedObjectDependencies.Count; i++) { ELFSharedObject SO = (ELFSharedObject)SharedObjectDependencies[i]; uint FileBaseAddress = SO.TheFile.BaseAddress; uint MemBaseAddress = SO.BaseAddress; List SOSegments = SO.TheFile.Segments; for (int j = 0; j < SOSegments.Count; j++) { ELFSegment SOSegment = (ELFSegment)SOSegments[j]; ProcessManager.CurrentProcess.TheMemoryLayout.RemovePage( (MemBaseAddress + ((uint)SOSegment.Header.VAddr - FileBaseAddress)) & 0xFFFFF000); } } { uint FileBaseAddress = theFile.BaseAddress; uint MemBaseAddress = BaseAddress; List ExeSegments = theFile.Segments; for (int j = 0; j < ExeSegments.Count; j++) { ELFSegment ExeSegment = (ELFSegment)ExeSegments[j]; ProcessManager.CurrentProcess.TheMemoryLayout.RemovePage( (MemBaseAddress + ((uint)ExeSegment.Header.VAddr - FileBaseAddress)) & 0xFFFFF000); } } #endregion ProcessManager.CurrentProcess.TheMemoryLayout.RemovePage(threadStackVirtAddr); } finally { if (!OK) { theProcess = null; } } }