diff --git a/common/Makefile b/common/Makefile
index 7c853ae4422bf331e98813555ffa2c0d62a02ce9..bfcb4664b7ba7f122670228cf990e4e01a17234a 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -237,6 +237,7 @@ obj-y += console.o
 obj-$(CONFIG_CROS_EC) += cros_ec.o
 obj-y += dlmalloc.o
 obj-y += image.o
+obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
 obj-$(CONFIG_OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_FIT) += image-fit.o
 obj-$(CONFIG_FIT_SIGNATURE) += image-sig.o
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index c243a5bd78a92ec55fb7d8f2feefe51f7fc9589a..993b906c70e3628b98511ef7548d7135d59ef1e3 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -222,6 +222,7 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
 			 char * const argv[])
 {
 	const void *os_hdr;
+	bool ep_found = false;
 
 	/* get kernel image header, start address and length */
 	os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
@@ -273,6 +274,18 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
 			return 1;
 		}
 		break;
+#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	case IMAGE_FORMAT_ANDROID:
+		images.os.type = IH_TYPE_KERNEL;
+		images.os.comp = IH_COMP_NONE;
+		images.os.os = IH_OS_LINUX;
+		images.ep = images.os.load;
+		ep_found = true;
+
+		images.os.end = android_image_get_end(os_hdr);
+		images.os.load = android_image_get_kload(os_hdr);
+		break;
 #endif
 	default:
 		puts("ERROR: unknown image format type!\n");
@@ -293,7 +306,7 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
 			return 1;
 		}
 #endif
-	} else {
+	} else if (!ep_found) {
 		puts("Could not find kernel entry point!\n");
 		return 1;
 	}
@@ -1001,6 +1014,14 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 		images->fit_uname_cfg = fit_uname_config;
 		images->fit_noffset_os = os_noffset;
 		break;
+#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	case IMAGE_FORMAT_ANDROID:
+		printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
+		if (android_image_get_kernel((void *)img_addr, images->verify,
+					     os_data, os_len))
+			return NULL;
+		break;
 #endif
 	default:
 		printf("Wrong Image Format for %s command\n", cmdtp->name);
diff --git a/common/image-android.c b/common/image-android.c
new file mode 100644
index 0000000000000000000000000000000000000000..6ded7e2c97ef6d0925895b3439d0f18c694e6562
--- /dev/null
+++ b/common/image-android.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <image.h>
+#include <android_image.h>
+
+static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1];
+
+int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
+			     ulong *os_data, ulong *os_len)
+{
+	/*
+	 * Not all Android tools use the id field for signing the image with
+	 * sha1 (or anything) so we don't check it. It is not obvious that the
+	 * string is null terminated so we take care of this.
+	 */
+	strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE);
+	andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0';
+	if (strlen(andr_tmp_str))
+		printf("Android's image name: %s\n", andr_tmp_str);
+
+	printf("Kernel load addr 0x%08x size %u KiB\n",
+	       hdr->kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
+	strncpy(andr_tmp_str, hdr->cmdline, ANDR_BOOT_ARGS_SIZE);
+	andr_tmp_str[ANDR_BOOT_ARGS_SIZE] = '\0';
+	if (strlen(andr_tmp_str)) {
+		printf("Kernel command line: %s\n", andr_tmp_str);
+		setenv("bootargs", andr_tmp_str);
+	}
+	if (hdr->ramdisk_size)
+		printf("RAM disk load addr 0x%08x size %u KiB\n",
+		       hdr->ramdisk_addr,
+		       DIV_ROUND_UP(hdr->ramdisk_size, 1024));
+
+	if (os_data) {
+		*os_data = (ulong)hdr;
+		*os_data += hdr->page_size;
+	}
+	if (os_len)
+		*os_len = hdr->kernel_size;
+	return 0;
+}
+
+int android_image_check_header(const struct andr_img_hdr *hdr)
+{
+	return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE);
+}
+
+ulong android_image_get_end(const struct andr_img_hdr *hdr)
+{
+	u32 size = 0;
+	/*
+	 * The header takes a full page, the remaining components are aligned
+	 * on page boundary
+	 */
+	size += hdr->page_size;
+	size += ALIGN(hdr->kernel_size, hdr->page_size);
+	size += ALIGN(hdr->ramdisk_size, hdr->page_size);
+	size += ALIGN(hdr->second_size, hdr->page_size);
+
+	return size;
+}
+
+ulong android_image_get_kload(const struct andr_img_hdr *hdr)
+{
+	return hdr->kernel_addr;
+}
+
+int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
+			      ulong *rd_data, ulong *rd_len)
+{
+	if (!hdr->ramdisk_size)
+		return -1;
+	*rd_data = (unsigned long)hdr;
+	*rd_data += hdr->page_size;
+	*rd_data += ALIGN(hdr->kernel_size, hdr->page_size);
+
+	*rd_len = hdr->ramdisk_size;
+	return 0;
+}
diff --git a/common/image.c b/common/image.c
index 9c6bec5b769ceb1834ffa978827c89609ad8402f..7ff27d75c385c5d75c8d3d877107847942d8c81e 100644
--- a/common/image.c
+++ b/common/image.c
@@ -659,10 +659,12 @@ int genimg_get_format(const void *img_addr)
 	if (image_check_magic(hdr))
 		format = IMAGE_FORMAT_LEGACY;
 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
-	else {
-		if (fdt_check_header(img_addr) == 0)
-			format = IMAGE_FORMAT_FIT;
-	}
+	else if (fdt_check_header(img_addr) == 0)
+		format = IMAGE_FORMAT_FIT;
+#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	else if (android_image_check_header(img_addr) == 0)
+		format = IMAGE_FORMAT_ANDROID;
 #endif
 
 	return format;
@@ -932,7 +934,15 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 				(ulong)images->legacy_hdr_os);
 
 		image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len);
-	} else {
+	}
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	else if ((genimg_get_format(images) == IMAGE_FORMAT_ANDROID) &&
+		 (!android_image_get_ramdisk((void *)images->os.start,
+		 &rd_data, &rd_len))) {
+		/* empty */
+	}
+#endif
+	else {
 		/*
 		 * no initrd image
 		 */
diff --git a/include/android_image.h b/include/android_image.h
new file mode 100644
index 0000000000000000000000000000000000000000..094d60afe8e65e436ef4333c0fe96fd0ca19cfa6
--- /dev/null
+++ b/include/android_image.h
@@ -0,0 +1,69 @@
+/*
+ * This is from the Android Project,
+ * Repository: https://android.googlesource.com/platform/bootable/bootloader/legacy
+ * File: include/boot/bootimg.h
+ * Commit: 4205b865141ff2e255fe1d3bd16de18e217ef06a
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _ANDROID_IMAGE_H_
+#define _ANDROID_IMAGE_H_
+
+#define ANDR_BOOT_MAGIC "ANDROID!"
+#define ANDR_BOOT_MAGIC_SIZE 8
+#define ANDR_BOOT_NAME_SIZE 16
+#define ANDR_BOOT_ARGS_SIZE 512
+
+struct andr_img_hdr {
+	char magic[ANDR_BOOT_MAGIC_SIZE];
+
+	u32 kernel_size;	/* size in bytes */
+	u32 kernel_addr;	/* physical load addr */
+
+	u32 ramdisk_size;	/* size in bytes */
+	u32 ramdisk_addr;	/* physical load addr */
+
+	u32 second_size;	/* size in bytes */
+	u32 second_addr;	/* physical load addr */
+
+	u32 tags_addr;		/* physical addr for kernel tags */
+	u32 page_size;		/* flash page size we assume */
+	u32 unused[2];		/* future expansion: should be 0 */
+
+	char name[ANDR_BOOT_NAME_SIZE]; /* asciiz product name */
+
+	char cmdline[ANDR_BOOT_ARGS_SIZE];
+
+	u32 id[8]; /* timestamp / checksum / sha1 / etc */
+};
+
+/*
+ * +-----------------+
+ * | boot header     | 1 page
+ * +-----------------+
+ * | kernel          | n pages
+ * +-----------------+
+ * | ramdisk         | m pages
+ * +-----------------+
+ * | second stage    | o pages
+ * +-----------------+
+ *
+ * n = (kernel_size + page_size - 1) / page_size
+ * m = (ramdisk_size + page_size - 1) / page_size
+ * o = (second_size + page_size - 1) / page_size
+ *
+ * 0. all entities are page_size aligned in flash
+ * 1. kernel and ramdisk are required (size != 0)
+ * 2. second is optional (second_size == 0 -> no second)
+ * 3. load each element (kernel, ramdisk, second) at
+ *    the specified physical address (kernel_addr, etc)
+ * 4. prepare tags at tag_addr.  kernel_args[] is
+ *    appended to the kernel commandline in the tags.
+ * 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+ * 6. if second_size != 0: jump to second_addr
+ *    else: jump to kernel_addr
+ */
+#endif
diff --git a/include/image.h b/include/image.h
index 2508d7d2430f100a91741f862655d227c91e169b..e1f92979a460642a1e4c503bd202e8704d9d5eb2 100644
--- a/include/image.h
+++ b/include/image.h
@@ -412,6 +412,7 @@ enum fit_load_op {
 #define IMAGE_FORMAT_INVALID	0x00
 #define IMAGE_FORMAT_LEGACY	0x01	/* legacy image_header based format */
 #define IMAGE_FORMAT_FIT	0x02	/* new, libfdt based format */
+#define IMAGE_FORMAT_ANDROID	0x03	/* Android boot image */
 
 int genimg_get_format(const void *img_addr);
 int genimg_has_config(bootm_headers_t *images);
@@ -1030,4 +1031,16 @@ static inline int fit_image_check_target_arch(const void *fdt, int node)
 #endif /* CONFIG_FIT_VERBOSE */
 #endif /* CONFIG_FIT */
 
+#if defined(CONFIG_ANDROID_BOOT_IMAGE)
+struct andr_img_hdr;
+int android_image_check_header(const struct andr_img_hdr *hdr);
+int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
+			     ulong *os_data, ulong *os_len);
+int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
+			      ulong *rd_data, ulong *rd_len);
+ulong android_image_get_end(const struct andr_img_hdr *hdr);
+ulong android_image_get_kload(const struct andr_img_hdr *hdr);
+
+#endif /* CONFIG_ANDROID_BOOT_IMAGE */
+
 #endif	/* __IMAGE_H__ */