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).
This commit is contained in:
Ian Lepore 2014-02-22 19:10:58 +00:00
parent f438547338
commit d000dd2f86

View File

@ -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_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(bfp->f_addr) == 0) {
printf("Using DTB from loaded file.\n");
return (0);
}
}
/* Board vendors use both fdtaddr and fdt_addr names. Grrrr. */
/* If we were given the address of a valid blob in memory, use it. */
if (fdt_to_load != NULL) {
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);
}
}
/*
* 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) {
if (fdt_load_dtb(va) == 0) {
printf("Using DTB compiled into kernel.\n");
return (0);
}
}
if ((va = fdt_find_static_dtb()) != 0) {
printf("Using DTB compiled into kernel.\n");
return (fdt_load_dtb(va));
}
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) {