summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Tymoshenko <gonzo@FreeBSD.org>2016-04-29 22:42:59 +0000
committerOleksandr Tymoshenko <gonzo@FreeBSD.org>2016-04-29 22:42:59 +0000
commit26f47fdd8ffecbef5f4e5892b4cb5f4553ad20ce (patch)
treefc50628fd285f565447ba4cf2386d96dd76d07f7
parent9f7f2d8f89c34d9ce652421b483f76c0cf9bb437 (diff)
Notes
-rw-r--r--sys/boot/fdt/Makefile2
-rw-r--r--sys/boot/fdt/fdt_loader_cmd.c123
-rw-r--r--sys/boot/fdt/fdt_overlay.c438
-rw-r--r--sys/boot/fdt/fdt_overlay.h34
-rw-r--r--sys/boot/fdt/fdt_platform.h2
-rw-r--r--sys/boot/uboot/fdt/uboot_fdt.c20
6 files changed, 616 insertions, 3 deletions
diff --git a/sys/boot/fdt/Makefile b/sys/boot/fdt/Makefile
index 22d8da59655e8..ce11dbb42f841 100644
--- a/sys/boot/fdt/Makefile
+++ b/sys/boot/fdt/Makefile
@@ -10,7 +10,7 @@ SRCS+= fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c \
fdt_empty_tree.c
# Loader's fdt commands extension sources.
-SRCS+= fdt_loader_cmd.c
+SRCS+= fdt_loader_cmd.c fdt_overlay.c
CFLAGS+= -I${.CURDIR}/../../contrib/libfdt/ -I${.CURDIR}/../common/
diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c
index 8cd8ab50150e8..6983a599a5d03 100644
--- a/sys/boot/fdt/fdt_loader_cmd.c
+++ b/sys/boot/fdt/fdt_loader_cmd.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include "bootstrap.h"
#include "fdt_platform.h"
+#include "fdt_overlay.h"
#ifdef DEBUG
#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
@@ -276,6 +277,128 @@ fdt_load_dtb_file(const char * filename)
return (0);
}
+static int
+fdt_load_dtb_overlay(const char * filename)
+{
+ struct preloaded_file *bfp, *oldbfp;
+ struct fdt_header header;
+ int err;
+
+ debugf("fdt_load_dtb_overlay(%s)\n", filename);
+
+ oldbfp = file_findfile(filename, "dtbo");
+
+ /* Attempt to load and validate a new dtb from a file. */
+ if ((bfp = file_loadraw(filename, "dtbo", 1)) == NULL) {
+ printf("failed to load file '%s'\n", filename);
+ return (1);
+ }
+
+ COPYOUT(bfp->f_addr, &header, sizeof(header));
+ err = fdt_check_header(&header);
+
+ if (err < 0) {
+ file_discard(bfp);
+ if (err == -FDT_ERR_BADVERSION)
+ printf("incompatible blob version: %d, should be: %d\n",
+ fdt_version(fdtp), FDT_LAST_SUPPORTED_VERSION);
+
+ else
+ printf("error validating blob: %s\n",
+ fdt_strerror(err));
+ return (1);
+ }
+
+ /* A new dtb was validated, discard any previous file. */
+ if (oldbfp)
+ file_discard(oldbfp);
+
+ return (0);
+}
+
+int
+fdt_load_dtb_overlays(const char * filenames)
+{
+ char *names;
+ char *name;
+ char *comaptr;
+
+ debugf("fdt_load_dtb_overlay(%s)\n", filenames);
+
+ names = strdup(filenames);
+ if (names == NULL)
+ return (1);
+ name = names;
+ do {
+ comaptr = strchr(name, ',');
+ if (comaptr)
+ *comaptr = '\0';
+ fdt_load_dtb_overlay(name);
+ name = comaptr + 1;
+ } while(comaptr);
+
+ free(names);
+ return (0);
+}
+
+void
+fdt_apply_overlays()
+{
+ struct preloaded_file *fp;
+ size_t overlays_size, max_overlay_size, new_fdtp_size;
+ void *new_fdtp;
+ void *overlay;
+ int rv;
+
+ if ((fdtp == NULL) || (fdtp_size == 0))
+ return;
+
+ overlays_size = 0;
+ max_overlay_size = 0;
+ for (fp = file_findfile(NULL, "dtbo"); fp != NULL; fp = fp->f_next) {
+ if (max_overlay_size < fp->f_size)
+ max_overlay_size = fp->f_size;
+ overlays_size += fp->f_size;
+ }
+
+ /* Nothing to apply */
+ if (overlays_size == 0)
+ return;
+
+ /* It's actually more than enough */
+ new_fdtp_size = fdtp_size + overlays_size;
+ new_fdtp = malloc(new_fdtp_size);
+ if (new_fdtp == NULL) {
+ printf("failed to allocate memory for DTB blob with overlays\n");
+ return;
+ }
+
+ overlay = malloc(max_overlay_size);
+ if (overlay == NULL) {
+ printf("failed to allocate memory for DTB blob with overlays\n");
+ free(new_fdtp);
+ return;
+ }
+
+ rv = fdt_open_into(fdtp, new_fdtp, new_fdtp_size);
+ if (rv != 0) {
+ printf("failed to open DTB blob for applying overlays\n");
+ return;
+ }
+
+ for (fp = file_findfile(NULL, "dtbo"); fp != NULL; fp = fp->f_next) {
+ printf("applying DTB overlay '%s'\n", fp->f_name);
+ COPYOUT(fp->f_addr, overlay, fp->f_size);
+ fdt_overlay_apply(new_fdtp, overlay, fp->f_size);
+ }
+
+ free(fdtp);
+ fdtp = new_fdtp;
+ fdtp_size = new_fdtp_size;
+
+ free(overlay);
+}
+
int
fdt_setup_fdtp()
{
diff --git a/sys/boot/fdt/fdt_overlay.c b/sys/boot/fdt/fdt_overlay.c
new file mode 100644
index 0000000000000..a19f06e8e9477
--- /dev/null
+++ b/sys/boot/fdt/fdt_overlay.c
@@ -0,0 +1,438 @@
+/*-
+ * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <libfdt.h>
+
+#include "fdt_overlay.h"
+
+/*
+ * Get max phandle
+ */
+static uint32_t
+fdt_max_phandle(void *fdtp)
+{
+ int o, depth;
+ uint32_t max_phandle, phandle;
+
+ depth = 1;
+ o = fdt_path_offset(fdtp, "/");
+ max_phandle = fdt_get_phandle(fdtp, o);
+ for (depth = 0; (o >= 0) && (depth >= 0); o = fdt_next_node(fdtp, o, &depth)) {
+ phandle = fdt_get_phandle(fdtp, o);
+ if (max_phandle < phandle)
+ max_phandle = phandle;
+ }
+
+ return max_phandle;
+}
+
+/*
+ * Returns exact memory location specified by fixup in format
+ * /path/to/node:property:offset
+ */
+static void *
+fdt_get_fixup_location(void *fdtp, const char *fixup)
+{
+ char *path, *prop, *offsetp, *endp;
+ int prop_offset, o, proplen;
+ void *result;
+
+ result = 0;
+
+ path = strdup(fixup);
+ prop = strchr(path, ':');
+ if (prop == NULL) {
+ printf("missing property part in \"%s\"\n", fixup);
+ result = NULL;
+ goto out;
+ }
+
+ *prop = 0;
+ prop++;
+
+ offsetp = strchr(prop, ':');
+ if (offsetp == NULL) {
+ printf("missing offset part in \"%s\"\n", fixup);
+ result = NULL;
+ goto out;
+ }
+
+ *offsetp = 0;
+ offsetp++;
+
+ prop_offset = strtoul(offsetp, &endp, 10);
+ if (*endp != '\0') {
+ printf("\"%s\" is not valid number\n", offsetp);
+ result = NULL;
+ goto out;
+ }
+
+ o = fdt_path_offset(fdtp, path);
+ if (o < 0) {
+ printf("path \"%s\" not found\n", path);
+ result = NULL;
+ goto out;
+ }
+
+ result = fdt_getprop_w(fdtp, o, prop, &proplen);
+ if (result == NULL){
+ printf("property \"%s\" not found in \"%s\" node\n", prop, path);
+ result = NULL;
+ goto out;
+ }
+
+ if (proplen < prop_offset + sizeof(uint32_t)) {
+ printf("%s: property length is too small for fixup\n", fixup);
+ result = NULL;
+ goto out;
+ }
+
+ result = (char*)result + prop_offset;
+
+out:
+ free(path);
+ return (result);
+}
+
+/*
+ * Process one entry in __fixups__ { } node
+ * @fixups is property value, array of NUL-terminated strings
+ * with fixup locations
+ * @fixups_len length of the fixups array in bytes
+ * @phandle is value for these locations
+ */
+static int
+fdt_do_one_fixup(void *fdtp, const char *fixups, int fixups_len, int phandle)
+{
+ void *fixup_pos;
+ uint32_t val;
+
+ val = cpu_to_fdt32(phandle);
+
+ while (fixups_len > 0) {
+ fixup_pos = fdt_get_fixup_location(fdtp, fixups);
+ if (fixup_pos != NULL)
+ memcpy(fixup_pos, &val, sizeof(val));
+
+ fixups_len -= strlen(fixups) + 1;
+ fixups += strlen(fixups) + 1;
+ }
+
+ return (0);
+}
+
+/*
+ * Increase u32 value at pos by offset
+ */
+static void
+fdt_increase_u32(void *pos, uint32_t offset)
+{
+ uint32_t val;
+
+ memcpy(&val, pos, sizeof(val));
+ val = cpu_to_fdt32(fdt32_to_cpu(val) + offset);
+ memcpy(pos, &val, sizeof(val));
+}
+
+/*
+ * Process local fixups
+ * @fixups is property value, array of NUL-terminated strings
+ * with fixup locations
+ * @fixups_len length of the fixups array in bytes
+ * @offset value these locations should be increased by
+ */
+static int
+fdt_do_local_fixup(void *fdtp, const char *fixups, int fixups_len, int offset)
+{
+ void *fixup_pos;
+
+ while (fixups_len > 0) {
+ fixup_pos = fdt_get_fixup_location(fdtp, fixups);
+ if (fixup_pos != NULL)
+ fdt_increase_u32(fixup_pos, offset);
+
+ fixups_len -= strlen(fixups) + 1;
+ fixups += strlen(fixups) + 1;
+ }
+
+ return (0);
+}
+
+/*
+ * Increase node phandle by phandle_offset
+ */
+static void
+fdt_increase_phandle(void *fdtp, int node_offset, uint32_t phandle_offset)
+{
+ int proplen;
+ void *phandle_pos, *node_pos;
+
+ node_pos = (char*)fdtp + node_offset;
+
+ phandle_pos = fdt_getprop_w(fdtp, node_offset, "phandle", &proplen);
+ if (phandle_pos)
+ fdt_increase_u32(phandle_pos, phandle_offset);
+ phandle_pos = fdt_getprop_w(fdtp, node_offset, "linux,phandle", &proplen);
+ if (phandle_pos)
+ fdt_increase_u32(phandle_pos, phandle_offset);
+}
+
+/*
+ * Increase all phandles by offset
+ */
+static void
+fdt_increase_phandles(void *fdtp, uint32_t offset)
+{
+ int o, depth;
+
+ o = fdt_path_offset(fdtp, "/");
+ for (depth = 0; (o >= 0) && (depth >= 0); o = fdt_next_node(fdtp, o, &depth)) {
+ fdt_increase_phandle(fdtp, o, offset);
+ }
+}
+
+/*
+ * Overlay one node defined by <overlay_fdtp, overlay_o> over <main_fdtp, target_o>
+ */
+static void
+fdt_overlay_node(void *main_fdtp, int target_o, void *overlay_fdtp, int overlay_o)
+{
+ int len, o, depth;
+ const char *name;
+ const void *val;
+ int target_subnode_o;
+
+ /* Overlay properties */
+ for (o = fdt_first_property_offset(overlay_fdtp, overlay_o);
+ o >= 0; o = fdt_next_property_offset(overlay_fdtp, o)) {
+ val = fdt_getprop_by_offset(overlay_fdtp, o, &name, &len);
+ if (val)
+ fdt_setprop(main_fdtp, target_o, name, val, len);
+ }
+
+ /* Now overlay nodes */
+ o = overlay_o;
+ for (depth = 0; (o >= 0) && (depth >= 0);
+ o = fdt_next_node(overlay_fdtp, o, &depth)) {
+ if (depth != 1)
+ continue;
+ /* Check if there is node with the same name */
+ name = fdt_get_name(overlay_fdtp, o, NULL);
+ target_subnode_o = fdt_subnode_offset(main_fdtp, target_o, name);
+ if (target_subnode_o < 0) {
+ /* create new subnode and run merge recursively */
+ target_subnode_o = fdt_add_subnode(main_fdtp, target_o, name);
+ if (target_subnode_o < 0) {
+ printf("failed to create subnode \"%s\": %d\n",
+ name, target_subnode_o);
+ return;
+ }
+ }
+
+ fdt_overlay_node(main_fdtp, target_subnode_o,
+ overlay_fdtp, o);
+ }
+}
+
+/*
+ * Apply one overlay fragment
+ */
+static void
+fdt_apply_fragment(void *main_fdtp, void *overlay_fdtp, int fragment_o)
+{
+ uint32_t target;
+ const char *target_path;
+ const void *val;
+ int target_node_o, overlay_node_o;
+
+ target_node_o = -1;
+ val = fdt_getprop(overlay_fdtp, fragment_o, "target", NULL);
+ if (val) {
+ memcpy(&target, val, sizeof(target));
+ target = fdt32_to_cpu(target);
+ target_node_o = fdt_node_offset_by_phandle(main_fdtp, target);
+ if (target_node_o < 0) {
+ printf("failed to find target %04x\n", target);
+ return;
+ }
+ }
+
+ if (target_node_o < 0) {
+ target_path = fdt_getprop(overlay_fdtp, fragment_o, "target-path", NULL);
+ if (target_path == NULL)
+ return;
+
+ target_node_o = fdt_path_offset(main_fdtp, target_path);
+ if (target_node_o < 0) {
+ printf("failed to find target-path %s\n", target_path);
+ return;
+ }
+ }
+
+ if (target_node_o < 0)
+ return;
+
+ overlay_node_o = fdt_subnode_offset(overlay_fdtp, fragment_o, "__overlay__");
+ if (overlay_node_o < 0) {
+ printf("missing __overlay__ sub-node\n");
+ return;
+ }
+
+ fdt_overlay_node(main_fdtp, target_node_o, overlay_fdtp, overlay_node_o);
+}
+
+/*
+ * Handle __fixups__ node in overlay DTB
+ */
+static int
+fdt_overlay_do_fixups(void *main_fdtp, void *overlay_fdtp)
+{
+ int main_symbols_o, symbol_o, overlay_fixups_o;
+ int fixup_prop_o;
+ int len;
+ const char *fixups, *name;
+ const char *symbol_path;
+ uint32_t phandle;
+
+ main_symbols_o = fdt_path_offset(main_fdtp, "/__symbols__");
+ overlay_fixups_o = fdt_path_offset(overlay_fdtp, "/__fixups__");
+
+ if (main_symbols_o < 0)
+ return (-1);
+ if (overlay_fixups_o < 0)
+ return (-1);
+
+ for (fixup_prop_o = fdt_first_property_offset(overlay_fdtp, overlay_fixups_o);
+ fixup_prop_o >= 0;
+ fixup_prop_o = fdt_next_property_offset(overlay_fdtp, fixup_prop_o)) {
+ fixups = fdt_getprop_by_offset(overlay_fdtp, fixup_prop_o, &name, &len);
+ symbol_path = fdt_getprop(main_fdtp, main_symbols_o, name, NULL);
+ if (symbol_path == NULL) {
+ printf("couldn't find \"%s\" symbol in main dtb\n", name);
+ return (-1);
+ }
+ symbol_o = fdt_path_offset(main_fdtp, symbol_path);
+ if (symbol_o < 0) {
+ printf("couldn't find \"%s\" path in main dtb\n", symbol_path);
+ return (-1);
+ }
+ phandle = fdt_get_phandle(main_fdtp, symbol_o);
+ if (fdt_do_one_fixup(overlay_fdtp, fixups, len, phandle) < 0)
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Handle __local_fixups__ node in overlay DTB
+ */
+static int
+fdt_overlay_do_local_fixups(void *main_fdtp, void *overlay_fdtp)
+{
+ int overlay_local_fixups_o;
+ int len;
+ const char *fixups;
+ uint32_t phandle_offset;
+
+ overlay_local_fixups_o = fdt_path_offset(overlay_fdtp, "/__local_fixups__");
+
+ if (overlay_local_fixups_o < 0)
+ return (-1);
+
+ phandle_offset = fdt_max_phandle(main_fdtp);
+ fdt_increase_phandles(overlay_fdtp, phandle_offset);
+ fixups = fdt_getprop_w(overlay_fdtp, overlay_local_fixups_o, "fixup", &len);
+ if (fixups) {
+ if (fdt_do_local_fixup(overlay_fdtp, fixups, len, phandle_offset) < 0)
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Apply all fragments to main DTB
+ */
+static int
+fdt_overlay_apply_fragments(void *main_fdtp, void *overlay_fdtp)
+{
+ int o, depth;
+
+ o = fdt_path_offset(overlay_fdtp, "/");
+ for (depth = 0; (o >= 0) && (depth >= 0); o = fdt_next_node(overlay_fdtp, o, &depth)) {
+ if (depth != 1)
+ continue;
+
+ fdt_apply_fragment(main_fdtp, overlay_fdtp, o);
+ }
+
+ return (0);
+}
+
+int
+fdt_overlay_apply(void *main_fdtp, void *overlay_fdtp, size_t overlay_length)
+{
+ void *overlay_copy;
+ int rv;
+
+ rv = 0;
+
+ /* We modify overlay in-place, so we need writable copy */
+ overlay_copy = malloc(overlay_length);
+ if (overlay_copy == NULL) {
+ printf("failed to allocate memory for overlay copy\n");
+ return (-1);
+ }
+
+ memcpy(overlay_copy, overlay_fdtp, overlay_length);
+
+ if (fdt_overlay_do_fixups(main_fdtp, overlay_copy) < 0) {
+ printf("failed to perform fixups in overlay\n");
+ rv = -1;
+ goto out;
+ }
+
+ if (fdt_overlay_do_local_fixups(main_fdtp, overlay_copy) < 0) {
+ printf("failed to perform local fixups in overlay\n");
+ rv = -1;
+ goto out;
+ }
+
+ if (fdt_overlay_apply_fragments(main_fdtp, overlay_copy) < 0) {
+ printf("failed to apply fragments\n");
+ rv = -1;
+ }
+
+out:
+ free(overlay_copy);
+
+ return (rv);
+}
diff --git a/sys/boot/fdt/fdt_overlay.h b/sys/boot/fdt/fdt_overlay.h
new file mode 100644
index 0000000000000..0f9134384d3c2
--- /dev/null
+++ b/sys/boot/fdt/fdt_overlay.h
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef FDT_OVERLAY_H
+#define FDT_OVERLAY_H
+
+int fdt_overlay_apply(void *main_fdtp, void *overlay_fdtp, size_t overlay_length);
+
+#endif /* FDT_OVERLAY_H */
diff --git a/sys/boot/fdt/fdt_platform.h b/sys/boot/fdt/fdt_platform.h
index cad760279b24d..eae940aab0303 100644
--- a/sys/boot/fdt/fdt_platform.h
+++ b/sys/boot/fdt/fdt_platform.h
@@ -43,8 +43,10 @@ void fdt_fixup_cpubusfreqs(unsigned long, unsigned long);
void fdt_fixup_ethernet(const char *, char *, int);
void fdt_fixup_memory(struct fdt_mem_region *, size_t);
void fdt_fixup_stdout(const char *);
+void fdt_apply_overlays(void);
int fdt_load_dtb_addr(struct fdt_header *);
int fdt_load_dtb_file(const char *);
+int fdt_load_dtb_overlays(const char *);
int fdt_setup_fdtp(void);
/* The platform library needs to implement these functions */
diff --git a/sys/boot/uboot/fdt/uboot_fdt.c b/sys/boot/uboot/fdt/uboot_fdt.c
index 6b646f63dc815..848d8594222ca 100644
--- a/sys/boot/uboot/fdt/uboot_fdt.c
+++ b/sys/boot/uboot/fdt/uboot_fdt.c
@@ -45,6 +45,7 @@ fdt_platform_load_dtb(void)
struct fdt_header *hdr;
const char *s;
char *p;
+ int rv;
/*
* If the U-boot environment contains a variable giving the address of a
@@ -68,6 +69,8 @@ fdt_platform_load_dtb(void)
}
}
+ rv = 1;
+
/*
* Try to get FDT filename first from loader env and then from u-boot env
*/
@@ -79,11 +82,21 @@ fdt_platform_load_dtb(void)
if (s != NULL && *s != '\0') {
if (fdt_load_dtb_file(s) == 0) {
printf("Loaded DTB from file '%s'.\n", s);
- return (0);
+ rv = 0;
}
}
- return (1);
+ if (rv == 0) {
+ s = getenv("fdt_overlays");
+ if (s == NULL)
+ s = ub_env_get("fdt_overlays");
+ if (s != NULL && *s != '\0') {
+ printf("Loading DTB overlays: '%s'\n", s);
+ fdt_load_dtb_overlays(s);
+ }
+ }
+
+ return (rv);
}
void
@@ -99,6 +112,9 @@ fdt_platform_fixups(void)
eth_no = 0;
ethstr = NULL;
+ /* Apply overlays before anything else */
+ fdt_apply_overlays();
+
/* Acquire sys_info */
si = ub_get_sys_info();