diff options
author | ian <ian@FreeBSD.org> | 2014-04-29 00:31:32 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2014-04-29 00:31:32 +0000 |
commit | 56bd016e78c171de47b7f9450975ea51cf694d43 (patch) | |
tree | fd44f38b9dfb8c157dc3d4abf88b4a8296d79ba5 /sys | |
parent | 4793c2eddbeb682d91f9d25dc10744080c2c44bd (diff) | |
download | FreeBSD-src-56bd016e78c171de47b7f9450975ea51cf694d43.zip FreeBSD-src-56bd016e78c171de47b7f9450975ea51cf694d43.tar.gz |
MFC r262340, r262345, r262347, find and load an appropriate dtb file.
The search order for a usable dtb in fdt_setup_fdtp() is now
- A dtb loaded with an explicit "load -t dtb" command.
- A dtb already loaded into memory somehow[*] and pointed to by fdt_to_load.
- A dtb in the memory pointed to by the u-boot env vars fdtaddr or fdt_addr.
- A file named by the u-boot env vars fdtfile or fdt_file.
- A static dtb compiled into the kernel.
* Presumably by some arch-specific command or code.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/boot/common/bootstrap.h | 1 | ||||
-rw-r--r-- | sys/boot/common/module.c | 19 | ||||
-rw-r--r-- | sys/boot/fdt/fdt_loader_cmd.c | 95 |
3 files changed, 91 insertions, 24 deletions
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index 516b8a5..c9bcc52 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -233,6 +233,7 @@ int mod_loadkld(const char *name, int argc, char *argv[]); struct preloaded_file *file_alloc(void); struct preloaded_file *file_findfile(char *name, char *type); struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type); +struct preloaded_file *file_loadraw(char *name, char *type); void file_discard(struct preloaded_file *fp); void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index e450fbd..cea01c0 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -52,7 +52,6 @@ struct moduledir { }; static int file_load(char *filename, vm_offset_t dest, struct preloaded_file **result); -static int file_loadraw(char *type, char *name); static int file_load_dependencies(struct preloaded_file *base_mod); static char * file_search(const char *name, char **extlist); static struct kernel_module * file_findmodule(struct preloaded_file *fp, char *modname, struct mod_depend *verinfo); @@ -134,7 +133,7 @@ command_load(int argc, char *argv[]) command_errmsg = "invalid load type"; return(CMD_ERROR); } - return(file_loadraw(typestr, argv[1])); + return(file_loadraw(argv[1], typestr) ? CMD_OK : CMD_ERROR); } /* * Do we have explicit KLD load ? @@ -189,7 +188,7 @@ command_load_geli(int argc, char *argv[]) argv += (optind - 1); argc -= (optind - 1); sprintf(typestr, "%s:geli_keyfile%d", argv[1], num); - return(file_loadraw(typestr, argv[2])); + return(file_loadraw(argv[2], typestr) ? CMD_OK : CMD_ERROR); } COMMAND_SET(unload, "unload", "unload all modules", command_unload); @@ -357,8 +356,8 @@ file_load_dependencies(struct preloaded_file *base_file) * We've been asked to load (name) as (type), so just suck it in, * no arguments or anything. */ -int -file_loadraw(char *type, char *name) +struct preloaded_file * +file_loadraw(char *name, char *type) { struct preloaded_file *fp; char *cp; @@ -368,21 +367,21 @@ file_loadraw(char *type, char *name) /* We can't load first */ if ((file_findfile(NULL, NULL)) == NULL) { command_errmsg = "can't load file before kernel"; - return(CMD_ERROR); + return(NULL); } /* locate the file on the load path */ cp = file_search(name, NULL); if (cp == NULL) { sprintf(command_errbuf, "can't find '%s'", name); - return(CMD_ERROR); + return(NULL); } name = cp; if ((fd = open(name, O_RDONLY)) < 0) { sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno)); free(name); - return(CMD_ERROR); + return(NULL); } if (archsw.arch_loadaddr != NULL) @@ -398,7 +397,7 @@ file_loadraw(char *type, char *name) sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno)); free(name); close(fd); - return(CMD_ERROR); + return(NULL); } laddr += got; } @@ -419,7 +418,7 @@ file_loadraw(char *type, char *name) /* Add to the list of loaded files */ file_insert_tail(fp); close(fd); - return(CMD_OK); + return(fp); } /* diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c index d8ad942..1d74d62 100644 --- a/sys/boot/fdt/fdt_loader_cmd.c +++ b/sys/boot/fdt/fdt_loader_cmd.c @@ -128,6 +128,8 @@ fdt_find_static_dtb() char *strp; int i, sym_count; + debugf("fdt_find_static_dtb()\n"); + sym_count = symtab = strtab = 0; strp = NULL; @@ -189,6 +191,8 @@ fdt_load_dtb(vm_offset_t va) struct fdt_header header; int err; + debugf("fdt_load_dtb(0x%08jx)\n", (uintmax_t)va); + COPYOUT(va, &header, sizeof(header)); err = fdt_check_header(&header); if (err < 0) { @@ -229,6 +233,8 @@ fdt_load_dtb_addr(struct fdt_header *header) { int err; + debugf("fdt_load_dtb_addr(0x%p)\n", header); + fdtp_size = fdt_totalsize(header); err = fdt_check_header(header); if (err < 0) { @@ -248,6 +254,32 @@ fdt_load_dtb_addr(struct fdt_header *header) } static int +fdt_load_dtb_file(const char * filename) +{ + struct preloaded_file *bfp, *oldbfp; + int err; + + debugf("fdt_load_dtb_file(%s)\n", filename); + + oldbfp = file_findfile(NULL, "dtb"); + + /* Attempt to load and validate a new dtb from a file. */ + if ((bfp = file_loadraw(filename, "dtb")) == NULL) { + sprintf(command_errbuf, "failed to load file '%s'", filename); + return (1); + } + if ((err = fdt_load_dtb(bfp->f_addr)) != 0) { + file_discard(bfp); + return (err); + } + + /* A new dtb was validated, discard any previous file. */ + if (oldbfp) + file_discard(oldbfp); + return (0); +} + +static int fdt_setup_fdtp() { struct preloaded_file *bfp; @@ -256,35 +288,68 @@ fdt_setup_fdtp() char *p; vm_offset_t va; + debugf("fdt_setup_fdtp()\n"); + + /* If we already loaded a file, use it. */ if ((bfp = file_findfile(NULL, "dtb")) != NULL) { - printf("Using DTB from loaded file.\n"); - return fdt_load_dtb(bfp->f_addr); + if (fdt_load_dtb(bfp->f_addr) == 0) { + printf("Using DTB from loaded file '%s'.\n", + bfp->f_name); + return (0); + } } - + + /* If we were given the address of a valid blob in memory, use it. */ if (fdt_to_load != NULL) { - printf("Using DTB from memory address 0x%08X.\n", - (unsigned int)fdt_to_load); - return fdt_load_dtb_addr(fdt_to_load); + if (fdt_load_dtb_addr(fdt_to_load) == 0) { + printf("Using DTB from memory address 0x%08X.\n", + (unsigned int)fdt_to_load); + return (0); + } } - /* Board vendors use both fdtaddr and fdt_addr names. Grrrr. */ + /* + * If the U-boot environment contains a variable giving the address of a + * valid blob in memory, use it. Board vendors use both fdtaddr and + * fdt_addr names. + */ s = ub_env_get("fdtaddr"); if (s == NULL) s = ub_env_get("fdt_addr"); if (s != NULL && *s != '\0') { hdr = (struct fdt_header *)strtoul(s, &p, 16); if (*p == '\0') { - printf("Using DTB provided by U-Boot.\n"); - return fdt_load_dtb_addr(hdr); + if (fdt_load_dtb_addr(hdr) == 0) { + printf("Using DTB provided by U-Boot at " + "address 0x%p.\n", hdr); + return (0); + } } } - + + /* + * If the U-boot environment contains a variable giving the name of a + * file, use it if we can load and validate it. + */ + s = ub_env_get("fdtfile"); + if (s == NULL) + s = ub_env_get("fdt_file"); + if (s != NULL && *s != '\0') { + if (fdt_load_dtb_file(s) == 0) { + printf("Loaded DTB from file '%s'.\n", s); + return (0); + } + } + + /* If there is a dtb compiled into the kernel, use it. */ if ((va = fdt_find_static_dtb()) != 0) { - printf("Using DTB compiled into kernel.\n"); - return (fdt_load_dtb(va)); + if (fdt_load_dtb(va) == 0) { + printf("Using DTB compiled into kernel.\n"); + return (0); + } } - command_errmsg = "no device tree blob found!"; + command_errmsg = "No device tree blob found!\n"; return (1); } @@ -678,6 +743,8 @@ fdt_fixup(void) ethstr = NULL; len = 0; + debugf("fdt_fixup()\n"); + if (fdtp == NULL && fdt_setup_fdtp() != 0) return (0); @@ -741,7 +808,7 @@ 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) { |