Patchwork [U-Boot,2/3] image: Implement IH_TYPE_KERNEL_REL

login
register
mail settings
Submitter Stephen Warren
Date Oct. 11, 2011, 4:15 p.m.
Message ID <1318349751-23798-2-git-send-email-swarren@nvidia.com>
Download mbox | patch
Permalink /patch/119017/
State Superseded
Headers show

Comments

Stephen Warren - Oct. 11, 2011, 4:15 p.m.
uImage files contain absolute "load" and "entry" addresses. Such a concept
is incompatible with using the same kernel image on multiple SoCs, each with
a potentially different SDRAM base. To support that, create a new image type
IH_TYPE_KERNEL_REL, which is handled identically to IH_TYPE_KERNEL, except
that the "load" and "entry" properties are an offset from the base of SDRAM,
rather than an absolute address.

v2:
* Add IH_TYPE_FLATDT_REL.
* Expanded documentation of "an offset from the base of SDRAM".
* Put all new code under #ifdef CONFIG_SYS_RELATIVE_IMAGEs, to prevent code
  bloat for platforms not wanting this feature. For me, this still results
  in a 32-byte .text increase; I'm not sure why.
* A few trivial cleanups (now completely checkpatch clean).
* Tested with MAKEALL -a arm; as best I can tell, this introduces no new
  issues.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 arch/arm/cpu/armv7/omap-common/spl.c |    2 +-
 arch/sh/lib/bootm.c                  |    2 +-
 common/cmd_bootm.c                   |   21 ++-
 common/cmd_ximg.c                    |    2 +-
 common/image.c                       |  270 +++++++++++++++++++++++++++++-----
 common/lynxkdi.c                     |    6 +-
 common/update.c                      |    2 +-
 include/image.h                      |   60 +++++++-
 tools/default_image.c                |   10 +-
 9 files changed, 318 insertions(+), 57 deletions(-)

Patch

diff --git a/arch/arm/cpu/armv7/omap-common/spl.c b/arch/arm/cpu/armv7/omap-common/spl.c
index c76fea6..919d012 100644
--- a/arch/arm/cpu/armv7/omap-common/spl.c
+++ b/arch/arm/cpu/armv7/omap-common/spl.c
@@ -69,7 +69,7 @@  void spl_parse_image_header(const struct image_header *header)
 
 	if (__be32_to_cpu(header->ih_magic) == IH_MAGIC) {
 		spl_image.size = __be32_to_cpu(header->ih_size) + header_size;
-		spl_image.entry_point = __be32_to_cpu(header->ih_load);
+		spl_image.entry_point = __be32_to_cpu(header->ih_load_raw);
 		/* Load including the header */
 		spl_image.load_addr = spl_image.entry_point - header_size;
 		spl_image.os = header->ih_os;
diff --git a/arch/sh/lib/bootm.c b/arch/sh/lib/bootm.c
index 57273fa..71a42b1 100644
--- a/arch/sh/lib/bootm.c
+++ b/arch/sh/lib/bootm.c
@@ -72,7 +72,7 @@  int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima
 	void (*kernel) (void) = (void (*)(void))images->ep;
 	/* empty_zero_page */
 	unsigned char *param
-		= (unsigned char *)image_get_load(images->legacy_hdr_os);
+		= (unsigned char *)image_get_load_raw(images->legacy_hdr_os);
 	/* Linux kernel command line */
 	char *cmdline = (char *)param + COMMAND_LINE;
 	/* PAGE_SIZE */
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 5a03b1c..a1a80f0 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -214,7 +214,7 @@  static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 		images.os.os = image_get_os(os_hdr);
 
 		images.os.end = image_get_image_end(os_hdr);
-		images.os.load = image_get_load(os_hdr);
+		images.os.load = image_get_load_abs(os_hdr);
 		break;
 #if defined(CONFIG_FIT)
 	case IMAGE_FORMAT_FIT:
@@ -241,7 +241,8 @@  static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 
 		images.os.end = fit_get_end(images.fit_hdr_os);
 
-		if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os,
+		if (fit_image_get_load_abs(images.fit_hdr_os,
+					images.fit_noffset_os,
 					&images.os.load)) {
 			puts("Can't get image load address!\n");
 			show_boot_progress(-112);
@@ -256,10 +257,10 @@  static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 
 	/* find kernel entry point */
 	if (images.legacy_hdr_valid) {
-		images.ep = image_get_ep(&images.legacy_hdr_os_copy);
+		images.ep = image_get_ep_abs(&images.legacy_hdr_os_copy);
 #if defined(CONFIG_FIT)
 	} else if (images.fit_uname_os) {
-		ret = fit_image_get_entry(images.fit_hdr_os,
+		ret = fit_image_get_entry_abs(images.fit_hdr_os,
 				images.fit_noffset_os, &images.ep);
 		if (ret) {
 			puts("Can't get entry point property!\n");
@@ -272,6 +273,9 @@  static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 	}
 
 	if (((images.os.type == IH_TYPE_KERNEL) ||
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	     (images.os.type == IH_TYPE_KERNEL_REL) ||
+#endif
 	     (images.os.type == IH_TYPE_MULTI)) &&
 	    (images.os.os == IH_OS_LINUX)) {
 		/* find ramdisk */
@@ -796,7 +800,11 @@  static int fit_check_kernel(const void *fit, int os_noffset, int verify)
 	}
 
 	show_boot_progress(106);
-	if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL)) {
+	if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL)
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	    && !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_REL)
+#endif
+	    ) {
 		puts("Not a kernel image\n");
 		show_boot_progress(-106);
 		return 0;
@@ -874,6 +882,9 @@  static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 		/* get os_data and os_len */
 		switch (image_get_type(hdr)) {
 		case IH_TYPE_KERNEL:
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+		case IH_TYPE_KERNEL_REL:
+#endif
 			*os_data = image_get_data(hdr);
 			*os_len = image_get_data_size(hdr);
 			break;
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c
index 0414589..c53a326 100644
--- a/common/cmd_ximg.c
+++ b/common/cmd_ximg.c
@@ -237,7 +237,7 @@  do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 				 * which requires at most 2300 KB of memory.
 				 */
 				i = BZ2_bzBuffToBuffDecompress(
-					(char *)ntohl(hdr->ih_load),
+					(char *)ntohl(hdr->ih_load_raw),
 					&unc_len, (char *)data, len,
 					CONFIG_SYS_MALLOC_LEN < (4096 * 1024),
 					0);
diff --git a/common/image.c b/common/image.c
index 9b4d4ad..708ec67 100644
--- a/common/image.c
+++ b/common/image.c
@@ -133,7 +133,14 @@  static const table_entry_t uimage_type[] = {
 	{	IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image",	},
 	{	IH_TYPE_FIRMWARE,   "firmware",	  "Firmware",		},
 	{	IH_TYPE_FLATDT,     "flat_dt",    "Flat Device Tree",	},
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	{	IH_TYPE_FLATDT_REL, "flat_dt_rel",
+					    "Relative Flat Device Tree",},
+#endif
 	{	IH_TYPE_KERNEL,	    "kernel",	  "Kernel Image",	},
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	{	IH_TYPE_KERNEL_REL, "kernel_rel", "Relative Kernel Image",},
+#endif
 	{	IH_TYPE_MULTI,	    "multi",	  "Multi-File Image",	},
 	{	IH_TYPE_RAMDISK,    "ramdisk",	  "RAMDisk Image",	},
 	{	IH_TYPE_SCRIPT,     "script",	  "Script",		},
@@ -157,6 +164,9 @@  static const table_entry_t uimage_comp[] = {
 
 uint32_t crc32(uint32_t, const unsigned char *, uint);
 uint32_t crc32_wd(uint32_t, const unsigned char *, uint, uint);
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+static ulong image_addr_raw_to_abs(uint8_t type, ulong raw);
+#endif
 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
 static void genimg_print_time(time_t timestamp);
 #endif
@@ -188,6 +198,20 @@  int image_check_dcrc(const image_header_t *hdr)
 	return (dcrc == image_get_dcrc(hdr));
 }
 
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+uint32_t image_get_load_abs(const image_header_t *hdr)
+{
+	return image_addr_raw_to_abs(image_get_type(hdr),
+					image_get_load_raw(hdr));
+}
+
+uint32_t image_get_ep_abs(const image_header_t *hdr)
+{
+	return image_addr_raw_to_abs(image_get_type(hdr),
+					image_get_ep_raw(hdr));
+}
+#endif
+
 /**
  * image_multi_count - get component (sub-image) count
  * @hdr: pointer to the header of the multi component image
@@ -298,6 +322,10 @@  void image_print_contents(const void *ptr)
 {
 	const image_header_t *hdr = (const image_header_t *)ptr;
 	const char *p;
+	uint32_t abs;
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	uint32_t raw;
+#endif
 
 #ifdef USE_HOSTCC
 	p = "";
@@ -314,8 +342,24 @@  void image_print_contents(const void *ptr)
 	image_print_type(hdr);
 	printf("%sData Size:    ", p);
 	genimg_print_size(image_get_data_size(hdr));
-	printf("%sLoad Address: %08x\n", p, image_get_load(hdr));
-	printf("%sEntry Point:  %08x\n", p, image_get_ep(hdr));
+
+	abs = image_get_load_abs(hdr);
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	raw = image_get_load_raw(hdr);
+	if (abs != raw)
+		printf("%sLoad Address: %08x (relative %08x)\n", p, abs, raw);
+	else
+#endif
+		printf("%sLoad Address: %08x\n", p, abs);
+
+	abs = image_get_ep_abs(hdr);
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	raw = image_get_ep_raw(hdr);
+	if (abs != raw)
+		printf("%sEntry Point:  %08x (relative %08x)\n", p, abs, raw);
+	else
+#endif
+		printf("%sEntry Point:  %08x\n", p, abs);
 
 	if (image_check_type(hdr, IH_TYPE_MULTI) ||
 			image_check_type(hdr, IH_TYPE_SCRIPT)) {
@@ -425,6 +469,10 @@  ulong getenv_bootm_low(void)
 		return tmp;
 	}
 
+	/*
+	 * If this code changes, please modify the comments in image.h that
+	 * describe IH_TYPE_xxx_REL, in the "Image Types" list.
+	 */
 #if defined(CONFIG_SYS_SDRAM_BASE)
 	return CONFIG_SYS_SDRAM_BASE;
 #elif defined(CONFIG_ARM)
@@ -492,6 +540,20 @@  void memmove_wd(void *to, void *from, size_t len, ulong chunksz)
 }
 #endif /* !USE_HOSTCC */
 
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+ulong image_addr_raw_to_abs(uint8_t type, ulong raw)
+{
+	ulong abs = raw;
+
+#ifndef USE_HOSTCC
+	if (type == IH_TYPE_KERNEL_REL)
+		abs += getenv_bootm_low();
+#endif
+
+	return abs;
+}
+#endif
+
 void genimg_print_size(uint32_t size)
 {
 #ifndef USE_HOSTCC
@@ -900,7 +962,7 @@  int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 
 			rd_data = image_get_data(rd_hdr);
 			rd_len = image_get_data_size(rd_hdr);
-			rd_load = image_get_load(rd_hdr);
+			rd_load = image_get_load_raw(rd_hdr);
 			break;
 #if defined(CONFIG_FIT)
 		case IMAGE_FORMAT_FIT:
@@ -972,7 +1034,8 @@  int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 			rd_data = (ulong)data;
 			rd_len = size;
 
-			if (fit_image_get_load(fit_hdr, rd_noffset, &rd_load)) {
+			if (fit_image_get_load_raw(fit_hdr, rd_noffset,
+							&rd_load)) {
 				puts("Can't get ramdisk subimage load "
 					"address!\n");
 				show_boot_progress(-129);
@@ -1143,7 +1206,12 @@  static const image_header_t *image_get_fdt(ulong fdt_addr)
 	}
 	puts("OK\n");
 
-	if (!image_check_type(fdt_hdr, IH_TYPE_FLATDT)) {
+	if (!image_check_type(fdt_hdr, IH_TYPE_FLATDT)
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+
+	    && !image_check_type(fdt_hdr, IH_TYPE_FLATDT_REL)
+#endif
+	    ) {
 		fdt_error("uImage is not a fdt");
 		return NULL;
 	}
@@ -1185,7 +1253,11 @@  static int fit_check_fdt(const void *fit, int fdt_noffset, int verify)
 		puts("OK\n");
 	}
 
-	if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)) {
+	if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	    && !fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT_REL)
+#endif
+	    ) {
 		fdt_error("Not a FDT image");
 		return 0;
 	}
@@ -1474,7 +1546,7 @@  int boot_get_fdt(int flag, int argc, char * const argv[],
 			image_start = (ulong)fdt_hdr;
 			image_end = image_get_image_end(fdt_hdr);
 
-			load_start = image_get_load(fdt_hdr);
+			load_start = image_get_load_abs(fdt_hdr);
 			load_end = load_start + image_get_data_size(fdt_hdr);
 
 			if ((load_start < image_end) && (load_end > image_start)) {
@@ -1576,7 +1648,8 @@  int boot_get_fdt(int flag, int argc, char * const argv[],
 				image_start = (ulong)fit_hdr;
 				image_end = fit_get_end(fit_hdr);
 
-				if (fit_image_get_load(fit_hdr, fdt_noffset,
+				if (fit_image_get_load_abs(fit_hdr,
+							fdt_noffset,
 							&load_start) == 0) {
 					load_end = load_start + size;
 
@@ -1968,7 +2041,10 @@  void fit_image_print(const void *fit, int image_noffset, const char *p)
 	char *desc;
 	uint8_t type, arch, os, comp;
 	size_t size;
-	ulong load, entry;
+	ulong abs;
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	ulong raw;
+#endif
 	const void *data;
 	int noffset;
 	int ndepth;
@@ -2005,35 +2081,75 @@  void fit_image_print(const void *fit, int image_noffset, const char *p)
 		genimg_print_size(size);
 
 	/* Remaining, type dependent properties */
-	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
-	    (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
-	    (type == IH_TYPE_FLATDT)) {
+	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_FLATDT) ||
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	    (type == IH_TYPE_KERNEL_REL) || (type == IH_TYPE_FLATDT_REL) ||
+#endif
+	    (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK) ||
+	    (type == IH_TYPE_FIRMWARE)) {
 		fit_image_get_arch(fit, image_noffset, &arch);
 		printf("%s  Architecture: %s\n", p, genimg_get_arch_name(arch));
 	}
 
-	if (type == IH_TYPE_KERNEL) {
+	if ((type == IH_TYPE_KERNEL)
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	    || (type == IH_TYPE_KERNEL_REL)
+#endif
+	    ) {
 		fit_image_get_os(fit, image_noffset, &os);
 		printf("%s  OS:           %s\n", p, genimg_get_os_name(os));
 	}
 
-	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
-		(type == IH_TYPE_FIRMWARE)) {
-		ret = fit_image_get_load(fit, image_noffset, &load);
+	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_FLATDT) ||
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	    (type == IH_TYPE_KERNEL_REL) || (type == IH_TYPE_FLATDT_REL) ||
+#endif
+	    (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_FIRMWARE)) {
+		ret = fit_image_get_load_abs(fit, image_noffset, &abs);
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+		/*
+		 * fit_image_get_load_* return 0 on success, other on failure.
+		 * Oring two such values together yields something that's
+		 * still 0 on success, other on failure.
+		 */
+		ret |= fit_image_get_load_raw(fit, image_noffset, &raw);
+#endif
 		printf("%s  Load Address: ", p);
-		if (ret)
+		if (ret) {
 			printf("unavailable\n");
-		else
-			printf("0x%08lx\n", load);
+		} else {
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+			if (abs != raw)
+				printf("0x%08lx (relative 0x%08lx)\n",
+					abs, raw);
+			else
+#endif
+				printf("0x%08lx\n", abs);
+		}
 	}
 
-	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) {
-		fit_image_get_entry(fit, image_noffset, &entry);
+	if ((type == IH_TYPE_KERNEL) ||
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	    (type == IH_TYPE_KERNEL_REL) ||
+#endif
+	    (type == IH_TYPE_STANDALONE)) {
+		ret = fit_image_get_entry_abs(fit, image_noffset, &abs);
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+		/* See comment about fit_image_get_load_* above */
+		ret |= fit_image_get_entry_raw(fit, image_noffset, &raw);
+#endif
 		printf("%s  Entry Point:  ", p);
-		if (ret)
+		if (ret) {
 			printf("unavailable\n");
-		else
-			printf("0x%08lx\n", entry);
+		} else {
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+			if (abs != raw)
+				printf("0x%08lx (relative 0x%08lx)\n",
+					abs, raw);
+			else
+#endif
+				printf("0x%08lx\n", abs);
+		}
 	}
 
 	/* Process all hash subnodes of the component image node */
@@ -2320,20 +2436,25 @@  int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
 	return 0;
 }
 
-/**
- * fit_image_get_load - get load address property for a given component image node
+/*
+ * fit_image_get_load_raw - get raw load address property for a given
+ * component image node
  * @fit: pointer to the FIT format image header
  * @noffset: component image node offset
  * @load: pointer to the uint32_t, will hold load address
  *
- * fit_image_get_load() finds load address property in a given component image node.
- * If the property is found, its value is returned to the caller.
+ * fit_image_get_load_raw() finds load address property in a given component
+ * image node.  If the property is found, its value is returned to the caller.
+ *
+ * Note that this function returns the raw value encoded into the image file;
+ * the actual value U-Boot will use may be different for "relative" image
+ * formats.
  *
  * returns:
  *     0, on success
  *     -1, on failure
  */
-int fit_image_get_load(const void *fit, int noffset, ulong *load)
+int fit_image_get_load_raw(const void *fit, int noffset, ulong *load)
 {
 	int len;
 	const uint32_t *data;
@@ -2348,20 +2469,63 @@  int fit_image_get_load(const void *fit, int noffset, ulong *load)
 	return 0;
 }
 
-/**
- * fit_image_get_entry - get entry point address property for a given component image node
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+/*
+ * fit_image_get_load_abs - get absolute load address property for a given
+ * component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @load: pointer to the uint32_t, will hold load address
+ *
+ * fit_image_get_load_abs() finds load address property in a given component
+ *  image node. If the property is found, its value is returned to the caller.
+ *
+ * Note that this function returns the absolute value that U-Boot should
+ * use when actually loading images, or relocating them to the load address.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_load_abs(const void *fit, int noffset, ulong *load)
+{
+	int ret;
+	ulong raw;
+	uint8_t type;
+
+	ret = fit_image_get_load_raw(fit, noffset, &raw);
+	if (ret)
+		return ret;
+
+	ret = fit_image_get_type(fit, noffset, &type);
+	if (ret)
+		return ret;
+
+	*load = image_addr_raw_to_abs(type, raw);
+	return 0;
+}
+#endif
+
+/*
+ * fit_image_get_entry_raw - get raw entry point address property for a given
+ * component image node
  * @fit: pointer to the FIT format image header
  * @noffset: component image node offset
  * @entry: pointer to the uint32_t, will hold entry point address
  *
- * fit_image_get_entry() finds entry point address property in a given component image node.
- * If the property is found, its value is returned to the caller.
+ * fit_image_get_entry_raw() finds entry point address property in a given
+ * component image node.  If the property is found, its value is returned to
+ * the caller.
+ *
+ * Note that this function returns the raw value encoded into the image file;
+ * the actual value U-Boot will use may be different for "relative" image
+ * formats.
  *
  * returns:
  *     0, on success
  *     -1, on failure
  */
-int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
+int fit_image_get_entry_raw(const void *fit, int noffset, ulong *entry)
 {
 	int len;
 	const uint32_t *data;
@@ -2376,6 +2540,44 @@  int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
 	return 0;
 }
 
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+/*
+ * fit_image_get_entry_abs - get absolute entry point address property for a
+ * given component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @entry: pointer to the uint32_t, will hold entry point address
+ *
+ * fit_image_get_entry_abs() finds entry point address property in a given
+ * component image node.  If the property is found, its value is returned to
+ * the caller.
+ *
+ * Note that this function returns the absolute value that U-Boot should
+ * use when actually executing images.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_entry_abs(const void *fit, int noffset, ulong *ep)
+{
+	int ret;
+	ulong raw;
+	uint8_t type;
+
+	ret = fit_image_get_entry_raw(fit, noffset, &raw);
+	if (ret)
+		return ret;
+
+	ret = fit_image_get_type(fit, noffset, &type);
+	if (ret)
+		return ret;
+
+	*ep = image_addr_raw_to_abs(type, raw);
+	return 0;
+}
+#endif
+
 /**
  * fit_image_get_data - get data property and its size for a given component image node
  * @fit: pointer to the FIT format image header
diff --git a/common/lynxkdi.c b/common/lynxkdi.c
index 22ad384..59b4ad5 100644
--- a/common/lynxkdi.c
+++ b/common/lynxkdi.c
@@ -25,10 +25,10 @@  DECLARE_GLOBAL_DATA_PTR;
 #if defined(CONFIG_MPC8260) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
 void lynxkdi_boot(image_header_t *hdr)
 {
-	void (*lynxkdi)(void) = (void(*)(void))image_get_ep(hdr);
+	void (*lynxkdi)(void) = (void(*)(void))image_get_ep_raw(hdr);
 	lynxos_bootparms_t *parms = (lynxos_bootparms_t *)0x0020;
 	bd_t *kbd;
-	u32 *psz = (u32 *)(image_get_load(hdr) + 0x0204);
+	u32 *psz = (u32 *)(image_get_load_raw(hdr) + 0x0204);
 
 	memset(parms, 0, sizeof(*parms));
 	kbd = gd->bd;
@@ -43,7 +43,7 @@  void lynxkdi_boot(image_header_t *hdr)
 	/* FIXME: NOT SURE HERE ! */
 	if (le32_to_cpu(*psz) == image_get_data_size(hdr)) {
 		char *args;
-		char *cmdline = (char *)(image_get_load(hdr) + 0x020c);
+		char *cmdline = (char *)(image_get_load_raw(hdr) + 0x020c);
 		int len;
 
 		printf("Booting Bluecat KDI ...\n");
diff --git a/common/update.c b/common/update.c
index a19f136..b35ef91 100644
--- a/common/update.c
+++ b/common/update.c
@@ -230,7 +230,7 @@  static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
 	if (fit_image_get_data(fit, noffset, &data, (size_t *)size))
 		return 1;
 
-	if (fit_image_get_load(fit, noffset, (ulong *)fladdr))
+	if (fit_image_get_load_raw(fit, noffset, (ulong *)fladdr))
 		return 1;
 
 	*addr = (ulong)data;
diff --git a/include/image.h b/include/image.h
index 0d683ad..fa3bd1b 100644
--- a/include/image.h
+++ b/include/image.h
@@ -144,6 +144,14 @@ 
  *	U-Boot's command interpreter; this feature is especially
  *	useful when you configure U-Boot to use a real shell (hush)
  *	as command interpreter (=> Shell Scripts).
+ *
+ * Types named IH_TYPE_xxx_REL have load and entry point addresses specified
+ * relative to "the base of SDRAM", where that is specified as:
+ * a) CONFIG_SYS_SDRAM_BASE, if set.
+ * b) Otherwise, for ARM only, the start address of the first bank of SDRAM
+ *    known to U-Boot (i.e. gd->bd->bi_dram[0].start).
+ * c) Otherwise, 0.
+ * The exact algorithm is implemented in getenv_bootm_low() in image.c.
  */
 
 #define IH_TYPE_INVALID		0	/* Invalid Image		*/
@@ -159,6 +167,10 @@ 
 #define IH_TYPE_IMXIMAGE	10	/* Freescale IMXBoot Image	*/
 #define IH_TYPE_UBLIMAGE	11	/* Davinci UBL Image		*/
 #define IH_TYPE_OMAPIMAGE	12	/* TI OMAP Config Header Image	*/
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+#define IH_TYPE_KERNEL_REL	13	/* OS Kernel Image		*/
+#define IH_TYPE_FLATDT_REL	14	/* Binary Flat Device Tree Blob	*/
+#endif
 
 /*
  * Compression Types
@@ -181,8 +193,8 @@  typedef struct image_header {
 	uint32_t	ih_hcrc;	/* Image Header CRC Checksum	*/
 	uint32_t	ih_time;	/* Image Creation Timestamp	*/
 	uint32_t	ih_size;	/* Image Data Size		*/
-	uint32_t	ih_load;	/* Data	 Load  Address		*/
-	uint32_t	ih_ep;		/* Entry Point Address		*/
+	uint32_t	ih_load_raw;	/* Data	 Load  Address		*/
+	uint32_t	ih_ep_raw;	/* Entry Point Address		*/
 	uint32_t	ih_dcrc;	/* Image Data CRC Checksum	*/
 	uint8_t		ih_os;		/* Operating System		*/
 	uint8_t		ih_arch;	/* CPU architecture		*/
@@ -371,10 +383,25 @@  image_get_hdr_l(magic)		/* image_get_magic */
 image_get_hdr_l(hcrc)		/* image_get_hcrc */
 image_get_hdr_l(time)		/* image_get_time */
 image_get_hdr_l(size)		/* image_get_size */
-image_get_hdr_l(load)		/* image_get_load */
-image_get_hdr_l(ep)		/* image_get_ep */
+image_get_hdr_l(load_raw)	/* image_get_load_raw */
+image_get_hdr_l(ep_raw)	/* image_get_ep_raw */
 image_get_hdr_l(dcrc)		/* image_get_dcrc */
 
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+uint32_t image_get_load_abs(const image_header_t *hdr);
+uint32_t image_get_ep_abs(const image_header_t *hdr);
+#else
+static inline uint32_t image_get_load_abs(const image_header_t *hdr)
+{
+	return image_get_load_raw(hdr);
+}
+
+static inline uint32_t image_get_ep_abs(const image_header_t *hdr)
+{
+	return image_get_ep_raw(hdr);
+}
+#endif
+
 #define image_get_hdr_b(f) \
 	static inline uint8_t image_get_##f(const image_header_t *hdr) \
 	{ \
@@ -429,8 +456,8 @@  image_set_hdr_l(magic)		/* image_set_magic */
 image_set_hdr_l(hcrc)		/* image_set_hcrc */
 image_set_hdr_l(time)		/* image_set_time */
 image_set_hdr_l(size)		/* image_set_size */
-image_set_hdr_l(load)		/* image_set_load */
-image_set_hdr_l(ep)		/* image_set_ep */
+image_set_hdr_l(load_raw)	/* image_set_load_raw */
+image_set_hdr_l(ep_raw)	/* image_set_ep_raw */
 image_set_hdr_l(dcrc)		/* image_set_dcrc */
 
 #define image_set_hdr_b(f) \
@@ -579,11 +606,28 @@  int fit_image_get_os(const void *fit, int noffset, uint8_t *os);
 int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch);
 int fit_image_get_type(const void *fit, int noffset, uint8_t *type);
 int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp);
-int fit_image_get_load(const void *fit, int noffset, ulong *load);
-int fit_image_get_entry(const void *fit, int noffset, ulong *entry);
+int fit_image_get_load_raw(const void *fit, int noffset, ulong *load);
+int fit_image_get_entry_raw(const void *fit, int noffset, ulong *entry);
 int fit_image_get_data(const void *fit, int noffset,
 				const void **data, size_t *size);
 
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+int fit_image_get_load_abs(const void *fit, int noffset, ulong *load);
+int fit_image_get_entry_abs(const void *fit, int noffset, ulong *ep);
+#else
+static inline int fit_image_get_load_abs(const void *fit, int noffset,
+						ulong *load)
+{
+	return fit_image_get_load_raw(fit, noffset, load);
+}
+
+static inline int fit_image_get_entry_abs(const void *fit, int noffset,
+						ulong *ep)
+{
+	return fit_image_get_entry_raw(fit, noffset, ep);
+}
+#endif
+
 int fit_image_hash_get_algo(const void *fit, int noffset, char **algo);
 int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
 				int *value_len);
diff --git a/tools/default_image.c b/tools/default_image.c
index 6ea3b46..b54b461 100644
--- a/tools/default_image.c
+++ b/tools/default_image.c
@@ -35,7 +35,11 @@  static image_header_t header;
 
 static int image_check_image_types(uint8_t type)
 {
-	if ((type > IH_TYPE_INVALID) && (type < IH_TYPE_FLATDT))
+	if (((type > IH_TYPE_INVALID) && (type < IH_TYPE_FLATDT))
+#ifdef CONFIG_SYS_RELATIVE_IMAGES
+	    || (type == IH_TYPE_KERNEL_REL)
+#endif
+	    )
 		return EXIT_SUCCESS;
 	else
 		return EXIT_FAILURE;
@@ -113,8 +117,8 @@  static void image_set_header(void *ptr, struct stat *sbuf, int ifd,
 	image_set_magic(hdr, IH_MAGIC);
 	image_set_time(hdr, sbuf->st_mtime);
 	image_set_size(hdr, sbuf->st_size - sizeof(image_header_t));
-	image_set_load(hdr, params->addr);
-	image_set_ep(hdr, params->ep);
+	image_set_load_raw(hdr, params->addr);
+	image_set_ep_raw(hdr, params->ep);
 	image_set_dcrc(hdr, checksum);
 	image_set_os(hdr, params->os);
 	image_set_arch(hdr, params->arch);