copper: Add Device Tree support

Add functionality to update device tree blob

Change-Id: I29b3c20ee58a370b860aec81a1c10e1095313d98
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 0dc1a52..f81a44b 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -49,6 +49,10 @@
 #include <platform.h>
 #include <crypto_hash.h>
 
+#if DEVICE_TREE
+#include <libfdt.h>
+#endif
+
 #include "image_verify.h"
 #include "recovery.h"
 #include "bootimg.h"
@@ -72,6 +76,10 @@
 #define RECOVERY_MODE   0x77665502
 #define FASTBOOT_MODE   0x77665500
 
+#if DEVICE_TREE
+int update_device_tree(const void *, char *, void *, unsigned);
+#endif
+
 static const char *emmc_cmdline = " androidboot.emmc=true";
 static const char *usb_sn_cmdline = " androidboot.serialno=";
 static const char *battchg_pause = " androidboot.mode=charger";
@@ -355,10 +363,21 @@
 		const char *cmdline, unsigned machtype,
 		void *ramdisk, unsigned ramdisk_size)
 {
+	int ret = 0;
 	void (*entry)(unsigned, unsigned, unsigned*) = kernel;
 
+#if DEVICE_TREE
+	/* Update the Device Tree */
+	ret = update_device_tree(tags, cmdline, ramdisk, ramdisk_size);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
+		ASSERT(0);
+	}
+#else
 	/* Generating the Atags */
 	generate_atags(tags, cmdline, ramdisk, ramdisk_size);
+#endif
 
 	dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)\n",
 		kernel, ramdisk, ramdisk_size);
@@ -1395,3 +1414,68 @@
 	.init = aboot_init,
 APP_END
 
+#if DEVICE_TREE
+/* Device Tree Stuff */
+int update_device_tree(const void * fdt, char *cmdline,
+					   void *ramdisk, unsigned ramdisk_size)
+{
+	int ret = 0;
+	int offset;
+	uint32_t *memory_reg;
+	unsigned char *final_cmdline;
+	uint32_t len;
+
+	/* Check the device tree header */
+	ret = fdt_check_header(fdt);
+	if(ret)
+	{
+		dprintf(CRITICAL, "Invalid device tree header \n");
+		return ret;
+	}
+
+	/* Get offset of the memory node */
+	offset = fdt_path_offset(fdt,"/memory");
+
+	memory_reg = target_dev_tree_mem(&len);
+
+	/* Adding the memory values to the reg property */
+	ret = fdt_setprop(fdt, offset, "reg", memory_reg, sizeof(uint32_t) * len * 2);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Cannot update memory node\n");
+		return ret;
+	}
+
+	/* Get offset of the chosen node */
+	offset = fdt_path_offset(fdt, "/chosen");
+
+	/* Adding the cmdline to the chosen node */
+	final_cmdline = update_cmdline(cmdline);
+	ret = fdt_setprop_string(fdt, offset, "bootargs", final_cmdline);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Cannot update chosen node [bootargs]\n");
+		return ret;
+	}
+
+	/* Adding the initrd-start to the chosen node */
+	ret = fdt_setprop_cell(fdt, offset, "linux,initrd-start", ramdisk);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-start]\n");
+		return ret;
+	}
+
+	/* Adding the initrd-end to the chosen node */
+	ret = fdt_setprop_cell(fdt, offset, "linux,initrd-end", (ramdisk + ramdisk_size));
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-end]\n");
+		return ret;
+	}
+
+	fdt_pack(fdt);
+
+	return ret;
+}
+#endif