Example #1
0
        /// <summary>
        /// Starts a new process based on the given path and arguments
        /// </summary>
        /// <param name="path">The path</param>
        /// <param name="argv">The arguments</param>
        /// <param name="flags">Spawn flags</param>
        /// <returns>Errorcode or PID</returns>
        public static int StartProcess(string path, string[] argv, Task.SpawnFlags flags)
        {
            if (argv == null)
            {
                Panic.DoPanic("argv == null");
            }

            Node node = VFS.GetByAbsolutePath(path);

            if (node == null)
            {
                return(-(int)ErrorCode.ENOENT);
            }

            // Open and create buffer
            VFS.Open(node, (int)FileMode.O_RDONLY);
            byte[] buffer = new byte[node.Size];
            if (buffer == null)
            {
                Heap.Free(node);
                VFS.Close(node);
                return(-(int)ErrorCode.ENOMEM);
            }

            // Fill buffer contents
            VFS.Read(node, 0, node.Size, buffer);
            VFS.Close(node);

            // Pass execution to ELF loader
            int status = ELFLoader.Execute(buffer, node.Size, argv, flags);

            Heap.Free(buffer);
            Heap.Free(node);
            return(status);
        }
Example #2
0
        /// <summary>
        /// Executes an ELF file
        /// </summary>
        /// <param name="buffer">The buffer</param>
        /// <param name="size">The size of the ELF</param>
        /// <param name="argv">The arguments</param>
        /// <param name="flags">Spawn flags</param>
        /// <returns>The error code or PID</returns>
        public static unsafe int Execute(byte[] buffer, uint size, string[] argv, Task.SpawnFlags flags)
        {
            ELF32 *elf;

            fixed(byte *ptr = buffer)
            elf = (ELF32 *)ptr;

            if (!isValidELF(elf))
            {
                return(-(int)ErrorCode.EINVAL);
            }

            // Get program header
            ProgramHeader *programHeader = (ProgramHeader *)((int)elf + elf->PhOff);
            uint           virtAddress   = programHeader->VirtAddress;
            void *         allocated     = Heap.AlignedAlloc(0x1000, (int)size);

            // Loop through every section
            for (uint i = 0; i < elf->ShNum; i++)
            {
                SectionHeader *section = getSection(elf, i);

                // Only loadable sections
                if (section->Address == 0)
                {
                    continue;
                }

                uint offset = section->Address - virtAddress;

                // BSS
                if (section->Type == SectionHeaderType.SHT_NOBITS)
                {
                    Memory.Memclear((void *)((uint)allocated + offset), (int)section->Size);
                }
                // Copy
                else
                {
                    Memory.Memcpy((void *)((uint)allocated + offset), (void *)((uint)elf + section->Offset), (int)section->Size);
                }
            }

            // Count arguments
            int argc = 0;

            while (argv[argc] != null)
            {
                argc++;
            }

            // Make sure arguments are safe by copying them
            string[] argvClone = new string[argc + 1];
            for (int i = 0; i < argc; i++)
            {
                argvClone[i] = String.Clone(argv[i]);
            }

            // Stack
            int[] initialStack = new int[2];
            initialStack[0] = (int)Util.ObjectToVoidPtr(argvClone);
            initialStack[1] = argc;

            // Create thread
            Thread thread = new Thread();

            thread.Context.CreateNewContext((void *)elf->Entry, 2, initialStack, false);
            Heap.Free(initialStack);

            CPU.CLI();

            // Create task
            Task       newTask = new Task(TaskPriority.NORMAL, flags);
            X86Context context = (X86Context)newTask.Context;

            context.CreateNewContext(false);
            newTask.AddThread(thread);
            newTask.AddUsedAddress(allocated);

            // Task info
            newTask.Name    = argvClone[0];
            newTask.CMDLine = Array.Join(argvClone, argc, " ");
            newTask.AddUsedAddress(newTask.CMDLine);

            // Argv clone freeing
            newTask.AddUsedAddress(argvClone);
            for (int i = 0; i < argc; i++)
            {
                newTask.AddUsedAddress(argvClone[i]);
            }

            // Map memory
            Paging.PageDirectory *newDirectory = context.PageDirVirtual;
            Paging.PageFlags      pageFlags    = Paging.PageFlags.Present | Paging.PageFlags.Writable | Paging.PageFlags.UserMode;
            for (uint j = 0; j < size; j += 0x1000)
            {
                // Note: the physical memory is not always a continuous block
                Paging.MapPage(newDirectory, (int)Paging.GetPhysicalFromVirtual((void *)((int)allocated + j)), (int)(virtAddress + j), pageFlags);
            }

            // Schedule task
            Tasking.ScheduleTask(newTask);

            CPU.STI();

            return(newTask.PID);
        }