[RFC PATCH V2 9/9] appended dtbs works!

Jason Cooper jason at lakedaemon.net
Fri Aug 2 11:51:16 EDT 2013


With this commit, the user can build a single binary with the zImage
linked in and the dtbs appended.

The user needs to provide a board-*.c file, address of the uart, then:

  make MFG=boardname APPEND_KERNEL=/tmp/zImage APPEND_DTBS=/tmp/*.dtb \
	uImage

Look at board-raumfeld.c for an example of how to determine the board
you are on and set the desired compatible string.

Signed-off-by: Jason Cooper <jason at lakedaemon.net>
---
 Makefile          |  1 +
 board-dreamplug.c | 28 ++++++++++++++++++++++++
 board-raumfeld.c  | 49 ++++++++++++++++++++----------------------
 board.h           |  2 --
 dtbs.c            | 36 +++++++++++++++++++++++++++++++
 dtbs.h            |  6 ++++++
 endian.h          | 12 +++++++++++
 fdt.h             | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 string.c          | 10 +++++++++
 string.h          |  1 +
 types.h           |  1 +
 11 files changed, 182 insertions(+), 28 deletions(-)
 create mode 100644 board-dreamplug.c
 create mode 100644 dtbs.c
 create mode 100644 dtbs.h
 create mode 100644 endian.h
 create mode 100644 fdt.h

diff --git a/Makefile b/Makefile
index c9b2381..7829a01 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ BOARD_OBJ = board-$(MFG).o
 UART_OBJ = serial-$(UART).o
 
 COMMON_OBJS = \
+	dtbs.o \
 	main.o \
 	print.o \
 	register.o \
diff --git a/board-dreamplug.c b/board-dreamplug.c
new file mode 100644
index 0000000..123c0f4
--- /dev/null
+++ b/board-dreamplug.c
@@ -0,0 +1,28 @@
+#include "board.h"
+#include "dtbs.h"
+#include "print.h"
+#include "register.h"
+#include "types.h"
+
+/*
+ * this code is just a quick PoC for appending multiple dtbs.  I don't have
+ * any boards handy with stock, non-DT bootloaders, so I have no machids to
+ * trigger off of.
+ */
+
+extern __u32 _binary_input_zImage_start;
+extern __u32 __end_of_image;
+
+struct board board;
+const char *compat = "globalscale,dreamplug";
+
+struct board *match_board(__u32 machid, const struct tag *tags)
+{
+
+	/* testing zImage linked in and dtbs appended */
+	board.kernel = &_binary_input_zImage_start;
+	board.compatible = compat;
+	board.dtb = find_dtb(&__end_of_image, compat);
+
+	return &board;
+}
diff --git a/board-raumfeld.c b/board-raumfeld.c
index e5d4702..90fffeb 100644
--- a/board-raumfeld.c
+++ b/board-raumfeld.c
@@ -1,38 +1,36 @@
 #include "atags.h"
 #include "board.h"
+#include "dtbs.h"
 #include "print.h"
 #include "register.h"
 #include "types.h"
 
 extern __u32 _binary_input_zImage_start;
-extern __u32 _binary_input_raumfeld_controller_0_dtb_start;
-extern __u32 _binary_input_raumfeld_controller_1_dtb_start;
-extern __u32 _binary_input_raumfeld_controller_2_dtb_start;
-extern __u32 _binary_input_raumfeld_connector_0_dtb_start;
-extern __u32 _binary_input_raumfeld_connector_1_dtb_start;
-extern __u32 _binary_input_raumfeld_connector_2_dtb_start;
-extern __u32 _binary_input_raumfeld_speaker_0_dtb_start;
-extern __u32 _binary_input_raumfeld_speaker_1_dtb_start;
-extern __u32 _binary_input_raumfeld_speaker_2_dtb_start;
-
-static struct board boards[] = {
+extern __u32 __end_of_image;
+
+struct board board;
+
+struct raum_board {
+	__u32		machid;
+	__u32		system_rev;
+	const char	*compatible;
+};
+
+static struct raum_board rboards[] = {
 	/* Controller */
 	{
 		.machid		= 2413,
 		.system_rev	= 0,
-		.dtb		= &_binary_input_raumfeld_controller_0_dtb_start,
 		.compatible	= "Raumfeld Controller, revision 0",
 	},
 	{
 		.machid		= 2413,
 		.system_rev	= 1,
-		.dtb		= &_binary_input_raumfeld_controller_1_dtb_start,
 		.compatible	= "Raumfeld Controller, revision 1",
 	},
 	{
 		.machid		= 2413,
 		.system_rev	= 2,
-		.dtb		= &_binary_input_raumfeld_controller_2_dtb_start,
 		.compatible	= "Raumfeld Controller, revision 2",
 	},
 
@@ -40,19 +38,16 @@ static struct board boards[] = {
 	{
 		.machid		= 2414,
 		.system_rev	= 0,
-		.dtb		= &_binary_input_raumfeld_connector_0_dtb_start,
 		.compatible	= "Raumfeld Connector, revision 0",
 	},
 	{
 		.machid		= 2414,
 		.system_rev	= 1,
-		.dtb		= &_binary_input_raumfeld_connector_1_dtb_start,
 		.compatible	= "Raumfeld Connector, revision 1",
 	},
 	{
 		.machid		= 2414,
 		.system_rev	= 2,
-		.dtb		= &_binary_input_raumfeld_connector_2_dtb_start,
 		.compatible	= "Raumfeld Connector, revision 2",
 	},
 
@@ -60,22 +55,19 @@ static struct board boards[] = {
 	{
 		.machid		= 2415,
 		.system_rev	= 0,
-		.dtb		= &_binary_input_raumfeld_speaker_0_dtb_start,
 		.compatible	= "Raumfeld Speaker, revision 0",
 	},
 	{
 		.machid		= 2415,
 		.system_rev	= 1,
-		.dtb		= &_binary_input_raumfeld_speaker_1_dtb_start,
 		.compatible	= "Raumfeld Speaker, revision 1",
 	},
 	{
 		.machid		= 2415,
 		.system_rev	= 2,
-		.dtb		= &_binary_input_raumfeld_speaker_2_dtb_start,
 		.compatible	= "Raumfeld Speaker, revision 2",
 	},
-	{ 0, 0, NULL, NULL }	/* sentinel */
+	{ 0, 0, NULL }	/* sentinel */
 };
 
 static void wait(__u32 ticks)
@@ -122,7 +114,7 @@ static void led_panic(void)
 struct board *match_board(__u32 machid, const struct tag *tags)
 {
 	const struct tag *t;
-	struct board *board;
+	struct raum_board *rboard;
 	__u32 system_rev = 0;
 
 	/* walk the atags to determine the system revision */
@@ -134,11 +126,12 @@ struct board *match_board(__u32 machid, const struct tag *tags)
 		}
 
 
-	for (board = boards; board->machid; board++)
-		if (board->machid == machid && board->system_rev == system_rev)
+	for (rboard = rboards; rboard->machid; rboard++)
+		if (rboard->machid == machid &&
+		    rboard->system_rev == system_rev)
 			break;
 
-	if (board->compatible == NULL) {
+	if (rboard->compatible == NULL) {
 		putstr("ERROR MATCHING BOARD!\n");
 		putstr("MACHID: 0x");
 		printhex(machid);
@@ -149,5 +142,9 @@ struct board *match_board(__u32 machid, const struct tag *tags)
 		led_panic(); /* doesn't return */
 	}
 
-	return board;
+	board.kernel = &_binary_input_zImage_start;
+	board.compatible = rboard->compatible;
+	board.dtb = find_dtb(&__end_of_image, rboard->compatible);
+
+	return &board;
 }
diff --git a/board.h b/board.h
index a28fb06..75931a1 100644
--- a/board.h
+++ b/board.h
@@ -5,8 +5,6 @@
 #include "atags.h"
 
 struct board {
-	__u32		machid;
-	__u32		system_rev;
 	void		*dtb;
 	void		*kernel;
 	const char	*compatible;
diff --git a/dtbs.c b/dtbs.c
new file mode 100644
index 0000000..a761ac4
--- /dev/null
+++ b/dtbs.c
@@ -0,0 +1,36 @@
+#include "endian.h"
+#include "fdt.h"
+#include "print.h"
+#include "string.h"
+#include "types.h"
+
+/* Yes, this is a dirty hack.  But it's simple, and fast. */
+
+int find_str(char *mem, __u32 memsz, const char *str)
+{
+	__u32 len = strlen(str);
+	const char *last = mem + memsz - len;
+	const char *p;
+
+	for (p = mem; p < last; p++) {
+		if (*p == *str)
+			if (strncmp(p, str, len) == 0)
+				return 1;
+	}
+
+	return 0;
+}
+
+void *find_dtb(void *dtbs, const char *compat)
+{
+	struct fdt_header *d = (struct fdt_header *)dtbs;
+
+	while (d->magic == be_to_cpu(FDT_MAGIC)) {
+		if (find_str((char *)d, be_to_cpu(d->totalsize), compat) == 1)
+			break;
+
+		d = (struct fdt_header *)((char *)d + be_to_cpu(d->totalsize));
+	}
+
+	return d;
+}
diff --git a/dtbs.h b/dtbs.h
new file mode 100644
index 0000000..4e14b32
--- /dev/null
+++ b/dtbs.h
@@ -0,0 +1,6 @@
+#ifndef _DTBS_H
+#define _DTBS_H
+
+void *find_dtb(void *, const char *);
+
+#endif
diff --git a/endian.h b/endian.h
new file mode 100644
index 0000000..531b6b1
--- /dev/null
+++ b/endian.h
@@ -0,0 +1,12 @@
+#ifndef _ENDIAN_H
+#define _ENDIAN_H
+
+#include "types.h"
+
+#define be_to_cpu(x) \
+	( ((0xFF000000UL & ((__u32)x)) >> 24) | \
+	  ((0x00FF0000UL & ((__u32)x)) >> 8)  | \
+	  ((0x0000FF00UL & ((__u32)x)) << 8)  | \
+	  ((0x000000FFUL & ((__u32)x)) << 24)    )
+
+#endif
diff --git a/fdt.h b/fdt.h
new file mode 100644
index 0000000..13a0354
--- /dev/null
+++ b/fdt.h
@@ -0,0 +1,64 @@
+#ifndef _FDT_H
+#define _FDT_H
+
+/* Copied from barebox, thanks! */
+
+#include "types.h"
+
+#ifndef __ASSEMBLY__
+
+struct fdt_header {
+	__u32 magic;			 /* magic word FDT_MAGIC */
+	__u32 totalsize;		 /* total size of DT block */
+	__u32 off_dt_struct;		 /* offset to structure */
+	__u32 off_dt_strings;	 /* offset to strings */
+	__u32 off_mem_rsvmap;	 /* offset to memory reserve map */
+	__u32 version;		 /* format version */
+	__u32 last_comp_version;	 /* last compatible version */
+
+	/* version 2 fields below */
+	__u32 boot_cpuid_phys;	 /* Which physical CPU id we're
+					    booting on */
+	/* version 3 fields below */
+	__u32 size_dt_strings;	 /* size of the strings block */
+
+	/* version 17 fields below */
+	__u32 size_dt_struct;	 /* size of the structure block */
+} __attribute__((packed));
+
+struct fdt_reserve_entry {
+	__u64 address;
+	__u64 size;
+};
+
+struct fdt_node_header {
+	__u32 tag;
+	char name[0];
+};
+
+struct fdt_property {
+	__u32 tag;
+	__u32 len;
+	__u32 nameoff;
+	char data[0];
+};
+
+#endif /* !__ASSEMBLY */
+
+#define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
+#define FDT_TAGSIZE	sizeof(__u32)
+
+#define FDT_BEGIN_NODE	0x1		/* Start node: full name */
+#define FDT_END_NODE	0x2		/* End node */
+#define FDT_PROP	0x3		/* Property: name off,
+					   size, content */
+#define FDT_NOP		0x4		/* nop */
+#define FDT_END		0x9
+
+#define FDT_V1_SIZE	(7*sizeof(__u32))
+#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(__u32))
+#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(__u32))
+#define FDT_V16_SIZE	FDT_V3_SIZE
+#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(__u32))
+
+#endif /* _FDT_H */
diff --git a/string.c b/string.c
index 6584378..d13e22b 100644
--- a/string.c
+++ b/string.c
@@ -7,6 +7,16 @@ int hexlut[1 + 'F' - '0'] = {
 	0xa, 0xb, 0xc, 0xd, 0xe, 0xf                      /* A - F */
 };
 
+int strlen(const char *str)
+{
+	const char *c = str;
+
+	while (*(c++))
+		;
+
+	return c - str;
+}
+
 int strncmp(const char *stra, const char *strb, int len)
 {
 	int diff=0;
diff --git a/string.h b/string.h
index 59f5f0c..0b99785 100644
--- a/string.h
+++ b/string.h
@@ -1,6 +1,7 @@
 #ifndef _STRING_H
 #define _STRING_H
 
+int strlen(const char *);
 int strncmp(const char *, const char *, int);
 void *gethexaddr(const char *, const char **);
 int getaddrs(void **, void **, const char *);
diff --git a/types.h b/types.h
index 27ec08e..4c078a3 100644
--- a/types.h
+++ b/types.h
@@ -2,6 +2,7 @@
 #define _TYPES_H
 
 typedef unsigned int __u32;
+typedef unsigned long long __u64;
 #define NULL	((void *) 0)
 
 #endif /* _TYPES_H */
-- 
1.8.3.2




More information about the linux-arm-kernel mailing list