My Project
Loading...
Searching...
No Matches
process.c
Go to the documentation of this file.
1/*
2 * PROJECT: MatanelOS Kernel
3 * LICENSE: GPLv3
4 * PURPOSE: Process Creation Implementation
5 */
6
7#include "../../time.h"
9#include "../../includes/me.h"
10#include "../../includes/ps.h"
11#include "../../includes/mg.h"
12#include "../../includes/ms.h"
13#include "../../includes/ob.h"
14#include "../../assert.h"
15
16#define MIN_PID 4u
17#define MAX_PID 0xFFFFFFFCUL
18#define ALIGN_DELTA 6u
19#define MAX_FREE_POOL 1024u
20
21#define PML4_INDEX(addr) (((addr) >> 39) & 0x1FFULL)
22#define KERNEL_PML4_START ((size_t)PML4_INDEX(KernelVaStart))
23#define USER_INITIAL_STACK_TOP 0x00007FFFFFFFFFFF
25
26uintptr_t MmSystemRangeStart = PhysicalMemoryOffset; // Changed to PhysicalMemoryOffset, since thats where actual stuff like hypermap, phys to virt, and more happen.
28uintptr_t MmUserProbeAddress = 0x00007FFFFFFF0000;
29
30static
31bool
32GetBaseName(const char* fullpath, char* out, size_t outsz) {
33 const char* ext = ".mtexe";
34 size_t ext_len = kstrlen(ext);
35 if (!fullpath || !out || outsz == 0) return false;
36
37 size_t len = kstrlen(fullpath);
38 const char* p = fullpath + len;
39 while (p > fullpath && *(p - 1) != '/') --p;
40
41 size_t name_len = kstrlen(p);
42 if (name_len < ext_len || kstrcmp(p + name_len - ext_len, ext) != 0) return false;
43
44 if (name_len + 1 > outsz) return false; // too small
45 kstrncpy(out, p, name_len + 1);
46 return true;
47}
48
51 IN const char* ExecutablePath,
52 OUT PHANDLE ProcessHandle,
53 IN ACCESS_MASK DesiredAccess,
54 _In_Opt HANDLE ParentProcess
55)
56
57/*++
58
59 Routine description:
60
61 Creates a process, simple as that.
62
63 Arguments:
64
65 [IN] const char* ExecutablePath - The process's main executable file.
66 [OUT] PHANDLE ProcessHandle - Pointer to store the the process's created handle.
67 [IN] ACCESS_MASK DesiredAccess - The maximum access the process should originally have.
68 [IN OPTIONAL] HANDLE ParentProcess - Optionally supply a handle to the parent of this process.
69
70 Return Values:
71
72 Various MTSTATUS Status codes.
73
74--*/
75
76{
77 MTSTATUS Status;
78 PEPROCESS Process, Parent;
79 // If we have a parent process, attempt to see if the parent process has the access to create another process.
80 if (ParentProcess) {
82 ParentProcess,
85 (void**)&Parent,
86 NULL
87 );
88
89 if (MT_FAILURE(Status)) {
90 return Status;
91 }
92 }
93 else {
94 // We have no parent process.
95 Parent = NULL;
96 }
97
98 // Create the EPROCESS Object.
99 Status = ObCreateObject(PsProcessType, sizeof(EPROCESS), (void*)&Process);
100 if (MT_FAILURE(Status)) goto Cleanup;
101
102 // CleanupWithRef from now on.
103 // Assume failure status.
104 Status = MT_GENERAL_FAILURE;
105 // Setup the process now, create its PID.
106 Process->PID = PsAllocateProcessId(Process);
107
108 // Set its parent process handle.
109 Process->ParentProcess = ParentProcess;
110
111 // Set its image name.
112 char filename[24];
113 GetBaseName(ExecutablePath, filename, sizeof(filename));
114 if (filename[0] == '\0') goto CleanupWithRef;
115 kstrncpy(Process->ImageName, filename, sizeof(Process->ImageName));
116
117 // Set initial state
119
120 // Create object table.
121 PHANDLE_TABLE HandleTable = HtCreateHandleTable(Process);
122 if (!HandleTable) goto CleanupWithRef;
123 Process->ObjectTable = HandleTable;
124
125 // Create address space.
126 void* DirectoryTablePhysical = NULL;
127 Status = MmCreateProcessAddressSpace(&DirectoryTablePhysical);
128 if (MT_FAILURE(Status)) goto CleanupWithRef;
129 Process->InternalProcess.PageDirectoryPhysical = (uintptr_t)DirectoryTablePhysical;
130 gop_printf(COLOR_RED, "Process CR3: %p\n", DirectoryTablePhysical);
131
132 // Per thread stack calculation.
134
135 // Creation time.
136 Process->CreationTime = MeGetEpoch();
137
138 // Initialize List heads.
140
141 // Load file into memory (TODO Section objects)
142 void* file_buffer = NULL;
143 uint32_t FileSize = 0;
144 Status = vfs_read(ExecutablePath, &FileSize, &file_buffer);
145 if (MT_FAILURE(Status)) goto CleanupWithRef;
146 Process->FileBuffer = file_buffer;
147 Process->ImageBase = USER_VA_START; // Dummy VA, FIXME Headers.
148
149 // TODO ADD ADDRESS TO WORKING SET OF PROCESS!!
150
151 // Calculate the number of pages needed to map the entire file in.
152 size_t num_pages = (FileSize + VirtualPageSize - 1) / VirtualPageSize;
153
154 // Prepare for the copy loop
155 uintptr_t CurrentVA = Process->ImageBase;
156 uint8_t* SourcePtr = (uint8_t*)file_buffer; // Pointer to the data we read from disk
157 size_t BytesRemaining = FileSize;
158
159 // Attach to process to get corrent PTE pointer.
160 APC_STATE ApcState;
161 MeAttachProcess(&Process->InternalProcess, &ApcState);
162
163 for (size_t i = 0; i < num_pages; i++) {
164 // Allocate a physical page.
166 if (pfn == PFN_ERROR) break;
167
168 // Now we change the actual physical address we got, and thats the physical address of CurrentVA.
169 IRQL oldIrql;
170 void* PhysicalAddressOfVa = MiMapPageInHyperspace(pfn, &oldIrql);
171
172 // Calculate how many bytes to copy for this specific iteration.
173 // It will be 4096 for every page except potentially the last one.
174 size_t BytesToCopy = (BytesRemaining > VirtualPageSize) ? VirtualPageSize : BytesRemaining;
175
176 // Copy the data.
177 kmemcpy((void*)PhysicalAddressOfVa, SourcePtr, BytesToCopy);
178
179 // End hyperspace mapping for physical address.
180 MiUnmapHyperSpaceMap(oldIrql);
181
182 // Get the PTE pointer for the current address.
183 PMMPTE pte = MiGetPtePointer(CurrentVA);
184
185 // Write to it the physical address.
186 MI_WRITE_PTE(pte, CurrentVA, PFN_TO_PHYS(pfn), PAGE_PRESENT | PAGE_RW | PAGE_USER);
187
188 // Advance pointers and decrement counters
189 CurrentVA += VirtualPageSize;
190 SourcePtr += BytesToCopy;
191 BytesRemaining -= BytesToCopy;
192 }
193
194 // The VA has been filed with the executable's instructions, now we do handle creation and yada yada.
195 // Detach from process address space.
196 MeDetachProcess(&ApcState);
197
198 // Create a handle for the process.
199 HANDLE hProcess;
200 Status = ObCreateHandleForObject(Process, DesiredAccess, &hProcess);
201 if (MT_FAILURE(Status)) goto CleanupWithRef;
202
203 // Create a main thread for the process.
204 HANDLE MainThreadHandle;
205 Status = PsCreateThread(hProcess, &MainThreadHandle, (ThreadEntry)Process->ImageBase, NULL, DEFAULT_TIMESLICE_TICKS);
206 if (MT_FAILURE(Status)) goto CleanupWithRef;
207
208 // Insert main thread to processor queue.
210
211 // We are, successful.
212 *ProcessHandle = hProcess;
213 Status = MT_SUCCESS;
214
215CleanupWithRef:
216#ifdef DEBUG
217 if (MT_FAILURE(Status)) {
218 assert(false, "Something went wrong.");
219 }
220#endif
221 // If all went smoothly, this should cancel out the reference made by ObCreateHandleForObject. (so we only have 1 reference left by ObCreateObject)
222 // If not, it would reach reference 0, and PspDeleteProcessd would execute.
223 ObDereferenceObject(Process);
224 // [[fallthrough]]
225Cleanup:
226 if (Parent) ObDereferenceObject(Parent);
227 return Status;
228}
229
230void
232 IN PEPROCESS Process
233)
234
235{
236 UNREFERENCED_PARAMETER(Process);
237 assert(false, "Unimplemented routine");
239}
#define _In_Opt
Definition annotations.h:9
#define IN
Definition annotations.h:7
#define OUT
Definition annotations.h:8
#define assert(...)
Definition assert.h:57
void MeDetachProcess(IN PAPC_STATE ApcState)
Definition attach.c:86
void MeAttachProcess(IN PIPROCESS Process, OUT PAPC_STATE ApcState)
Definition attach.c:23
NORETURN void MeBugCheck(IN enum _BUGCHECK_CODES BugCheckCode)
Definition bugcheck.c:214
HANDLE PsAllocateProcessId(IN PEPROCESS Process)
Definition cid.c:59
struct _EPROCESS EPROCESS
Definition core.h:49
enum _IRQL IRQL
EPROCESS * PEPROCESS
Definition core.h:50
size_t kstrlen(const char *str)
Definition gop.c:393
void gop_printf(uint32_t color, const char *fmt,...)
Definition gop.c:694
char * kstrncpy(char *dst, const char *src, size_t n)
Definition gop.c:416
int kstrcmp(const char *s1, const char *s2)
Definition gop.c:657
PHANDLE_TABLE HtCreateHandleTable(IN PEPROCESS Process)
Definition handle.c:87
uint32_t ACCESS_MASK
Definition ht.h:63
int32_t * PHANDLE
Definition ht.h:59
struct _HANDLE_TABLE * PHANDLE_TABLE
int32_t HANDLE
Definition ht.h:59
void * MiMapPageInHyperspace(IN uint64_t PfnIndex, OUT PIRQL OldIrql)
Definition hypermap.c:33
void MiUnmapHyperSpaceMap(IN IRQL OldIrql)
Definition hypermap.c:83
#define UNREFERENCED_PARAMETER(x)
Definition intrin.h:24
PMMPTE MiGetPtePointer(IN uintptr_t va)
Definition map.c:76
struct _APC_STATE APC_STATE
@ MANUALLY_INITIATED_CRASH2
Definition me.h:129
FORCEINLINE PPROCESSOR MeGetCurrentProcessor(void)
Definition me.h:356
@ DEFAULT_TIMESLICE_TICKS
Definition me.h:48
#define COLOR_RED
Colors definitions for easier access.
Definition mg.h:29
@ PAGE_RW
Definition mm.h:272
@ PAGE_USER
Definition mm.h:276
@ PAGE_PRESENT
Definition mm.h:268
#define PFN_TO_PHYS(Pfn)
Definition mm.h:205
@ PfnStateZeroed
Definition mm.h:243
struct _MMPTE * PMMPTE
FORCEINLINE void * kmemcpy(void *dest, const void *src, size_t len)
Definition mm.h:554
uint64_t PAGE_INDEX
Definition mm.h:232
#define USER_VA_END
Definition mm.h:160
#define PhysicalMemoryOffset
Definition mm.h:56
#define USER_VA_START
Definition mm.h:161
#define PFN_ERROR
Definition mm.h:208
#define VirtualPageSize
Definition mm.h:53
#define MI_WRITE_PTE(_PtePointer, _Va, _Pa, _Flags)
Definition mm.h:90
MTSTATUS MmCreateProcessAddressSpace(OUT void **DirectoryTable)
Definition mmproc.c:220
FORCEINLINE void InitializeListHead(PDOUBLY_LINKED_LIST Head)
Definition ms.h:166
#define MT_SUCCESS
Definition mtstatus.h:22
#define MT_GENERAL_FAILURE
Definition mtstatus.h:31
#define MT_FAILURE(Status)
Definition mtstatus.h:16
int32_t MTSTATUS
Definition mtstatus.h:12
MTSTATUS ObCreateHandleForObject(IN void *Object, IN ACCESS_MASK DesiredAccess, OUT PHANDLE ReturnedHandle)
Definition ob.c:318
MTSTATUS ObReferenceObjectByHandle(IN HANDLE Handle, IN uint32_t DesiredAccess, IN POBJECT_TYPE DesiredType, OUT void **Object, _Out_Opt PHANDLE_TABLE_ENTRY HandleInformation)
Definition ob.c:247
void ObDereferenceObject(IN void *Object)
Definition ob.c:446
MTSTATUS ObCreateObject(IN POBJECT_TYPE ObjectType, IN uint32_t ObjectSize, OUT void **ObjectCreated)
Definition ob.c:116
PAGE_INDEX MiRequestPhysicalPage(IN PFN_STATE ListType)
Definition pfn.c:325
uintptr_t MmSystemRangeStart
Definition process.c:26
uintptr_t MmUserProbeAddress
Definition process.c:28
EPROCESS SystemProcess
void PsTerminateProcess(IN PEPROCESS Process)
Definition process.c:231
#define USER_INITIAL_STACK_TOP
Definition process.c:23
MTSTATUS PsCreateProcess(IN const char *ExecutablePath, OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, _In_Opt HANDLE ParentProcess)
Definition process.c:50
uintptr_t MmHighestUserAddress
Definition process.c:27
FORCEINLINE void MeEnqueueThreadWithLock(Queue *queue, PETHREAD thread)
Definition ps.h:306
void(* ThreadEntry)(THREAD_PARAMETER)
Definition ps.h:147
@ PROCESS_READY
Definition ps.h:48
#define MT_PROCESS_CREATE_PROCESS
Definition ps.h:87
POBJECT_TYPE PsProcessType
Definition psmgr.c:30
HANDLE PID
Definition ps.h:94
HANDLE ParentProcess
Definition ps.h:95
PHANDLE_TABLE ObjectTable
Definition ps.h:114
void * FileBuffer
Definition ps.h:101
char ImageName[24]
Definition ps.h:93
struct _ETHREAD * MainThread
Definition ps.h:108
uint64_t NextStackTop
Definition ps.h:111
uint64_t CreationTime
Definition ps.h:97
struct _IPROCESS InternalProcess
Definition ps.h:92
uint64_t ImageBase
Definition ps.h:102
DOUBLY_LINKED_LIST AllThreads
Definition ps.h:109
uint32_t ProcessState
Definition me.h:258
uintptr_t PageDirectoryPhysical
Definition me.h:255
MTSTATUS PsCreateThread(HANDLE ProcessHandle, PHANDLE ThreadHandle, ThreadEntry EntryPoint, THREAD_PARAMETER ThreadParameter, TimeSliceTicks TimeSlice)
Definition thread.c:34
MTSTATUS vfs_read(const char *filename, uint32_t *file_size_out, void **buffer_out)
Reads the file into a buffer.
Definition vfs.c:87