summaryrefslogtreecommitdiffstats
path: root/sys/boot/uboot
diff options
context:
space:
mode:
authorandrew <andrew@FreeBSD.org>2014-11-01 17:12:44 +0000
committerandrew <andrew@FreeBSD.org>2014-11-01 17:12:44 +0000
commit2b36711b7857337942c3a4a579451a49491e3db2 (patch)
treeb2eda9c3d489687e9caaec4068e0ceef99190fc0 /sys/boot/uboot
parent9e8b5d9f18c4a511536a0cf4ad5d1528d933abba (diff)
downloadFreeBSD-src-2b36711b7857337942c3a4a579451a49491e3db2.zip
FreeBSD-src-2b36711b7857337942c3a4a579451a49491e3db2.tar.gz
Start to allow platforms other than U-Boot to use the FDT code in loader by
moving U-Boot specific code from libfdt.a to a new libuboot_fdt.a. This needs to be a new library for linking to work correctly. Differential Revision: https://reviews.freebsd.org/D1054 Reviewed by: ian, rpaulo (earlier version) MFC after: 1 week
Diffstat (limited to 'sys/boot/uboot')
-rw-r--r--sys/boot/uboot/Makefile6
-rw-r--r--sys/boot/uboot/fdt/Makefile33
-rw-r--r--sys/boot/uboot/fdt/uboot_fdt.c181
3 files changed, 220 insertions, 0 deletions
diff --git a/sys/boot/uboot/Makefile b/sys/boot/uboot/Makefile
index 1116ee6..43b5748 100644
--- a/sys/boot/uboot/Makefile
+++ b/sys/boot/uboot/Makefile
@@ -1,5 +1,11 @@
# $FreeBSD$
+.include <src.opts.mk>
+
SUBDIR= lib
+.if ${MK_FDT} != "no"
+SUBDIR+=fdt
+.endif
+
.include <bsd.subdir.mk>
diff --git a/sys/boot/uboot/fdt/Makefile b/sys/boot/uboot/fdt/Makefile
new file mode 100644
index 0000000..f739fa4
--- /dev/null
+++ b/sys/boot/uboot/fdt/Makefile
@@ -0,0 +1,33 @@
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+.PATH: ${.CURDIR}/../../common
+
+LIB= uboot_fdt
+INTERNALLIB=
+WARNS?= 2
+
+SRCS= uboot_fdt.c
+
+CFLAGS+= -ffreestanding -msoft-float
+
+CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
+
+# U-Boot library headers
+CFLAGS+= -I${.CURDIR}/../lib
+
+# libfdt headers
+CFLAGS+= -I${.CURDIR}/../../fdt
+
+# Pick up the bootstrap header for some interface items
+CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../../.. -I.
+
+machine:
+ ln -sf ${.CURDIR}/../../../${MACHINE_CPUARCH}/include machine
+
+CLEANFILES+= machine
+
+.include <bsd.lib.mk>
+
+beforedepend ${OBJS}: machine
diff --git a/sys/boot/uboot/fdt/uboot_fdt.c b/sys/boot/uboot/fdt/uboot_fdt.c
new file mode 100644
index 0000000..3765242
--- /dev/null
+++ b/sys/boot/uboot/fdt/uboot_fdt.c
@@ -0,0 +1,181 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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 <sys/param.h>
+#include <stand.h>
+#include <fdt_platform.h>
+
+#include "glue.h"
+
+#define STR(number) #number
+#define STRINGIFY(number) STR(number)
+
+int
+fdt_platform_load_dtb(void)
+{
+ struct fdt_header *hdr;
+ const char *s;
+ char *p;
+
+ /*
+ * If the U-boot environment contains a variable giving the address of a
+ * valid blob in memory, use it. The U-boot README says the right
+ * variable for fdt data loaded into ram is fdt_addr_r, so try that
+ * first. Board vendors also use both fdtaddr and fdt_addr names.
+ */
+ s = ub_env_get("fdt_addr_r");
+ if (s == NULL)
+ 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') {
+ if (fdt_load_dtb_addr(hdr) == 0) {
+ printf("Using DTB provided by U-Boot at "
+ "address %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);
+ }
+ }
+
+ return (1);
+}
+
+void
+fdt_platform_fixups(void)
+{
+ struct fdt_mem_region regions[3];
+ const char *env, *str;
+ char *end, *ethstr;
+ int eth_no, i, len, n;
+ struct sys_info *si;
+
+ env = NULL;
+ eth_no = 0;
+ ethstr = NULL;
+
+ /* Acquire sys_info */
+ si = ub_get_sys_info();
+
+ while ((env = ub_env_enum(env)) != NULL) {
+ if (strncmp(env, "eth", 3) == 0 &&
+ strncmp(env + (strlen(env) - 4), "addr", 4) == 0) {
+ /*
+ * Handle Ethernet addrs: parse uboot env eth%daddr
+ */
+
+ if (!eth_no) {
+ /*
+ * Check how many chars we will need to store
+ * maximal eth iface number.
+ */
+ len = strlen(STRINGIFY(TMP_MAX_ETH)) +
+ strlen("ethernet") + 1;
+
+ /*
+ * Reserve mem for string "ethernet" and len
+ * chars for iface no.
+ */
+ ethstr = (char *)malloc(len * sizeof(char));
+ bzero(ethstr, len * sizeof(char));
+ strcpy(ethstr, "ethernet0");
+ }
+
+ /* Extract interface number */
+ i = strtol(env + 3, &end, 10);
+ if (end == (env + 3))
+ /* 'ethaddr' means interface 0 address */
+ n = 0;
+ else
+ n = i;
+
+ if (n > TMP_MAX_ETH)
+ continue;
+
+ str = ub_env_get(env);
+
+ if (n != 0) {
+ /*
+ * Find the lenght of the interface id by
+ * taking in to account the first 3 and
+ * last 4 characters.
+ */
+ i = strlen(env) - 7;
+ strncpy(ethstr + 8, env + 3, i);
+ }
+
+ /* Modify blob */
+ fdt_fixup_ethernet(str, ethstr, len);
+
+ /* Clear ethernet..XXXX.. string */
+ bzero(ethstr + 8, len - 8);
+
+ if (n + 1 > eth_no)
+ eth_no = n + 1;
+ } else if (strcmp(env, "consoledev") == 0) {
+ str = ub_env_get(env);
+ fdt_fixup_stdout(str);
+ }
+ }
+
+ /* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */
+ fdt_fixup_cpubusfreqs(si->clk_cpu, si->clk_bus);
+
+ /* Copy the data into a useful form */
+ for (i = 0; i < si->mr_no; i++) {
+ if (i > nitems(regions)) {
+ i = nitems(regions);
+ break;
+ }
+
+ regions[i].start = si->mr[i].start;
+ regions[i].size = si->mr[i].size;
+ }
+
+ /* Fixup memory regions */
+ fdt_fixup_memory(regions, i);
+}
OpenPOWER on IntegriCloud