Example #1
0
static int load_elf(struct exec_info *execi)
{
  int r;
  struct vnode *vp;
  int proc_e;
  phys_bytes tot_bytes;		/* total space for program, including gap */
  vir_bytes text_vaddr, text_paddr, text_filebytes, text_membytes;
  vir_bytes data_vaddr, data_paddr, data_filebytes, data_membytes;
  off_t text_offset, data_offset;
  int sep_id, is_elf;

  assert(execi != NULL);
  assert(execi->hdr != NULL);
  assert(execi->vp != NULL);

  proc_e = execi->proc_e;
  vp = execi->vp;

  /* Read the file header and extract the segment sizes. */
  r = read_header_elf(execi->hdr, &text_vaddr, &text_paddr,
		      &text_filebytes, &text_membytes,
		      &data_vaddr, &data_paddr,
		      &data_filebytes, &data_membytes,
		      &execi->pc, &text_offset, &data_offset);
  if (r != OK) return(r);

  sep_id = 0;
  is_elf = 1;
  tot_bytes = 0; /* Use default stack size */
  r = exec_newmem(proc_e,
		  trunc_page(text_vaddr), text_membytes,
		  trunc_page(data_vaddr), data_membytes,
		  tot_bytes, execi->frame_len, sep_id, is_elf,
		  vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime,
		  execi->progname, execi->new_uid, execi->new_gid,
		  &execi->stack_top, &execi->load_text, &execi->setugid);

  if (r != OK) {
        printf("VFS: load_elf: exec_newmem failed: %d\n", r);
        return(r);
  }

  /* Read in text and data segments. */
  if (execi->load_text)
      r = read_seg(vp, text_offset, proc_e, T, text_vaddr, text_filebytes);

  if (r == OK)
      r = read_seg(vp, data_offset, proc_e, D, data_vaddr, data_filebytes);

  return(r);
}
Example #2
0
File: exec.c Project: mwilbur/minix
static int load_elf(struct exec_info *execi)
{
  int r;
  int proc_e;
  phys_bytes tot_bytes;		/* total space for program, including gap */
  vir_bytes text_addr, text_filebytes, text_membytes;
  vir_bytes data_addr, data_filebytes, data_membytes;
  off_t text_offset, data_offset;
  int sep_id, is_elf, load_text, allow_setuid;
  uid_t new_uid;
  gid_t new_gid;

  assert(execi != NULL);
  assert(execi->image != NULL);

  proc_e = execi->proc_e;

  /* Read the file header and extract the segment sizes. */
  r = read_header_elf(execi->image, &text_addr, &text_filebytes, &text_membytes,
		      &data_addr, &data_filebytes, &data_membytes,
		      &tot_bytes, &execi->pc, &text_offset, &data_offset);
  if (r != OK) {
      return(r);
  }

  new_uid= getuid();
  new_gid= getgid();

  sep_id = 1;
  is_elf = 1;

  r = exec_newmem(proc_e,
		  trunc_page(text_addr), text_membytes,
		  trunc_page(data_addr), data_membytes,
		  tot_bytes, execi->frame_len, sep_id, is_elf,
		  0 /*dev*/, proc_e /*inum*/, 0 /*ctime*/,
		  execi->progname, new_uid, new_gid,
		  &execi->stack_top, &load_text, &allow_setuid);
  if (r != OK)
  {
      printf("RS: load_elf: exec_newmem failed: %d\n", r);
      exec_restart(proc_e, r, execi->pc);
      return r;
  }

  /* Read in text and data segments. */
  if (load_text) {
      r = read_seg(execi, text_offset, proc_e, T, text_addr, text_filebytes);
      if (r != OK)
      {
	  printf("RS: load_elf: read_seg failed: %d\n", r);
	  exec_restart(proc_e, r, execi->pc);
	  return r;
      }
  }
  else
      printf("RS: load_elf: not loading text segment\n");

  r = read_seg(execi, data_offset, proc_e, D, data_addr, data_filebytes);
  if (r != OK)
  {
      printf("RS: load_elf: read_seg failed: %d\n", r);
      exec_restart(proc_e, r, execi->pc);
      return r;
  }

  return(OK);
}
Example #3
0
void exec_mb(char *kernel, char* modules)
/* Get a Minix image into core, patch it up and execute. */
{
	int i;
	static char hdr[SECTOR_SIZE];
	char *buf;
	u32_t vsec, addr, limit, n, totalmem = 0;
	u16_t kmagic, mode;
	char *console;
	char params[SECTOR_SIZE];
	extern char *sbrk(int);
	char *verb;
	u32_t text_vaddr, text_paddr, text_filebytes, text_membytes;
	u32_t data_vaddr, data_paddr, data_filebytes, data_membytes;
	u32_t pc;
	u32_t text_offset, data_offset;
	i32_t segsize;
	int r;
	u32_t cs, ds;
	char *modstring, *mod;
	multiboot_info_t *mbinfo;
	multiboot_module_t *mbmodinfo;
	u32_t mbinfo_size, mbmodinfo_size;
	char *memvar;
	memory *mp;
	u32_t mod_cmdline_start, kernel_cmdline_start;
	u32_t modstringlen;
	int modnr;

	/* The stack is pretty deep here, so check if heap and stack collide. */
	(void) sbrk(0);

	if ((verb= b_value(VERBOSEBOOTVARNAME)) != nil)
		verboseboot = a2l(verb);

	printf("\nLoading %s\n", kernel);

	vsec= 0;			/* Load this sector from kernel next. */
	addr= mem[0].base;		/* Into this memory block. */
	limit= mem[0].base + mem[0].size;
	if (limit > caddr) limit= caddr;

	/* set click size for get_segment */
	click_size = PAGE_SIZE;

	k_flags = K_KHIGH|K_BRET|K_MEML|K_INT86|K_RET|K_HDR
	    |K_HIGH|K_CHMEM|K_I386;

	/* big kernels must be loaded into extended memory */
	addr= mem[1].base;
	limit= mem[1].base + mem[1].size;

	/* Get first sector */
	DEBUGEXTRA(("get_sector\n"));
	if ((buf= get_sector(vsec++)) == nil) {
	    DEBUGEXTRA(("get_sector failed\n"));
	    return;
	}
	memcpy(hdr, buf, SECTOR_SIZE);

	/* Get ELF header */
	DEBUGEXTRA(("read_header_elf\n"));
	r = read_header_elf(hdr, &text_vaddr, &text_paddr,
			    &text_filebytes, &text_membytes,
			    &data_vaddr, &data_paddr,
			    &data_filebytes, &data_membytes,
			    &pc, &text_offset, &data_offset);
	if (r < 0) { errno= ENOEXEC; return; }

	/* Read the text segment. */
	addr = text_paddr;
	segsize = (i32_t) text_filebytes;
	vsec = text_offset / SECTOR_SIZE;
	DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
		    vsec, segsize, addr, limit));
	if (!get_segment(&vsec, &segsize, &addr, limit)) return;
	DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx "
		    "addr=0x%lx\n",
		    vsec, segsize, addr));

	/* Read the data segment. */
	addr = data_paddr;
	segsize = (i32_t) data_filebytes;
	vsec = data_offset / SECTOR_SIZE;

	DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
		    vsec, segsize, addr, limit));
	if (!get_segment(&vsec, &segsize, &addr, limit)) return;
	DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx "
		    "addr=0x%lx\n",
		    vsec, segsize, addr));

	n = data_membytes - align(data_filebytes, click_size);

	/* Zero out bss. */
	DEBUGEXTRA(("\nraw_clear(0x%lx, 0x%lx); limit=0x%lx... ", addr, n, limit));
	if (addr + n > limit) { errno= ENOMEM; return; }
	raw_clear(addr, n);
	DEBUGEXTRA(("done\n"));
	addr+= n;

	/* Check the kernel magic number. */
	raw_copy(mon2abs(&kmagic),
		 data_paddr + MAGIC_OFF, sizeof(kmagic));
	if (kmagic != KERNEL_D_MAGIC) {
		printf("Kernel magic number is incorrect (0x%x@0x%lx)\n",
			kmagic, data_paddr + MAGIC_OFF);
		errno= 0;
		return;
	}

	/* Translate the boot parameters to what Minix likes best. */
	DEBUGEXTRA(("params2params(0x%x, 0x%x)... ", params, sizeof(params)));
	if (!params2params(params, sizeof(params))) { errno= 0; return; }
	DEBUGEXTRA(("done\n"));

	/* Create multiboot info struct */
	mbinfo = malloc(sizeof(multiboot_info_t));
	if (mbinfo == nil) { errno= ENOMEM; return; }
	memset(mbinfo, 0, sizeof(multiboot_info_t));

	/* Module info structs start where kernel ends */
	mbinfo->mods_addr = addr;

	modstring = strdup(modules);
	if (modstring == nil) {errno = ENOMEM; return; }
	modstringlen = strlen(modules);
	mbinfo->mods_count = split_module_list(modules);

	mbmodinfo_size = sizeof(multiboot_module_t) * mbinfo->mods_count;
	mbmodinfo = malloc(mbmodinfo_size);
	if (mbmodinfo == nil) { errno= ENOMEM; return; }
	addr+= mbmodinfo_size;
	addr= align(addr, click_size);

	mod_cmdline_start = mbinfo->mods_addr + sizeof(multiboot_module_t) *
	    mbinfo->mods_count;

	raw_copy(mod_cmdline_start, mon2abs(modules),
		 modstringlen+1);

	mbmodinfo[0].cmdline = mod_cmdline_start;
	modnr = 1;
	for (i= 0; i < modstringlen; ++i) {
	    if (modules[i] == '\0') {
		mbmodinfo[modnr].cmdline = mod_cmdline_start + i + 1;
		++modnr;
	    }
	}

	kernel_cmdline_start = mod_cmdline_start + modstringlen + 1;
	mbinfo->cmdline = kernel_cmdline_start;
	raw_copy(kernel_cmdline_start, mon2abs(kernel),
		 strlen(kernel)+1);

	mbinfo->flags = MULTIBOOT_INFO_MODS|MULTIBOOT_INFO_CMDLINE|
	    MULTIBOOT_INFO_BOOTDEV|MULTIBOOT_INFO_MEMORY;

	mbinfo->boot_device = mbdev;
	mbinfo->mem_lower = mem[0].size/1024;
	mbinfo->mem_upper = mem[1].size/1024;

	for (i = 0, mod = strtok(modstring, " "); mod != nil;
	     mod = strtok(nil, " "), i++) {

		mod = select_image(mod);
		if (mod == nil) {errno = 0; return; }

		mbmodinfo[i].mod_start = addr;
		mbmodinfo[i].mod_end = addr + image_bytes;
		mbmodinfo[i].pad = 0;

		segsize= image_bytes;
		vsec= 0;
		DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
		       vsec, segsize, addr, limit));
		if (!get_segment(&vsec, &segsize, &addr, limit)) return;
		DEBUGEXTRA(("get_segment done vsec=0x%lx size=0x%lx "
		       "addr=0x%lx\n",
		       vsec, segsize, addr));
		addr+= segsize;
		addr= align(addr, click_size);
	}
	free(modstring);

	DEBUGEXTRA(("modinfo raw_copy: dst 0x%lx src 0x%lx sz 0x%lx\n",
	    mbinfo->mods_addr, mon2abs(mbmodinfo),
	    mbmodinfo_size));
	raw_copy(mbinfo->mods_addr, mon2abs(mbmodinfo),
	    mbmodinfo_size);
	free(mbmodinfo);

	raw_copy(MULTIBOOT_INFO_ADDR, mon2abs(mbinfo),
		 sizeof(multiboot_info_t));
	free(mbinfo);

	/* Run the trailer function just before starting Minix. */
	DEBUGEXTRA(("run_trailer()... "));
	if (!run_trailer()) { errno= 0; return; }
	DEBUGEXTRA(("done\n"));

	/* Set the video to the required mode. */
	if ((console= b_value("console")) == nil || (mode= a2x(console)) == 0) {
		mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE :
								MONO_MODE;
	}
	DEBUGEXTRA(("set_mode(%d)... ", mode));
	set_mode(mode);
	DEBUGEXTRA(("done\n"));

	/* Close the disk. */
	DEBUGEXTRA(("dev_close()... "));
	(void) dev_close();
	DEBUGEXTRA(("done\n"));

	/* Minix. */
	cs = ds = text_paddr;
	DEBUGEXTRA(("minix(0x%lx, 0x%lx, 0x%lx, 0x%x, 0x%x, 0x%lx)\n",
		pc, cs, ds, params, sizeof(params), 0));
	minix(pc, cs, ds, params, sizeof(params), 0);

	if (!(k_flags & K_BRET)) {
		extern u32_t reboot_code;
		raw_copy(mon2abs(params), reboot_code, sizeof(params));
	}
	parse_code(params);

	/* Return from Minix.  Things may have changed, so assume nothing. */
	fsok= -1;
	errno= 0;

	/* Read leftover character, if any. */
	scan_keyboard();

	/* Restore screen contents. */
	restore_screen();
}