示例#1
0
int
command_fdt_internal(int argc, char *argv[])
{
	cmdf_t *cmdh;
	int flags;
	char *cmd;
	int i, err;

	if (argc < 2) {
		command_errmsg = "usage is 'fdt <command> [<args>]";
		return (CMD_ERROR);
	}

	/*
	 * Validate fdt <command>.
	 */
	cmd = strdup(argv[1]);
	i = 0;
	cmdh = NULL;
	while (!(commands[i].name == NULL)) {
		if (strcmp(cmd, commands[i].name) == 0) {
			/* found it */
			cmdh = commands[i].handler;
			flags = commands[i].flags;
			break;
		}
		i++;
	}
	if (cmdh == NULL) {
		command_errmsg = "unknown command";
		return (CMD_ERROR);
	}

	if (flags & CMD_REQUIRES_BLOB) {
		/*
		 * Check if uboot env vars were parsed already. If not, do it now.
		 */
		if (fdt_fixup() == 0)
			return (CMD_ERROR);
	}

	/*
	 * Call command handler.
	 */
	err = (*cmdh)(argc, argv);

	return (err);
}
示例#2
0
/*
 * Copy DTB blob to specified location and return size
 */
int
fdt_copy(vm_offset_t va)
{
	int err;
	debugf("fdt_copy va 0x%08x\n", va);
	if (fdtp == NULL) {
		err = fdt_setup_fdtp();
		if (err) {
			printf("No valid device tree blob found!\n");
			return (0);
		}
	}

	if (fdt_fixup() == 0)
		return (0);

	if (fdtp_va != 0) {
		/* Overwrite the FDT with the fixed version. */
		/* XXX Is this really appropriate? */
		COPYIN(fdtp, fdtp_va, fdtp_size);
	}
	COPYIN(fdtp, va, fdtp_size);
	return (fdtp_size);
}
示例#3
0
/*
 * Load the information expected by a kernel.
 *
 * - The 'boothowto' argument is constructed
 * - The 'bootdev' argument is constructed
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
md_load(char *args, vm_offset_t *modulep)
{
	struct preloaded_file	*kfp, *bfp;
	struct preloaded_file	*xp;
	struct file_metadata	*md;
	struct bootinfo		*bip;
	vm_offset_t		kernend;
	vm_offset_t		addr;
	vm_offset_t		envp;
	vm_offset_t		size;
	vm_offset_t		vaddr;
	vm_offset_t		dtbp;
	char			*rootdevname;
	int			howto;
	int			i;

	/*
	 * These metadata addreses must be converted for kernel after
	 * relocation.
	 */
	uint32_t		mdt[] = {
	    MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND,
	    MODINFOMD_ENVP,
#if defined(LOADER_FDT_SUPPORT)
	    MODINFOMD_DTBP
#endif
	};

	howto = md_getboothowto(args);

	/*
	 * Allow the environment variable 'rootdev' to override the supplied
	 * device. This should perhaps go to MI code and/or have $rootdev
	 * tested/set by MI code before launching the kernel.
	 */
	rootdevname = getenv("rootdev");
	if (rootdevname == NULL)
		rootdevname = getenv("currdev");
	/* Try reading the /etc/fstab file to select the root device */
	getrootmount(rootdevname);

	/* Find the last module in the chain */
	addr = 0;
	for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
		if (addr < (xp->f_addr + xp->f_size))
			addr = xp->f_addr + xp->f_size;
	}
	/* Pad to a page boundary */
	addr = roundup(addr, PAGE_SIZE);

	/* Copy our environment */
	envp = addr;
	addr = md_copyenv(addr);

	/* Pad to a page boundary */
	addr = roundup(addr, PAGE_SIZE);

	kernend = 0;
	kfp = file_findfile(NULL, "elf32 kernel");
	if (kfp == NULL)
		kfp = file_findfile(NULL, "elf kernel");
	if (kfp == NULL)
		panic("can't find kernel file");
	file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);

#if defined(LOADER_FDT_SUPPORT)
	/* Handle device tree blob */
	dtbp = fdt_fixup();
	if (dtbp != 0)
		file_addmetadata(kfp, MODINFOMD_DTBP, sizeof dtbp, &dtbp);
	else
		pager_output("WARNING! Trying to fire up the kernel, but no "
		    "device tree blob found!\n");
#endif

	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);

	/* Figure out the size and location of the metadata */
	*modulep = addr;
	size = md_copymodules(0);
	kernend = roundup(addr + size, PAGE_SIZE);

	/* Provide MODINFOMD_KERNEND */
	md = file_findmetadata(kfp, MODINFOMD_KERNEND);
	bcopy(&kernend, md->md_data, sizeof kernend);

	/* Convert addresses to the final VA */
	*modulep -= __elfN(relocation_offset);

	for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) {
		md = file_findmetadata(kfp, mdt[i]);
		if (md) {
			bcopy(md->md_data, &vaddr, sizeof vaddr);
			vaddr -= __elfN(relocation_offset);
			bcopy(&vaddr, md->md_data, sizeof vaddr);
		}
	}

	/* Only now copy actual modules and metadata */
	(void)md_copymodules(addr);

	return (0);
}