Esempio n. 1
0
/*
 * There is an ELF kernel and one or more ELF modules loaded.  
 * We wish to start executing the kernel image, so make such 
 * preparations as are required, and do so.
 */
static int
elf32_exec(struct preloaded_file *fp)
{
    struct file_metadata	*md;
    Elf_Ehdr 			*ehdr;
    vm_offset_t			entry, bootinfop, modulep, kernend;
    int				boothowto, err, bootdev;

    if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
	return(EFTYPE);
    ehdr = (Elf_Ehdr *)&(md->md_data);

    err = bi_load32(fp->f_args, &boothowto, &bootdev, &bootinfop, &modulep, &kernend);
    if (err != 0)
	return(err);
    entry = ehdr->e_entry & 0xffffff;

#ifdef DEBUG
    printf("Start @ 0x%lx ...\n", entry);
#endif

    dev_cleanup();
    __exec((void *)entry, boothowto, bootdev, 0, 0, 0, bootinfop, modulep, kernend);

    panic("exec returned");
}
Esempio n. 2
0
thread_QThread::thread_QThread()
{
    _thread = new QThread(xfmain.getXfalconWnd());

    connect(_thread, SIGNAL(started()), this, SLOT(__exec()));
    connect(_thread, SIGNAL(finished()), this, SLOT(deleteLater()));

    this->moveToThread(_thread);
}
Esempio n. 3
0
File: rua.c Progetto: pjhwan92/tizen
static int __create_table(sqlite3 *db)
{
	int r;

	r = __exec(db, CREATE_RUA_HISTORY_TABLE);
	if (r == -1) {
		LOGE("create table error");
		return -1;
	}

	return 0;
}
Esempio n. 4
0
void
Execution(FormatedInput* input, Environ* env) {
   char *path = 0;
   if (input->datas[0][0] == '.' ||
       input->datas[0][0] == '/')
     path = input->datas[0];
   else
    path = __binPath(env, input);

   if (path == 0) {
      printf("%s : no such command\n", input->datas[0]);
      return ;
   }
   __exec(input, env, path);
}
Esempio n. 5
0
File: rua.c Progetto: pjhwan92/tizen
int rua_clear_history(void)
{
	int r;
	char query[QUERY_MAXLEN];

	if (_db == NULL) {
		LOGE("rua is not inited.");
		return -1;
	}

	LOGD("rua clear history is invoked");

	snprintf(query, QUERY_MAXLEN, "delete from %s;", RUA_HISTORY);

	r = __exec(_db, query);

	return r;
}
Esempio n. 6
0
File: time.c Progetto: TySag/project
int main(int argc, char **argv)
{
	int pid;
	argv[argc] = 0;
	uint64_t before = sys_gettime();

	if (argc > 1) {
		pid = fork();
		if (pid < 0) {
			printf("Error: cannot fork process.\n");
		} else if (pid == 0) {
			__exec(NULL, argv + 1, NULL);
		}
		waitpid(pid, NULL);
	}

	uint64_t after = sys_gettime();

	printf("\n ===== Summary ===== \n");
	printf("real    %ld ticks.\n", after - before);
	printf("\n");
	return 0;
}
Esempio n. 7
0
File: rua.c Progetto: pjhwan92/tizen
int rua_delete_history_with_pkgname(char *pkg_name)
{
	int r;
	char query[QUERY_MAXLEN];

	if (_db == NULL) {
		LOGE("rua is not inited.");
		return -1;
	}

	if (pkg_name == NULL) {
		LOGE("pkg_name is null");
		return -1;
	}

	LOGD("rua delete history with name(%s) is invoked", pkg_name);

	snprintf(query, QUERY_MAXLEN, "delete from %s where pkg_name = '%s';",
		RUA_HISTORY, pkg_name);

	r = __exec(_db, query);

	return r;
}
Esempio n. 8
0
File: rua.c Progetto: pjhwan92/tizen
int rua_delete_history_with_apppath(char *app_path)
{
	int r;
	char query[QUERY_MAXLEN];

	if (_db == NULL) {
		LOGE("rua is not inited.");
		return -1;
	}

	if (app_path == NULL) {
		LOGE("app_path is null");
		return -1;
	}

	LOGD("rua delete history with path(%s) is invoked", app_path);

	snprintf(query, QUERY_MAXLEN, "delete from %s where app_path = '%s';",
		RUA_HISTORY, app_path);

	r = __exec(_db, query);

	return r;
}
Esempio n. 9
0
File: rua.c Progetto: pjhwan92/tizen
int rua_add_history(struct rua_rec *rec)
{
	int r;
	int cnt = 0;
	char query[QUERY_MAXLEN];
	sqlite3_stmt *stmt;

	unsigned int timestamp;
	timestamp = PERF_MEASURE_START("RUA");

	LOGD("rua_add_history invoked");

	if (_db == NULL) {
		LOGE("rua is not inited.");
		return -1;
	}

	if (rec == NULL) {
		LOGE("rec is null");
		return -1;
	}

	snprintf(query, QUERY_MAXLEN,
		"select count(*) from %s where pkg_name = '%s';", RUA_HISTORY,
		rec->pkg_name);

	r = sqlite3_prepare(_db, query, sizeof(query), &stmt, NULL);
	if (r != SQLITE_OK) {
		LOGE("query prepare error(%d)", r);
		return -1;
	}

	r = sqlite3_step(stmt);
	if (r == SQLITE_ROW) {
		cnt = sqlite3_column_int(stmt, 0);
	}
	sqlite3_finalize(stmt);

	/****************************************************/
	if (!flag) {
		vconf_unset_recursive ("db/rua_data");
		flag = 1;
	}
	if(strcmp(rec->pkg_name, "org.tizen.menu-screen") && strcmp(rec->pkg_name, "org.tizen.volume") && strcmp(rec->pkg_name, "org.tizen.lockscreen") && strcmp(rec->pkg_name, "org.tizen.pwlock")){
		int total = 0;
		int apps;
		char key[255], *key2 = "db/rua_data/apps";
		sprintf (key, "db/rua_data/%s", "tizen_total_cnt");
		if (vconf_get_int (key, &total) < 0)
			total = 0;
		vconf_set_int (key, total + 1);
		memset (key, 0, 255);
		sprintf (key, "db/rua_data/%s", rec->pkg_name);
		if (vconf_get_int (key, &total) < 0) {
			total = 0;
			if (vconf_get_int (key2, &apps) < 0)
				apps = 0;
			vconf_set_int (key2, apps + 1);
		}
		vconf_set_int (key, total + 1);
	}
	/****************************************************/
	if (cnt == 0) {
		/* insert */
		snprintf(query, QUERY_MAXLEN,
			"insert into %s ( pkg_name, app_path, arg, launch_time ) "
			" values ( \"%s\", \"%s\", \"%s\", %d ) ",
			RUA_HISTORY,
			rec->pkg_name ? rec->pkg_name : "",
			rec->app_path ? rec->app_path : "",
			rec->arg ? rec->arg : "", (int)time(NULL));
	}
	else {
		/* update */
		snprintf(query, QUERY_MAXLEN,
			"update %s set arg='%s', launch_time='%d' where pkg_name = '%s';",
			RUA_HISTORY,
			rec->arg ? rec->arg : "", (int)time(NULL), rec->pkg_name);
	}

	r = __exec(_db, query);
	if (r == -1) {
		LOGE("[RUA ADD HISTORY ERROR] %s\n", query);
		return -1;
	}

	PERF_MEASURE_END("RUA", timestamp);

	return r;
}
Esempio n. 10
0
static void
load(void)
{
    union {
	struct exec ex;
	Elf32_Ehdr eh;
    } hdr;
    Elf32_Phdr ep[2];
    Elf32_Shdr es[2];
    caddr_t p;
    ino_t ino;
    uint32_t addr, x;
    int fmt, i, j;

    if (!(ino = lookup(kname))) {
	if (!ls)
	    printf("No %s\n", kname);
	return;
    }
    if (xfsread(ino, &hdr, sizeof(hdr)))
	return;
    if (N_GETMAGIC(hdr.ex) == ZMAGIC)
	fmt = 0;
    else if (IS_ELF(hdr.eh))
	fmt = 1;
    else {
	printf("Invalid %s\n", "format");
	return;
    }
    if (fmt == 0) {
	addr = hdr.ex.a_entry & 0xffffff;
	p = PTOV(addr);
	fs_off = PAGE_SIZE;
	if (xfsread(ino, p, hdr.ex.a_text))
	    return;
	p += roundup2(hdr.ex.a_text, PAGE_SIZE);
	if (xfsread(ino, p, hdr.ex.a_data))
	    return;
	p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
	bootinfo.bi_symtab = VTOP(p);
	memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
	p += sizeof(hdr.ex.a_syms);
	if (hdr.ex.a_syms) {
	    if (xfsread(ino, p, hdr.ex.a_syms))
		return;
	    p += hdr.ex.a_syms;
	    if (xfsread(ino, p, sizeof(int)))
		return;
	    x = *(uint32_t *)p;
	    p += sizeof(int);
	    x -= sizeof(int);
	    if (xfsread(ino, p, x))
		return;
	    p += x;
	}
    } else {
	fs_off = hdr.eh.e_phoff;
	for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) {
	    if (xfsread(ino, ep + j, sizeof(ep[0])))
		return;
	    if (ep[j].p_type == PT_LOAD)
		j++;
	}
	for (i = 0; i < 2; i++) {
	    p = PTOV(ep[i].p_paddr & 0xffffff);
	    fs_off = ep[i].p_offset;
	    if (xfsread(ino, p, ep[i].p_filesz))
		return;
	}
	p += roundup2(ep[1].p_memsz, PAGE_SIZE);
	bootinfo.bi_symtab = VTOP(p);
	if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) {
	    fs_off = hdr.eh.e_shoff + sizeof(es[0]) *
		(hdr.eh.e_shstrndx + 1);
	    if (xfsread(ino, &es, sizeof(es)))
		return;
	    for (i = 0; i < 2; i++) {
		memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size));
		p += sizeof(es[i].sh_size);
		fs_off = es[i].sh_offset;
		if (xfsread(ino, p, es[i].sh_size))
		    return;
		p += es[i].sh_size;
	    }
	}
	addr = hdr.eh.e_entry & 0xffffff;
    }
    bootinfo.bi_esymtab = VTOP(p);
    bootinfo.bi_kernelname = VTOP(kname);
    bootinfo.bi_bios_dev = dsk.drive;
    __exec((caddr_t)addr, opts & RBX_MASK,
	   MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),
	   0, 0, 0, VTOP(&bootinfo));
}
Esempio n. 11
0
int ph_exec(char *name)
{
    return __exec(name);
}
Esempio n. 12
0
int
runcmd(char *cmd) {
    static char argv0[BUFSIZE];
    const char *argv[EXEC_MAX_ARG_NUM + 1];
    char *t;
    int argc, token, ret, p[2];
again:
    argc = 0;
    while (1) {
        switch (token = gettoken(&cmd, &t)) {
        case 'w':
            if (argc == EXEC_MAX_ARG_NUM) {
                printf("sh error: too many arguments\n");
                return -1;
            }
            argv[argc ++] = t;
            break;
        case '<':
            if (gettoken(&cmd, &t) != 'w') {
                printf("sh error: syntax error: < not followed by word\n");
                return -1;
            }
            if ((ret = reopen(0, t, O_RDONLY)) != 0) {
                return ret;
            }
            break;
        case '>':
            if (gettoken(&cmd, &t) != 'w') {
                printf("sh error: syntax error: > not followed by word\n");
                return -1;
            }
            if ((ret = reopen(1, t, O_RDWR | O_TRUNC | O_CREAT)) != 0) {
                return ret;
            }
            break;
        case '|':
            if ((ret = pipe(p)) != 0) {
                return ret;
            }
            if ((ret = fork()) == 0) {
                close(0);
                if ((ret = dup2(p[0], 0)) < 0) {
                    return ret;
                }
                close(p[0]), close(p[1]);
                goto again;
            }
            else {
                if (ret < 0) {
                    return ret;
                }
                close(1);
                if ((ret = dup2(p[1], 1)) < 0) {
                    return ret;
                }
                close(p[0]), close(p[1]);
                goto runit;
            }
            break;
        case 0:
            goto runit;
        case ';':
            if ((ret = fork()) == 0) {
                goto runit;
            }
            else {
                if (ret < 0) {
                    return ret;
                }
                waitpid(ret, NULL);
                goto again;
            }
            break;
        default:
            printf("sh error: bad return %d from gettoken\n", token);
            return -1;
        }
    }

runit:
    if (argc == 0) {
        return 0;
    }
    else if (strcmp(argv[0], "cd") == 0) {
        if (argc != 2) {
            return -1;
        }
        strcpy(shcwd, argv[1]);
        return 0;
    }
    if ((ret = testfile(argv[0])) != 0) {
        if (ret != -E_NOENT) {
            return ret;
        }
        snprintf(argv0, sizeof(argv0), "/bin/%s", argv[0]);
        argv[0] = argv0;
    }
    argv[argc] = NULL;
    return __exec(NULL, argv, g_envp);
}
Esempio n. 13
0
static int
multiboot_exec(struct preloaded_file *fp)
{
	struct preloaded_file		*mfp;
	vm_offset_t			 entry;
	struct file_metadata		*md;
	struct multiboot_info		*mb_info = NULL;
	struct multiboot_mod_list	*mb_mod = NULL;
	multiboot_memory_map_t		*mmap;
	struct bios_smap		*smap;
	struct devdesc			*rootdev;
	char				*cmdline = NULL;
	size_t				 len;
	int				 error, num, i;
	int				 rootfs = 0;	/* flag for rootfs */
	int				 xen = 0;	/* flag for xen */
	int				 kernel = 0;	/* flag for kernel */

	/* Set up base for mb_malloc. */
	for (mfp = fp; mfp->f_next != NULL; mfp = mfp->f_next);

	/* Start info block from new page. */
	last_addr = roundup(mfp->f_addr + mfp->f_size, MULTIBOOT_MOD_ALIGN);

	/* Allocate the multiboot struct and fill the basic details. */
	mb_info = (struct multiboot_info *)PTOV(mb_malloc(sizeof (*mb_info)));

	bzero(mb_info, sizeof(struct multiboot_info));
	mb_info->flags = MULTIBOOT_INFO_MEMORY|MULTIBOOT_INFO_BOOT_LOADER_NAME;
	mb_info->mem_lower = bios_basemem / 1024;
	mb_info->mem_upper = bios_extmem / 1024;
	mb_info->boot_loader_name = mb_malloc(strlen(bootprog_info) + 1);

	i386_copyin(bootprog_info, mb_info->boot_loader_name,
	    strlen(bootprog_info) + 1);

	i386_getdev((void **)(&rootdev), NULL, NULL);
	if (rootdev == NULL) {
		printf("can't determine root device\n");
		error = EINVAL;
		goto error;
	}

	/*
	 * Boot image command line. If args were not provided, we need to set
	 * args here, and that depends on image type...
	 * Fortunately we only have following options:
	 * 64 or 32 bit unix or xen. So we just check if f_name has unix.
	 */
	/* Do we boot xen? */
	if (strstr(fp->f_name, "unix") == NULL)
		xen = 1;

	entry = fp->f_addr;

	num = 0;
	for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) {
		num++;
		if (mfp->f_type != NULL && strcmp(mfp->f_type, "rootfs") == 0)
			rootfs++;
		if (mfp->f_type != NULL && strcmp(mfp->f_type, "kernel") == 0)
			kernel++;
	}

	if (num == 0 || rootfs == 0) {
		/* We need at least one module - rootfs. */
		printf("No rootfs module provided, aborting\n");
		error = EINVAL;
		goto error;
	}
	if (xen == 1 && kernel == 0) {
		printf("No kernel module provided for xen, aborting\n");
		error = EINVAL;
		goto error;
	}
	mb_mod = (struct multiboot_mod_list *) PTOV(last_addr);
	last_addr += roundup(sizeof(*mb_mod) * num, MULTIBOOT_INFO_ALIGN);

	bzero(mb_mod, sizeof(*mb_mod) * num);

	num = 0;
	for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) {
		mb_mod[num].mod_start = mfp->f_addr;
		mb_mod[num].mod_end = mfp->f_addr + mfp->f_size;

		if (strcmp(mfp->f_type, "kernel") == 0) {
			cmdline = NULL;
			error = mb_kernel_cmdline(mfp, rootdev, &cmdline);
			if (error != 0)
				goto error;
		} else {
			len = strlen(mfp->f_name) + 1;
			len += strlen(mfp->f_type) + 5 + 1;
			if (mfp->f_args != NULL) {
				len += strlen(mfp->f_args) + 1;
			}
			cmdline = malloc(len);
			if (cmdline == NULL) {
				error = ENOMEM;
				goto error;
			}

			if (mfp->f_args != NULL)
				snprintf(cmdline, len, "%s type=%s %s",
				    mfp->f_name, mfp->f_type, mfp->f_args);
			else
				snprintf(cmdline, len, "%s type=%s",
				    mfp->f_name, mfp->f_type);
		}

		mb_mod[num].cmdline = mb_malloc(strlen(cmdline)+1);
		i386_copyin(cmdline, mb_mod[num].cmdline, strlen(cmdline)+1);
		free(cmdline);
		num++;
	}

	mb_info->mods_count = num;
	mb_info->mods_addr = VTOP(mb_mod);
	mb_info->flags |= MULTIBOOT_INFO_MODS;

	md = file_findmetadata(fp, MODINFOMD_SMAP);
	if (md == NULL) {
		printf("no memory smap\n");
		error = EINVAL;
		goto error;
	}

	num = md->md_size / sizeof(struct bios_smap); /* number of entries */
	mmap = (multiboot_memory_map_t *)PTOV(mb_malloc(sizeof(*mmap) * num));

	mb_info->mmap_length = num * sizeof(*mmap);
	smap = (struct bios_smap *)md->md_data;

	for (i = 0; i < num; i++) {
		mmap[i].size = sizeof(*smap);
		mmap[i].addr = smap[i].base;
		mmap[i].len = smap[i].length;
		mmap[i].type = smap[i].type;
	}
	mb_info->mmap_addr = VTOP(mmap);
	mb_info->flags |= MULTIBOOT_INFO_MEM_MAP;

	if (strstr(getenv("loaddev"), "net") != NULL &&
	    bootp_response != NULL) {
		mb_info->drives_length = bootp_response_size;
		mb_info->drives_addr = mb_malloc(bootp_response_size);
		i386_copyin(bootp_response, mb_info->drives_addr,
		    bootp_response_size);
		mb_info->flags &= ~MULTIBOOT_INFO_DRIVE_INFO;
	}
	/*
	 * Set the image command line. Need to do this as last thing,
	 * as illumos kernel dboot_startkern will check cmdline
	 * address as last check to find first free address.
	 */
	if (fp->f_args == NULL) {
		if (xen)
			cmdline = getenv("xen_cmdline");
		else
			cmdline = getenv("boot-args");
		if (cmdline != NULL) {
			fp->f_args = strdup(cmdline);
			if (fp->f_args == NULL) {
				error = ENOMEM;
				goto error;
			}
		}
	}

	/*
	 * If the image is xen, we just use f_name + f_args for commandline
	 * for unix, we need to add zfs-bootfs.
	 */
	if (xen) {
		len = strlen(fp->f_name) + 1;
		if (fp->f_args != NULL)
			len += strlen(fp->f_args) + 1;

		if (fp->f_args != NULL) {
			if((cmdline = malloc(len)) == NULL) {
				error = ENOMEM;
				goto error;
			}
			snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args);
		} else {
			cmdline = strdup(fp->f_name);
			if (cmdline == NULL) {
				error = ENOMEM;
				goto error;
			}
		}
	} else {
		cmdline = NULL;
		if ((error = mb_kernel_cmdline(fp, rootdev, &cmdline)) != 0)
			goto error;
	}

	mb_info->cmdline = mb_malloc(strlen(cmdline)+1);
	i386_copyin(cmdline, mb_info->cmdline, strlen(cmdline)+1);
	mb_info->flags |= MULTIBOOT_INFO_CMDLINE;
	free(cmdline);
	cmdline = NULL;

	dev_cleanup();
	__exec((void *)VTOP(multiboot_tramp), MULTIBOOT_BOOTLOADER_MAGIC,
	    (void *)entry, (void *)VTOP(mb_info));

	panic("exec returned");

error:
	free(cmdline);
	return (error);
}
Esempio n. 14
0
static int
multiboot_exec(struct preloaded_file *fp)
{
	vm_offset_t			 module_start, last_addr, metadata_size;
	vm_offset_t			 modulep, kernend, entry;
	struct file_metadata		*md;
	Elf_Ehdr			*ehdr;
	struct multiboot_info		*mb_info = NULL;
	struct multiboot_mod_list	*mb_mod = NULL;
	char				*cmdline = NULL;
	size_t				 len;
	int				 error, mod_num;

	/*
	 * Don't pass the memory size found by the bootloader, the memory
	 * available to Dom0 will be lower than that.
	 */
	unsetenv("smbios.memory.enabled");

	/* Allocate the multiboot struct and fill the basic details. */
	mb_info = malloc(sizeof(struct multiboot_info));
	if (mb_info == NULL) {
		error = ENOMEM;
		goto error;
	}
	bzero(mb_info, sizeof(struct multiboot_info));
	mb_info->flags = MULTIBOOT_INFO_MEMORY|MULTIBOOT_INFO_BOOT_LOADER_NAME;
	mb_info->mem_lower = bios_basemem / 1024;
	mb_info->mem_upper = bios_extmem / 1024;
	mb_info->boot_loader_name = VTOP(mbl_name);

	/* Set the Xen command line. */
	if (fp->f_args == NULL) {
		/* Add the Xen command line if it is set. */
		cmdline = getenv("xen_cmdline");
		if (cmdline != NULL) {
			fp->f_args = strdup(cmdline);
			if (fp->f_args == NULL) {
				error = ENOMEM;
				goto error;
			}
		}
	}
	if (fp->f_args != NULL) {
		len = strlen(fp->f_name) + 1 + strlen(fp->f_args) + 1;
		cmdline = malloc(len);
		if (cmdline == NULL) {
			error = ENOMEM;
			goto error;
		}
		snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args);
		mb_info->cmdline = VTOP(cmdline);
		mb_info->flags |= MULTIBOOT_INFO_CMDLINE;
	}

	/* Find the entry point of the Xen kernel and save it for later */
	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
		printf("Unable to find %s entry point\n", fp->f_name);
		error = EINVAL;
		goto error;
	}
	ehdr = (Elf_Ehdr *)&(md->md_data);
	entry = ehdr->e_entry & 0xffffff;

	/*
	 * Prepare the multiboot module list, Xen assumes the first
	 * module is the Dom0 kernel, and the second one is the initramfs.
	 * This is not optimal for FreeBSD, that doesn't have a initramfs
	 * but instead loads modules dynamically and creates the metadata
	 * info on-the-fly.
	 *
	 * As expected, the first multiboot module is going to be the
	 * FreeBSD kernel loaded as a raw file. The second module is going
	 * to contain the metadata info and the loaded modules.
	 *
	 * On native FreeBSD loads all the modules and then places the
	 * metadata info at the end, but this is painful when running on Xen,
	 * because it relocates the second multiboot module wherever it
	 * likes. In order to workaround this limitation the metadata
	 * information is placed at the start of the second module and
	 * the original modulep value is saved together with the other
	 * metadata, so we can relocate everything.
	 *
	 * Native layout:
	 *           fp->f_addr + fp->f_size
	 * +---------+----------------+------------+
	 * |         |                |            |
	 * | Kernel  |    Modules     |  Metadata  |
	 * |         |                |            |
	 * +---------+----------------+------------+
	 * fp->f_addr                 modulep      kernend
	 *
	 * Xen layout:
	 *
	 * Initial:
	 *                      fp->f_addr + fp->f_size
	 * +---------+----------+----------------+------------+
	 * |         |          |                |            |
	 * | Kernel  | Reserved |    Modules     |  Metadata  |
	 * |         |          |                |  dry run   |
	 * +---------+----------+----------------+------------+
	 * fp->f_addr
	 *
	 * After metadata polacement (ie: final):
	 *                                  fp->f_addr + fp->f_size
	 * +-----------+---------+----------+----------------+
	 * |           |         |          |                |
	 * |  Kernel   |  Free   | Metadata |    Modules     |
	 * |           |         |          |                |
	 * +-----------+---------+----------+----------------+
	 * fp->f_addr            modulep                     kernend
	 * \__________/          \__________________________/
	 *  Multiboot module 0    Multiboot module 1
	 */

	fp = file_findfile(NULL, "elf kernel");
	if (fp == NULL) {
		printf("No FreeBSD kernel provided, aborting\n");
		error = EINVAL;
		goto error;
	}

	if (fp->f_metadata != NULL) {
		printf("FreeBSD kernel already contains metadata, aborting\n");
		error = EINVAL;
		goto error;
	}


	mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES);
	if (mb_mod == NULL) {
		error = ENOMEM;
		goto error;
	}

	bzero(mb_mod, sizeof(struct multiboot_mod_list) * NUM_MODULES);

	/*
	 * Calculate how much memory is needed for the metatdata. We did
	 * an approximation of the maximum size when loading the kernel,
	 * but now we know the exact size, so we can release some of this
	 * preallocated memory if not needed.
	 */
	last_addr = roundup(max_addr(), PAGE_SIZE);
	mod_num = num_modules(fp);

	/*
	 * Place the metadata after the last used address in order to
	 * calculate it's size, this will not be used.
	 */
	error = bi_load64(fp->f_args, last_addr, &modulep, &kernend, 0);
	if (error != 0) {
		printf("bi_load64 failed: %d\n", error);
		goto error;
	}
	metadata_size = roundup(kernend - last_addr, PAGE_SIZE);

	/* Check that the size is not greater than what we have reserved */
	if (metadata_size > METADATA_RESV_SIZE(mod_num)) {
		printf("Required memory for metadata is greater than reserved "
		    "space, please increase METADATA_FIXED_SIZE and "
		    "METADATA_MODULE_SIZE and rebuild the loader\n");
		error = ENOMEM;
		goto error;
	}

	/* Clean the metadata added to the kernel in the bi_load64 dry run */
	file_removemetadata(fp);

	/*
	 * This is the position where the second multiboot module
	 * will be placed.
	 */
	module_start = fp->f_addr + fp->f_size - metadata_size;

	error = bi_load64(fp->f_args, module_start, &modulep, &kernend, 0);
	if (error != 0) {
		printf("bi_load64 failed: %d\n", error);
		goto error;
	}

	mb_mod[0].mod_start = fp->f_addr;
	mb_mod[0].mod_end = fp->f_addr + fp->f_size;
	mb_mod[0].mod_end -= METADATA_RESV_SIZE(mod_num);

	mb_mod[1].mod_start = module_start;
	mb_mod[1].mod_end = last_addr;

	mb_info->mods_count = NUM_MODULES;
	mb_info->mods_addr = VTOP(mb_mod);
	mb_info->flags |= MULTIBOOT_INFO_MODS;

	dev_cleanup();
	__exec((void *)VTOP(multiboot_tramp), (void *)entry,
	    (void *)VTOP(mb_info));

	panic("exec returned");

error:
	if (mb_mod)
		free(mb_mod);
	if (mb_info)
		free(mb_info);
	if (cmdline)
		free(cmdline);
	return (error);
}