Esempio n. 1
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) {
    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;
}
Esempio n. 2
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;
}