linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: jason@lakedaemon.net (Jason Cooper)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH V2 9/9] appended dtbs works!
Date: Fri,  2 Aug 2013 15:51:16 +0000	[thread overview]
Message-ID: <ecbf213c41cfd68781dd362e01ee1e42e3d7dba9.1375457714.git.jason@lakedaemon.net> (raw)
In-Reply-To: <cover.1375457714.git.jason@lakedaemon.net>

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@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

  parent reply	other threads:[~2013-08-02 15:51 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-04 16:56 Appended DTB files for multi-machine kernels Daniel Mack
2013-07-04 17:11 ` Mark Brown
2013-07-04 21:34   ` Arnd Bergmann
2013-07-04 23:02     ` Daniel Mack
2013-07-05  8:32     ` Magnus Damm
2013-07-04 17:28 ` Nicolas Pitre
2013-07-04 17:57   ` Daniel Mack
2013-07-04 18:27     ` Nicolas Pitre
2013-07-26 16:13   ` Daniel Mack
2013-07-26 16:44     ` Nicolas Pitre
2013-07-29 21:23     ` [RFC PATCH 0/2] impedance-matcher generic improvements Jason Cooper
2013-07-29 21:24       ` [PATCH 1/2] add cscope Makefile target Jason Cooper
2013-07-29 21:24       ` [RFC PATCH 2/2] WIP: Get kernel and dtb addresses from command line Jason Cooper
2013-07-30  7:48       ` [RFC PATCH 0/2] impedance-matcher generic improvements Daniel Mack
2013-07-30 13:17         ` Jason Cooper
2013-07-30 13:37           ` Daniel Mack
2013-07-30 14:42             ` Jason Cooper
2013-08-02 15:51     ` [RFC PATCH V2 0/9] " Jason Cooper
2013-08-02 15:51       ` [RFC PATCH V2 1/9] add cscope Makefile target Jason Cooper
2013-08-02 15:51       ` [RFC PATCH V2 2/9] separate common functions from board specific Jason Cooper
2013-08-02 15:51       ` [RFC PATCH V2 3/9] rename board.c to board-raumfeld.c Jason Cooper
2013-08-02 15:51       ` [RFC PATCH V2 4/9] s/.name/.compatible/ Jason Cooper
2013-08-02 21:52         ` Stephen Warren
2013-08-03 14:07           ` Jason Cooper
2013-08-03 14:16             ` Daniel Mack
2013-08-02 15:51       ` [RFC PATCH V2 5/9] directly include needed headers Jason Cooper
2013-08-02 15:51       ` [RFC PATCH V2 6/9] serial: split out 8250 code, configurable reg addr Jason Cooper
2013-08-02 15:51       ` [RFC PATCH V2 7/9] add generic board code Jason Cooper
2013-08-02 15:51       ` [RFC PATCH V2 8/9] make appending images/dtbs optional Jason Cooper
2013-08-02 15:51       ` Jason Cooper [this message]
2013-08-02 19:42         ` [RFC PATCH V2 9/9] appended dtbs works! Nicolas Pitre
2013-08-02 19:54           ` Jason Cooper
2013-08-02 19:57           ` Jason Cooper
2013-08-02 17:53       ` [RFC PATCH V2 0/9] impedance-matcher generic improvements Daniel Mack
2013-08-02 18:43         ` Jason Cooper
2013-08-02 18:46           ` Daniel Mack
2013-07-04 18:36 ` Appended DTB files for multi-machine kernels Dirk Behme
2013-07-05 18:36 ` Stephen Warren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ecbf213c41cfd68781dd362e01ee1e42e3d7dba9.1375457714.git.jason@lakedaemon.net \
    --to=jason@lakedaemon.net \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).