#include #include #include #include #include #include #include #include "../Common/bootinfo.h" void ModuleLoad(BootModule* module) { OSProcess* userProc = HeapAllocate(sizeof(OSProcess)); MemorySet(userProc, 0, sizeof(OSProcess)); userProc->id = SchedulerGetNextProcessID(); userProc->state = OSTaskStateRunning; StringCopy(userProc->name, module->name); Address userL0Phys = (Address)PMMAllocatePage(); Address* userL0Virt = (Address*)VMPhysToHHDM(userL0Phys); MemorySet(userL0Virt, 0, kVMPageSize); userProc->l0Table = userL0Virt; for (BIUInt32 s = 0; s < module->segmentCount; s++) { BootModuleSegment* seg = &module->segments[s]; UInt64 segFlags = kPTENormalMem | kPTEUser; if (seg->flags & PF_W) { // writable: AP[2]=0 (RW), which is the default } else { segFlags |= kPTEAccessRO; } if (seg->flags & PF_X) { // executable: default is already executable } else { segFlags |= kPTEPrivNX | kPTEUserNX; } for (Size i = 0; i < seg->size; i += kVMPageSize) { VMMMapPage((Address*)userL0Phys, seg->physicalBase + i, seg->virtualBase + i, segFlags); } CPUCleanAndInvalidateCode((void*)VMPhysToHHDM(seg->physicalBase), seg->size); } Address stackPhys = (Address)PMMAllocatePage(); Address userStackVirt = 0x80000000; UInt64 stackFlags = kPTENormalMem | kPTEUser | kPTEAccessRW | kPTEPrivNX | kPTEUserNX; VMMMapPage((Address*)userL0Phys, stackPhys, userStackVirt, stackFlags); void (*userEntryPoint)() = (void(*)())module->entry; if ((Address)userEntryPoint == 0x0) { OSLog("Skipping module %s: entry point is 0x0.\n", module->name); return; } SchedulerSpawn(userEntryPoint, userProc, true, userStackVirt + kVMPageSize); }