mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* bootm + devicetree + much memory
@ 2014-01-10 11:05 Sascha Hauer
  2014-01-10 11:05 ` [PATCH 1/8] list: add list_first_entry_or_null() Sascha Hauer
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

Current bootm implementation on ARM has the problem with systems with
much memory. The devicetree is allocated with malloc(). On some systems
the malloc area is outside of the kernels lowmem, so the kernel can't
access the devicetree anymore. The complexity of the current code
makes it hard to solve, so this series contains several patches to
make the bootm code simpler before the actual problem is solved.

Sascha

----------------------------------------------------------------
Sascha Hauer (8):
      list: add list_first_entry_or_null()
      bootm: introduce bootm_load_os helper
      ARM: bootm: move os loading to do_bootm_linux
      bootm: introduce bootm_load_initrd helper
      bootm: introduce bootm_load_devicetree helper
      ARM: bootm: locate zImage higher into RAM
      ARM: bootm: determine RAM start in separate function
      ARM: bootm: pass free memory to __do_bootm_linux

 arch/arm/lib/bootm.c               | 164 ++++++++++++++++++++++++-------------
 arch/blackfin/lib/blackfin_linux.c |   6 +-
 arch/nios2/lib/bootm.c             |   6 +-
 arch/ppc/lib/ppclinux.c            |   6 +-
 common/bootm.c                     | 150 +++++++++++++++++++++++++++++++--
 include/boot.h                     |   5 ++
 include/linux/list.h               |  11 +++
 7 files changed, 278 insertions(+), 70 deletions(-)

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] list: add list_first_entry_or_null()
  2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
@ 2014-01-10 11:05 ` Sascha Hauer
  2014-01-10 11:05 ` [PATCH 2/8] bootm: introduce bootm_load_os helper Sascha Hauer
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/linux/list.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/linux/list.h b/include/linux/list.h
index 5ae90b4..bc63ece 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -292,6 +292,17 @@ static inline void list_splice_init(struct list_head *list,
 	list_entry((head)->prev, type, member)
 
 /**
+ * list_first_entry_or_null - get the first element from a list
+ * @ptr:	the list head to take the element from.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Note that if the list is empty, it returns NULL.
+ */
+#define list_first_entry_or_null(ptr, type, member) \
+	(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
+/**
  * list_for_each	-	iterate over a list
  * @pos:	the &struct list_head to use as a loop cursor.
  * @head:	the head for your list.
-- 
1.8.5.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/8] bootm: introduce bootm_load_os helper
  2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
  2014-01-10 11:05 ` [PATCH 1/8] list: add list_first_entry_or_null() Sascha Hauer
@ 2014-01-10 11:05 ` Sascha Hauer
  2014-01-10 11:05 ` [PATCH 3/8] ARM: bootm: move os loading to do_bootm_linux Sascha Hauer
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

The common bootm code used to load uImage contents to SDRAM
before calling into the handlers if possible. This makes the
handlers complicated since they have to handle many cases. Instead,
introduce a helper to load the os after the handlers have figured
out a good load address.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/lib/bootm.c               | 24 ++++++-------------
 arch/blackfin/lib/blackfin_linux.c |  6 +++--
 arch/nios2/lib/bootm.c             |  6 +++--
 arch/ppc/lib/ppclinux.c            |  6 +++--
 common/bootm.c                     | 49 +++++++++++++++++++++++++++++++-------
 include/boot.h                     |  2 ++
 6 files changed, 61 insertions(+), 32 deletions(-)

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index c0e4e15..7401f2f 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -28,32 +28,22 @@ static int __do_bootm_linux(struct image_data *data, int swap)
 	unsigned long initrd_start = 0, initrd_size = 0, initrd_end = 0;
 	struct memory_bank *bank;
 	unsigned long load_address;
+	int ret;
 
-	if (data->os_res) {
-		load_address = data->os_res->start;
-	} else if (data->os_address != UIMAGE_INVALID_ADDRESS) {
-		load_address = data->os_address;
-	} else {
+	if (data->os_address == UIMAGE_INVALID_ADDRESS) {
 		bank = list_first_entry(&memory_banks,
 				struct memory_bank, list);
 		load_address = bank->start + SZ_32K;
 		if (bootm_verbose(data))
 			printf("no os load address, defaulting to 0x%08lx\n",
 				load_address);
+	} else {
+		load_address = data->os_address;
 	}
 
-	if (!data->os_res && data->os) {
-		data->os_res = uimage_load_to_sdram(data->os,
-			data->os_num, load_address);
-		if (!data->os_res)
-			return -ENOMEM;
-	}
-
-	if (!data->os_res) {
-		data->os_res = file_to_sdram(data->os_file, load_address);
-		if (!data->os_res)
-			return -ENOMEM;
-	}
+	ret = bootm_load_os(data, load_address);
+	if (ret)
+		return ret;
 
 	kernel = data->os_res->start + data->os_entry;
 
diff --git a/arch/blackfin/lib/blackfin_linux.c b/arch/blackfin/lib/blackfin_linux.c
index bb3c774..2561a7e 100644
--- a/arch/blackfin/lib/blackfin_linux.c
+++ b/arch/blackfin/lib/blackfin_linux.c
@@ -41,9 +41,11 @@ static int do_bootm_linux(struct image_data *idata)
 	int (*appl)(char *cmdline);
 	const char *cmdline = linux_bootargs_get();
 	char *cmdlinedest = (char *) CMD_LINE_ADDR;
+	int ret;
 
-	if (!idata->os_res)
-		return -EINVAL;
+	ret = bootm_load_os(idata, idata->os_address);
+	if (ret)
+		return ret;
 
 	appl = (void *)(idata->os_address + idata->os_entry);
 	printf("Starting Kernel at 0x%p\n", appl);
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index cc96290..77da119 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -36,9 +36,11 @@ static int do_bootm_linux(struct image_data *idata)
 {
 	void (*kernel)(int, int, int, const char *);
 	const char *commandline = linux_bootargs_get();
+	int ret;
 
-	if (!idata->os_res)
-		return -EINVAL;
+	ret = bootm_load_os(idata, idata->os_address);
+	if (ret)
+		return ret;
 
 	kernel = (void *)(idata->os_address + idata->os_entry);
 
diff --git a/arch/ppc/lib/ppclinux.c b/arch/ppc/lib/ppclinux.c
index 7c30ac3..e25efec 100644
--- a/arch/ppc/lib/ppclinux.c
+++ b/arch/ppc/lib/ppclinux.c
@@ -47,9 +47,11 @@ static int do_bootm_linux(struct image_data *data)
 {
 	void	(*kernel)(void *, void *, unsigned long,
 			unsigned long, unsigned long);
+	int ret;
 
-	if (!data->os_res)
-		return -EINVAL;
+	ret = bootm_load_os(data, data->os_address);
+	if (ret)
+		return ret;
 
 	data->oftree = of_get_fixed_tree(data->of_root_node);
 	if (!data->oftree) {
diff --git a/common/bootm.c b/common/bootm.c
index 2da6e59..5ad10d9 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -45,6 +45,46 @@ static struct image_handler *bootm_find_handler(enum filetype filetype,
 	return NULL;
 }
 
+/*
+ * bootm_load_os() - load OS to RAM
+ *
+ * @data:		image data context
+ * @load_address:	The address where the OS should be loaded to
+ *
+ * This loads the OS to a RAM location. load_address must be a valid
+ * address. If the image_data doesn't have a OS specified it's considered
+ * an error.
+ *
+ * Return: 0 on success, negative error code otherwise
+ */
+int bootm_load_os(struct image_data *data, unsigned long load_address)
+{
+	if (data->os_res)
+		return 0;
+
+	if (load_address == UIMAGE_INVALID_ADDRESS)
+		return -EINVAL;
+
+	if (data->os) {
+		data->os_res = uimage_load_to_sdram(data->os,
+			data->os_num, load_address);
+		if (!data->os_res)
+			return -ENOMEM;
+
+		return 0;
+	}
+
+	if (data->os_file) {
+		data->os_res = file_to_sdram(data->os_file, load_address);
+		if (!data->os_res)
+			return -ENOMEM;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static int bootm_open_os_uimage(struct image_data *data)
 {
 	int ret;
@@ -75,15 +115,6 @@ static int bootm_open_os_uimage(struct image_data *data)
 	if (data->os_address == UIMAGE_SOME_ADDRESS)
 		data->os_address = data->os->header.ih_load;
 
-	if (data->os_address != UIMAGE_INVALID_ADDRESS) {
-		data->os_res = uimage_load_to_sdram(data->os, 0,
-				data->os_address);
-		if (!data->os_res) {
-			uimage_close(data->os);
-			return -ENOMEM;
-		}
-	}
-
 	return 0;
 }
 
diff --git a/include/boot.h b/include/boot.h
index 56f6c35..61ab5d0 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -108,6 +108,8 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
 }
 #endif
 
+int bootm_load_os(struct image_data *data, unsigned long load_address);
+
 #define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
 
 #endif /* __BOOT_H */
-- 
1.8.5.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/8] ARM: bootm: move os loading to do_bootm_linux
  2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
  2014-01-10 11:05 ` [PATCH 1/8] list: add list_first_entry_or_null() Sascha Hauer
  2014-01-10 11:05 ` [PATCH 2/8] bootm: introduce bootm_load_os helper Sascha Hauer
@ 2014-01-10 11:05 ` Sascha Hauer
  2014-01-10 11:05 ` [PATCH 4/8] bootm: introduce bootm_load_initrd helper Sascha Hauer
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

__do_bootm_linux is called from the uImage, zImage and raw handlers.
In case of the zImage handler the kernel will already be loaded and
the kernel load code in __do_bootm_linux will do nothing. Move the
loading code to do_bootm_linux so that __do_bootm_linux will always
be called with the kernel already loaded.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/lib/bootm.c | 37 +++++++++++++++++++------------------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 7401f2f..6f84cb3 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -26,24 +26,6 @@ static int __do_bootm_linux(struct image_data *data, int swap)
 {
 	unsigned long kernel;
 	unsigned long initrd_start = 0, initrd_size = 0, initrd_end = 0;
-	struct memory_bank *bank;
-	unsigned long load_address;
-	int ret;
-
-	if (data->os_address == UIMAGE_INVALID_ADDRESS) {
-		bank = list_first_entry(&memory_banks,
-				struct memory_bank, list);
-		load_address = bank->start + SZ_32K;
-		if (bootm_verbose(data))
-			printf("no os load address, defaulting to 0x%08lx\n",
-				load_address);
-	} else {
-		load_address = data->os_address;
-	}
-
-	ret = bootm_load_os(data, load_address);
-	if (ret)
-		return ret;
 
 	kernel = data->os_res->start + data->os_entry;
 
@@ -104,6 +86,25 @@ static int __do_bootm_linux(struct image_data *data, int swap)
 
 static int do_bootm_linux(struct image_data *data)
 {
+	struct memory_bank *bank;
+	unsigned long load_address;
+	int ret;
+
+	load_address = data->os_address;
+
+	if (load_address == UIMAGE_INVALID_ADDRESS) {
+		bank = list_first_entry(&memory_banks,
+				struct memory_bank, list);
+		load_address = bank->start + SZ_32K;
+		if (bootm_verbose(data))
+			printf("no os load address, defaulting to 0x%08lx\n",
+				load_address);
+	}
+
+	ret = bootm_load_os(data, load_address);
+	if (ret)
+		return ret;
+
 	return __do_bootm_linux(data, 0);
 }
 
-- 
1.8.5.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4/8] bootm: introduce bootm_load_initrd helper
  2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
                   ` (2 preceding siblings ...)
  2014-01-10 11:05 ` [PATCH 3/8] ARM: bootm: move os loading to do_bootm_linux Sascha Hauer
@ 2014-01-10 11:05 ` Sascha Hauer
  2014-01-10 11:05 ` [PATCH 5/8] bootm: introduce bootm_load_devicetree helper Sascha Hauer
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

Make the bootm handlers simpler by factoring out an initrd load
function.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/lib/bootm.c | 15 ++++-----------
 common/bootm.c       | 38 ++++++++++++++++++++++++++++++++++++++
 include/boot.h       |  1 +
 3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 6f84cb3..3604df0 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -31,7 +31,7 @@ static int __do_bootm_linux(struct image_data *data, int swap)
 
 	initrd_start = data->initrd_address;
 
-	if (data->initrd_file && initrd_start == UIMAGE_INVALID_ADDRESS) {
+	if (initrd_start == UIMAGE_INVALID_ADDRESS) {
 		initrd_start = data->os_res->start + SZ_8M;
 
 		if (bootm_verbose(data)) {
@@ -40,16 +40,9 @@ static int __do_bootm_linux(struct image_data *data, int swap)
 		}
 	}
 
-	if (data->initrd) {
-		data->initrd_res = uimage_load_to_sdram(data->initrd,
-			data->initrd_num, initrd_start);
-		if (!data->initrd_res)
-			return -ENOMEM;
-	} else if (data->initrd_file) {
-		data->initrd_res = file_to_sdram(data->initrd_file, initrd_start);
-		if (!data->initrd_res)
-			return -ENOMEM;
-	}
+	ret = bootm_load_initrd(data, initrd_start);
+	if (ret)
+		return ret;
 
 	if (data->initrd_res) {
 		initrd_start = data->initrd_res->start;
diff --git a/common/bootm.c b/common/bootm.c
index 5ad10d9..9ccbe8f 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -85,6 +85,44 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
 	return -EINVAL;
 }
 
+/*
+ * bootm_load_initrd() - load initrd to RAM
+ *
+ * @data:		image data context
+ * @load_address:	The address where the initrd should be loaded to
+ *
+ * This loads the initrd to a RAM location. load_address must be a valid
+ * address. If the image_data doesn't have a initrd specified this function
+ * still returns successful as an initrd is optional. Check data->initrd_res
+ * to see if an initrd has been loaded.
+ *
+ * Return: 0 on success, negative error code otherwise
+ */
+int bootm_load_initrd(struct image_data *data, unsigned long load_address)
+{
+	if (data->initrd_res)
+		return 0;
+
+	if (data->initrd) {
+		data->initrd_res = uimage_load_to_sdram(data->initrd,
+			data->initrd_num, load_address);
+		if (!data->initrd_res)
+			return -ENOMEM;
+
+		return 0;
+	}
+
+	if (data->initrd_file) {
+		data->initrd_res = file_to_sdram(data->initrd_file, load_address);
+		if (!data->initrd_res)
+			return -ENOMEM;
+
+		return 0;
+	}
+
+	return 0;
+}
+
 static int bootm_open_os_uimage(struct image_data *data)
 {
 	int ret;
diff --git a/include/boot.h b/include/boot.h
index 61ab5d0..0cb2949 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -109,6 +109,7 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
 #endif
 
 int bootm_load_os(struct image_data *data, unsigned long load_address);
+int bootm_load_initrd(struct image_data *data, unsigned long load_address);
 
 #define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
 
-- 
1.8.5.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 5/8] bootm: introduce bootm_load_devicetree helper
  2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
                   ` (3 preceding siblings ...)
  2014-01-10 11:05 ` [PATCH 4/8] bootm: introduce bootm_load_initrd helper Sascha Hauer
@ 2014-01-10 11:05 ` Sascha Hauer
  2014-01-10 11:05 ` [PATCH 6/8] ARM: bootm: locate zImage higher into RAM Sascha Hauer
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/bootm.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/boot.h |  2 ++
 2 files changed, 65 insertions(+)

diff --git a/common/bootm.c b/common/bootm.c
index 9ccbe8f..d62d011 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -123,6 +123,67 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
 	return 0;
 }
 
+/*
+ * bootm_load_devicetree() - load devicetree
+ *
+ * @data:		image data context
+ * @load_address:	The address where the devicetree should be loaded to
+ *
+ * This loads the devicetree to a RAM location. load_address must be a valid
+ * address. The resulting devicetree will be found at data->oftree.
+ *
+ * Return: 0 on success, negative error code otherwise
+ */
+int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
+{
+	int fdt_size;
+	struct fdt_header *oftree;
+
+	if (data->oftree)
+		return 0;
+
+	if (!IS_ENABLED(CONFIG_OFTREE))
+		return 0;
+
+	if (!data->of_root_node)
+		return 0;
+
+	if (data->initrd_res) {
+		of_add_initrd(data->of_root_node, data->initrd_res->start,
+				data->initrd_res->end);
+		of_add_reserve_entry(data->initrd_res->start, data->initrd_res->end);
+	}
+
+	oftree = of_get_fixed_tree(data->of_root_node);
+	if (!oftree)
+		return -EINVAL;
+
+	fdt_size = be32_to_cpu(oftree->totalsize);
+
+	data->oftree_res = request_sdram_region("oftree", load_address,
+			fdt_size);
+	if (!data->oftree_res) {
+		free(oftree);
+		return -ENOMEM;
+	}
+
+	memcpy((void *)data->oftree_res->start, oftree, fdt_size);
+
+	free(oftree);
+
+	oftree = (void *)data->oftree_res->start;
+
+	fdt_add_reserve_map(oftree);
+
+	of_print_cmdline(data->of_root_node);
+	if (bootm_verbose(data) > 1)
+		of_print_nodes(data->of_root_node, 0);
+
+	data->oftree = oftree;
+
+	return 0;
+}
+
 static int bootm_open_os_uimage(struct image_data *data)
 {
 	int ret;
@@ -412,6 +473,8 @@ err_out:
 		release_sdram_region(data->os_res);
 	if (data->initrd_res)
 		release_sdram_region(data->initrd_res);
+	if (data->oftree_res)
+		release_sdram_region(data->oftree_res);
 	if (data->initrd && data->initrd != data->os)
 		uimage_close(data->initrd);
 	if (data->os)
diff --git a/include/boot.h b/include/boot.h
index 0cb2949..bdd5477 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -61,6 +61,7 @@ struct image_data {
 
 	struct device_node *of_root_node;
 	struct fdt_header *oftree;
+	struct resource *oftree_res;
 
 	int verify;
 	int verbose;
@@ -110,6 +111,7 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
 
 int bootm_load_os(struct image_data *data, unsigned long load_address);
 int bootm_load_initrd(struct image_data *data, unsigned long load_address);
+int bootm_load_devicetree(struct image_data *data, unsigned long load_address);
 
 #define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
 
-- 
1.8.5.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 6/8] ARM: bootm: locate zImage higher into RAM
  2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
                   ` (4 preceding siblings ...)
  2014-01-10 11:05 ` [PATCH 5/8] bootm: introduce bootm_load_devicetree helper Sascha Hauer
@ 2014-01-10 11:05 ` Sascha Hauer
  2014-01-10 11:05 ` [PATCH 7/8] ARM: bootm: determine RAM start in separate function Sascha Hauer
  2014-01-10 11:05 ` [PATCH 8/8] ARM: bootm: pass free memory to __do_bootm_linux Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

The zImage should be placed where it won't be overwritten by the
uncompressed image, otherwise the kernel decompressing code has
to relocate the zImage before decompression. As Kernels tend to
become bigger put it into 32MiB into RAM if we have enough RAM
available.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/lib/bootm.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 3604df0..11ff98c 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -195,7 +195,17 @@ static int do_bootz_linux(struct image_data *data)
 	if (load_address == UIMAGE_INVALID_ADDRESS) {
 		struct memory_bank *bank = list_first_entry(&memory_banks,
 				struct memory_bank, list);
-		data->os_address = bank->start + SZ_8M;
+
+		/*
+		 * The kernel should stay in the first 128MiB of RAM, recommended
+		 * is 32MiB into RAM so that relocation prior to decompression
+		 * can be avoided.
+		 */
+		if (mem_size > SZ_64M)
+			data->os_address = bank->start + SZ_32M;
+		else
+			data->os_address = bank->start + SZ_8M;
+
 		load_address = data->os_address;
 		if (bootm_verbose(data))
 			printf("no os load address, defaulting to 0x%08lx\n",
-- 
1.8.5.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 7/8] ARM: bootm: determine RAM start in separate function
  2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
                   ` (5 preceding siblings ...)
  2014-01-10 11:05 ` [PATCH 6/8] ARM: bootm: locate zImage higher into RAM Sascha Hauer
@ 2014-01-10 11:05 ` Sascha Hauer
  2014-01-10 11:05 ` [PATCH 8/8] ARM: bootm: pass free memory to __do_bootm_linux Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

We have two places in which we determine the RAM start address.
Put the code in a separate function. Let this function also figure
out the space available from beginning of RAM.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/lib/bootm.c | 55 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 45 insertions(+), 10 deletions(-)

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 11ff98c..5a2780a 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -22,6 +22,38 @@
 #include <asm/armlinux.h>
 #include <asm/system.h>
 
+/*
+ * sdram_start_and_size() - determine place for putting the kernel/oftree/initrd
+ *
+ * @start:	returns the start address of the first RAM bank
+ * @size:	returns the usable space at the beginning of the first RAM bank
+ *
+ * This function returns the base address of the first RAM bank and the free
+ * space found there.
+ *
+ * return: 0 for success, negative error code otherwise
+ */
+static int sdram_start_and_size(unsigned long *start, unsigned long *size)
+{
+	struct memory_bank *bank;
+	struct resource *res;
+
+	bank = list_first_entry_or_null(&memory_banks, struct memory_bank,
+			list);
+	if (!bank)
+		return -EINVAL;
+
+	res = list_first_entry_or_null(&bank->res->children, struct resource,
+			sibling);
+	if (!res)
+		return -EINVAL;
+
+	*start = bank->start;
+	*size = res->start - bank->start;
+
+	return 0;
+}
+
 static int __do_bootm_linux(struct image_data *data, int swap)
 {
 	unsigned long kernel;
@@ -79,16 +111,17 @@ static int __do_bootm_linux(struct image_data *data, int swap)
 
 static int do_bootm_linux(struct image_data *data)
 {
-	struct memory_bank *bank;
-	unsigned long load_address;
+	unsigned long load_address, mem_start, mem_size;
 	int ret;
 
+	ret = sdram_start_and_size(&mem_start, &mem_size);
+	if (ret)
+		return ret;
+
 	load_address = data->os_address;
 
 	if (load_address == UIMAGE_INVALID_ADDRESS) {
-		bank = list_first_entry(&memory_banks,
-				struct memory_bank, list);
-		load_address = bank->start + SZ_32K;
+		load_address = mem_start + SZ_32K;
 		if (bootm_verbose(data))
 			printf("no os load address, defaulting to 0x%08lx\n",
 				load_address);
@@ -191,20 +224,22 @@ static int do_bootz_linux(struct image_data *data)
 	void *zimage;
 	u32 end;
 	unsigned long load_address = data->os_address;
+	unsigned long mem_start, mem_size;
 
-	if (load_address == UIMAGE_INVALID_ADDRESS) {
-		struct memory_bank *bank = list_first_entry(&memory_banks,
-				struct memory_bank, list);
+	ret = sdram_start_and_size(&mem_start, &mem_size);
+	if (ret)
+		return ret;
 
+	if (load_address == UIMAGE_INVALID_ADDRESS) {
 		/*
 		 * The kernel should stay in the first 128MiB of RAM, recommended
 		 * is 32MiB into RAM so that relocation prior to decompression
 		 * can be avoided.
 		 */
 		if (mem_size > SZ_64M)
-			data->os_address = bank->start + SZ_32M;
+			data->os_address = mem_start + SZ_32M;
 		else
-			data->os_address = bank->start + SZ_8M;
+			data->os_address = mem_start + SZ_8M;
 
 		load_address = data->os_address;
 		if (bootm_verbose(data))
-- 
1.8.5.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 8/8] ARM: bootm: pass free memory to __do_bootm_linux
  2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
                   ` (6 preceding siblings ...)
  2014-01-10 11:05 ` [PATCH 7/8] ARM: bootm: determine RAM start in separate function Sascha Hauer
@ 2014-01-10 11:05 ` Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2014-01-10 11:05 UTC (permalink / raw)
  To: barebox

This improves the initrd/devicetree placement in the bootm code.
We used to put the initrd at the start of the kernel + 8MiB. This
of course fails once the kernel gets bigger than 8MiB. Also the
place for the devicetree was allocated using malloc(). This can
lead to the problem that the devicetree is outside of the kernels
lowmem and thus not reachable for the kernel.
With this patch __do_bootm_linux gets a pointer to free space where
the devicetree and the initrd can be safely put.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/lib/bootm.c | 59 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 42 insertions(+), 17 deletions(-)

diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 5a2780a..182655f 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -54,17 +54,18 @@ static int sdram_start_and_size(unsigned long *start, unsigned long *size)
 	return 0;
 }
 
-static int __do_bootm_linux(struct image_data *data, int swap)
+static int __do_bootm_linux(struct image_data *data, unsigned long free_mem, int swap)
 {
 	unsigned long kernel;
 	unsigned long initrd_start = 0, initrd_size = 0, initrd_end = 0;
+	int ret;
 
 	kernel = data->os_res->start + data->os_entry;
 
 	initrd_start = data->initrd_address;
 
 	if (initrd_start == UIMAGE_INVALID_ADDRESS) {
-		initrd_start = data->os_res->start + SZ_8M;
+		initrd_start = PAGE_ALIGN(free_mem);
 
 		if (bootm_verbose(data)) {
 			printf("no initrd load address, defaulting to 0x%08lx\n",
@@ -80,18 +81,12 @@ static int __do_bootm_linux(struct image_data *data, int swap)
 		initrd_start = data->initrd_res->start;
 		initrd_end = data->initrd_res->end;
 		initrd_size = resource_size(data->initrd_res);
+		free_mem = PAGE_ALIGN(initrd_end);
 	}
 
-	if (IS_ENABLED(CONFIG_OFTREE) && data->of_root_node) {
-		of_add_initrd(data->of_root_node, initrd_start, initrd_end);
-		if (initrd_end)
-			of_add_reserve_entry(initrd_start, initrd_end);
-		data->oftree = of_get_fixed_tree(data->of_root_node);
-		fdt_add_reserve_map(data->oftree);
-		of_print_cmdline(data->of_root_node);
-		if (bootm_verbose(data) > 1)
-			of_print_nodes(data->of_root_node, 0);
-	}
+	ret = bootm_load_devicetree(data, free_mem);
+	if (ret)
+		return ret;
 
 	if (bootm_verbose(data)) {
 		printf("\nStarting kernel at 0x%08lx", kernel);
@@ -111,7 +106,7 @@ static int __do_bootm_linux(struct image_data *data, int swap)
 
 static int do_bootm_linux(struct image_data *data)
 {
-	unsigned long load_address, mem_start, mem_size;
+	unsigned long load_address, mem_start, mem_size, mem_free;
 	int ret;
 
 	ret = sdram_start_and_size(&mem_start, &mem_size);
@@ -131,7 +126,16 @@ static int do_bootm_linux(struct image_data *data)
 	if (ret)
 		return ret;
 
-	return __do_bootm_linux(data, 0);
+	/*
+	 * Put devicetree/initrd at maximum to 128MiB into RAM to not
+	 * risk to put it outside of lowmem.
+	 */
+	if (mem_size > SZ_256M)
+		mem_free = mem_start + SZ_128M;
+	else
+		mem_free = PAGE_ALIGN(data->os_res->end + SZ_1M);
+
+	return __do_bootm_linux(data, mem_free, 0);
 }
 
 static struct image_handler uimage_handler = {
@@ -224,7 +228,7 @@ static int do_bootz_linux(struct image_data *data)
 	void *zimage;
 	u32 end;
 	unsigned long load_address = data->os_address;
-	unsigned long mem_start, mem_size;
+	unsigned long mem_start, mem_size, mem_free;
 
 	ret = sdram_start_and_size(&mem_start, &mem_size);
 	if (ret)
@@ -309,7 +313,17 @@ static int do_bootz_linux(struct image_data *data)
 		goto err_out;
 
 	close(fd);
-	return __do_bootm_linux(data, swap);
+
+	/*
+	 * Put devicetree/initrd at maximum to 128MiB into RAM to not
+	 * risk to put it outside of lowmem.
+	 */
+	if (mem_size > SZ_256M)
+		mem_free = mem_start + SZ_128M;
+	else
+		mem_free = PAGE_ALIGN(data->os_res->end + SZ_1M);
+
+	return __do_bootm_linux(data, mem_free, swap);
 
 err_out:
 	close(fd);
@@ -384,6 +398,7 @@ static int do_bootm_aimage(struct image_data *data)
 	void *buf;
 	int to_read;
 	struct android_header_comp *cmp;
+	unsigned long mem_free;
 
 	fd = open(data->os_file, O_RDONLY);
 	if (fd < 0) {
@@ -477,7 +492,17 @@ static int do_bootm_aimage(struct image_data *data)
 	}
 
 	close(fd);
-	return __do_bootm_linux(data, 0);
+
+	/*
+	 * Put devicetree right after initrd if present or after the kernel
+	 * if not.
+	 */
+	if (data->initrd_res)
+		mem_free = PAGE_ALIGN(data->initrd_res->end);
+	else
+		mem_free = PAGE_ALIGN(data->os_res->end + SZ_1M);
+
+	return __do_bootm_linux(data, mem_free, 0);
 
 err_out:
 	linux_bootargs_overwrite(NULL);
-- 
1.8.5.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-01-10 11:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-10 11:05 bootm + devicetree + much memory Sascha Hauer
2014-01-10 11:05 ` [PATCH 1/8] list: add list_first_entry_or_null() Sascha Hauer
2014-01-10 11:05 ` [PATCH 2/8] bootm: introduce bootm_load_os helper Sascha Hauer
2014-01-10 11:05 ` [PATCH 3/8] ARM: bootm: move os loading to do_bootm_linux Sascha Hauer
2014-01-10 11:05 ` [PATCH 4/8] bootm: introduce bootm_load_initrd helper Sascha Hauer
2014-01-10 11:05 ` [PATCH 5/8] bootm: introduce bootm_load_devicetree helper Sascha Hauer
2014-01-10 11:05 ` [PATCH 6/8] ARM: bootm: locate zImage higher into RAM Sascha Hauer
2014-01-10 11:05 ` [PATCH 7/8] ARM: bootm: determine RAM start in separate function Sascha Hauer
2014-01-10 11:05 ` [PATCH 8/8] ARM: bootm: pass free memory to __do_bootm_linux Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox