/* * 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) { int i; ulong_t maxva = 0; unsigned numArgs; ulong_t argBlockSize; ulong_t size, argBlockAddr; struct User_Context *userContext = 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; /* FIXME: range check */ if (topva > maxva) maxva = topva; } /* Determine size required for argument block */ Get_Argument_Block_Size(command, &numArgs, &argBlockSize); /* * Now we can determine the size of the memory block needed * to run the process. */ size = Round_Up_To_Page(maxva) + DEFAULT_USER_STACK_SIZE; argBlockAddr = size; size += argBlockSize; /* Create User_Context */ userContext = Create_User_Context(size); if (userContext == 0) return -1; /* Load segment data into memory */ for (i = 0; i < exeFormat->numSegments; ++i) { struct Exe_Segment *segment = &exeFormat->segmentList[i]; memcpy(userContext->memory + segment->startAddress, exeFileData + segment->offsetInFile, segment->lengthInFile); } /* Format argument block */ Format_Argument_Block(userContext->memory + argBlockAddr, numArgs, argBlockAddr, command); /* Fill in code entry point */ userContext->entryAddr = exeFormat->entryAddr; /* * Fill in addresses of argument block and stack * (They happen to be the same) */ userContext->argBlockAddr = argBlockAddr; userContext->stackPointerAddr = argBlockAddr; *pUserContext = userContext; 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; }