Beispiel #1
0
/*
 * 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;
}
Beispiel #2
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;
}