summaryrefslogtreecommitdiffstats
path: root/sys/boot/fdt/fdt_loader_cmd.c
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-02-22 19:10:58 +0000
committerian <ian@FreeBSD.org>2014-02-22 19:10:58 +0000
commitf9012da3847fff7a5c4b095adf8899aebb5c0d79 (patch)
tree8703d7b07c6b37ac5c915cc2fcf215d15433af7a /sys/boot/fdt/fdt_loader_cmd.c
parentebe945ff9f2ff29bb83930550f210cdab9fae7e7 (diff)
downloadFreeBSD-src-f9012da3847fff7a5c4b095adf8899aebb5c0d79.zip
FreeBSD-src-f9012da3847fff7a5c4b095adf8899aebb5c0d79.tar.gz
Change fdt_setup_fdtp() from "guess then fail" to more probe-like behavior.
The old code basically said it was going to use some particular blob without knowing whether it could successfully do so, then it would invoke the function to do that and return its status. If it failed, you were done, even if other blobs might be available. Now the code attempts to use some particular blob and if that succeeds it says so and returns success, otherwise it moves on to try another potential blob. One specific problem this solves is when u-boot sets an fdtaddr variable to point to some memory address, then doesn't actually load a blob at that address. Now the header check will fail, and the code will move on to the fallback dtb compiled into the kernel (if any).
Diffstat (limited to 'sys/boot/fdt/fdt_loader_cmd.c')
-rw-r--r--sys/boot/fdt/fdt_loader_cmd.c55
1 files changed, 41 insertions, 14 deletions
diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c
index d8ad942..b553a85 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) {
@@ -252,39 +258,58 @@ fdt_setup_fdtp()
{
struct preloaded_file *bfp;
struct fdt_header *hdr;
+ int err;
const char *s;
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.\n");
+ 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%08X.\n", hdr);
+ 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 +703,8 @@ fdt_fixup(void)
ethstr = NULL;
len = 0;
+ debugf("fdt_fixup()\n");
+
if (fdtp == NULL && fdt_setup_fdtp() != 0)
return (0);
@@ -741,7 +768,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) {
OpenPOWER on IntegriCloud