/* * Create a new user context of given size */ static struct User_Context *Create_User_Context(ulong_t size) { struct User_Context *context; int index; /* Size must be a multiple of the page size */ size = Round_Up_To_Page(size); if (userDebug) Print("Size of user memory == %lu (%lx) (%lu pages)\n", size, size, size / PAGE_SIZE); /* Allocate memory for the user context */ Disable_Interrupts(); context = (struct User_Context *)Malloc(sizeof(*context)); if (context != 0) context->memory = Malloc(size); Enable_Interrupts(); if (context == 0 || context->memory == 0) goto fail; /* * Fill user memory with zeroes; * leaving it uninitialized is a potential security flaw */ memset(context->memory, '\0', size); context->size = size; /* Allocate an LDT descriptor for the user context */ context->ldtDescriptor = Allocate_Segment_Descriptor(); if (context->ldtDescriptor == 0) goto fail; if (userDebug) Print("Allocated descriptor %d for LDT\n", Get_Descriptor_Index(context->ldtDescriptor)); Init_LDT_Descriptor(context->ldtDescriptor, context->ldt, NUM_USER_LDT_ENTRIES); index = Get_Descriptor_Index(context->ldtDescriptor); context->ldtSelector = Selector(KERNEL_PRIVILEGE, true, index); /* Initialize code and data segments within the LDT */ Init_Code_Segment_Descriptor(&context->ldt[0], (ulong_t) context->memory, size / PAGE_SIZE, USER_PRIVILEGE); Init_Data_Segment_Descriptor(&context->ldt[1], (ulong_t) context->memory, size / PAGE_SIZE, USER_PRIVILEGE); context->csSelector = Selector(USER_PRIVILEGE, false, 0); context->dsSelector = Selector(USER_PRIVILEGE, false, 1); /* Nobody is using this user context yet */ context->refCount = 0; /* Initialize background flag */ context->backgrounded = 0; /* Initialize all semaphore flags to 0 */ int sem_ind; for (sem_ind = 0; sem_ind < MAX_SEM_SIZE; sem_ind++) { context->sem_flags[sem_ind] = 0; } /* Success! */ return context; fail: /* We failed; release any allocated memory */ Disable_Interrupts(); if (context != 0) { if (context->memory != 0) Free(context->memory); Free(context); } Enable_Interrupts(); return 0; }
static int Spawn_Program(char *exeFileData, struct Exe_Format *exeFormat) { struct Segment_Descriptor* desc; unsigned long virtSize; unsigned short codeSelector, dataSelector; int i; ulong_t maxva = 0; /* Find maximum virtual address */ for (i = 0; i < exeFormat->numSegments; ++i) { struct Exe_Segment *segment = &exeFormat->segmentList[i]; ulong_t topva = segment->startAddress + segment->sizeInMemory; if (topva > maxva) maxva = topva; } /* setup some memory space for the program */ virtSize = Round_Up_To_Page(maxva) + 4096; /* leave some slack for stack */ virtSpace = Malloc(virtSize); memset((char *) virtSpace, '\0', virtSize); /* Load segment data into memory */ for (i = 0; i < exeFormat->numSegments; ++i) { struct Exe_Segment *segment = &exeFormat->segmentList[i]; memcpy(virtSpace + segment->startAddress, exeFileData + segment->offsetInFile, segment->lengthInFile); } /* allocate and init descriptors and selectors for code and data */ // Kernel code segment. desc = Allocate_Segment_Descriptor(); Init_Code_Segment_Descriptor( desc, (unsigned long)virtSpace, // base address (virtSize/PAGE_SIZE)+10, // num pages 0 // privilege level (0 == kernel) ); codeSelector = Selector( 0, true, Get_Descriptor_Index( desc ) ); // Kernel data segment. desc = Allocate_Segment_Descriptor(); Init_Data_Segment_Descriptor( desc, (unsigned long)virtSpace, // base address (virtSize/PAGE_SIZE)+10, // num pages 0 // privilege level (0 == kernel) ); dataSelector = Selector( 0, true, Get_Descriptor_Index( desc ) ); Install_Interrupt_Handler( 0x90, &Printrap_Handler ); if (lprogdebug) { Print("Spawn_Program(): all structures are set up\n"); Print(" virtSpace = %x\n", (unsigned int) virtSpace); Print(" virtSize = %x\n", (unsigned int) virtSize); Print(" codeSelector = %x\n", codeSelector); Print(" dataSelector = %x\n", dataSelector); Print("Now calling Trampoline()... \n"); } Trampoline(codeSelector, dataSelector, exeFormat->entryAddr); return 0; }
/* * Load a user executable into memory by creating a User_Context * data structure. * Params: * exeFileData - a buffer containing the executable to load * exeFileLength - number of bytes in exeFileData * exeFormat - parsed ELF segment information describing how to * load the executable's text and data segments, and the * code entry point address * command - string containing the complete command to be executed: * this should be used to create the argument block for the * process * pUserContext - reference to the pointer where the User_Context * should be stored * * Returns: * 0 if successful, or an error code (< 0) if unsuccessful */ int Load_User_Program(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat, const char *command, struct User_Context **pUserContext) { /* * Hints: * ok - Determine where in memory each executable segment will be placed * ok - Determine size of argument block and where it memory it will * be placed * - Copy each executable segment into memory * - Format argument block in memory * - In the created User_Context object, set code entry point * address, argument block address, and initial kernel stack pointer * address */ int i; ulong_t size; ulong_t maxva = 0; unsigned numArgs; ulong_t argBlockSize; /* calculates arg block length */ Get_Argument_Block_Size(command, &numArgs, &argBlockSize); /* Find maximum virtual address */ for (i = 0; i < exeFormat->numSegments; ++i) { struct Exe_Segment *segment = &exeFormat->segmentList[i]; ulong_t topva = segment->startAddress + segment->sizeInMemory; if (topva > maxva) maxva = topva; } /* calculates memory size for the program, the stack and the args */ size = Round_Up_To_Page(maxva) + Round_Up_To_Page(DEFAULT_USER_STACK_SIZE + argBlockSize); /* creates the user context */ if( (*pUserContext = Create_User_Context(size)) == 0 ) return -1; /* Load segment data into memory */ for (i = 0; i < exeFormat->numSegments; ++i) { struct Exe_Segment *segment = &exeFormat->segmentList[i]; memcpy((*pUserContext)->memory + segment->startAddress, exeFileData + segment->offsetInFile, segment->lengthInFile); } /* copy the args just after the data segment */ struct Exe_Segment *segment = &exeFormat->segmentList[1]; int userAddress = segment->startAddress + segment->lengthInFile; Print("%.8x\n", userAddress); Format_Argument_Block( (*pUserContext)->memory + userAddress, numArgs, userAddress, command); /* to show some part of the code */ // memDump((*pUserContext)->memory + userAddress, 0x6c + 0x20); /* allocate the LDT descriptor in the GDT */ (*pUserContext)->ldtDescriptor = Allocate_Segment_Descriptor(); Init_LDT_Descriptor( (*pUserContext)->ldtDescriptor, (*pUserContext)->ldt, NUM_USER_LDT_ENTRIES); /* the LDT selector */ (*pUserContext)->ldtSelector = Selector( KERNEL_PRIVILEGE, true, /* in the GDT */ Get_Descriptor_Index( (*pUserContext)->ldtDescriptor )); /* code descriptor */ Init_Code_Segment_Descriptor( &(*pUserContext)->ldt[0], (ulong_t)(*pUserContext)->memory , // base address ((*pUserContext)->size/PAGE_SIZE)+10, // FIXME is ok??? num pages USER_PRIVILEGE ); (*pUserContext)->csSelector = Selector( USER_PRIVILEGE, false, /* LDT */ 0 ); /* descriptor index */ /* data descriptor */ Init_Data_Segment_Descriptor( &(*pUserContext)->ldt[1], (ulong_t)(*pUserContext)->memory , // base address ((*pUserContext)->size/PAGE_SIZE)+10, // FIXME is ok??? num pages USER_PRIVILEGE ); (*pUserContext)->dsSelector = Selector( USER_PRIVILEGE, false, /* LDT */ 1 ); /* descriptor index */ /* entry point */ (*pUserContext)->entryAddr = exeFormat->entryAddr; /* Address of argument block in user memory */ (*pUserContext)->argBlockAddr = userAddress; (*pUserContext)->stackPointerAddr = (*pUserContext)->size; /* Initial stack pointer */ // TODO stackPointerAddr; /* * May use this in future to allow multiple threads * in the same user context * * int refCount; * */ /* for debuging */ Print("virt Space: From %p to %p\n", (*pUserContext)->memory, (*pUserContext)->memory + (*pUserContext)->size); Print("%.8lX\n", (*pUserContext)->size); //Print("codeSelector=%08x,DataSelector=%08x\n", (*pUserContext)->csSelector, // (*pUserContext)->dsSelector); //j memDump((*pUserContext)->memory+0x24f0,0x100); // memDump((void*)(*pUserContext),0x100); return 0; }