Skip to contentSkip to conversation

Fastboot gadget, v2

U-Boot New Sebastian Andrzej Siewior 3 participants 10 messages Sep 20, 2011 – Feb 29, 2012 USB

lore
Share & tools
lore
#0 lore raw

This series contains a smaller version of the fastboot gadget. I removed the flash/mmc/write to media part and re-add once I'm through with this basic thing :)
This "basic" gadget supports the retrieval of variables (like serial number), reboot functionality, download of binary data and booting them in case the binary data is a bootable image.
I did not include the fastboot client in this series. Remy asked about this. I could take it and stash it in tools if someone really wants this to have. This would include the fastboot and libzipfile folder from Andorid's system/core repository. An online version can be found at [0]. I haven't seen the library somewhere else than Android. For basic testing, the library could be excluded.

v1..v2:
fixed all issues that came up so far, including:
- s/andoir_img_get_kload/android_img_get_kload/ spotted by Mike
- adjusted Copyright message to GPLv2 or later for f_fastboot.c and removed "change" comments.
- removed two header files in example patch 3/3
I believe that the "All rights reserved" problem got resolved.

[0] http://www.netmite.com/android/mydroid/system/core/

Sebastian

#1 lore raw

PATCH v2 1/3 image: add support for Android's boot image format

This patch adds support for the Android boot-image format. The header file is from the Android project and got slightly alterted so the struct + its defines are not generic but have something like a namespace. The header file is from bootloader/legacy/include/boot/bootimg.h. The header parsing has been written from scratch and I looked at bootloader/legacy/usbloader/usbloader.c for some details.
The image contains the physical address (load address) of the kernel and ramdisk. This address is considered only for the kernel image. The "second image" is currently ignored. I haven't found anything that is creating this.

---
 common/cmd_bootm.c      |   87 +++++++++++++++++++++++++++++++++++++++++++++-
 common/image.c          |   17 +++++++++
 include/android_image.h |   89 +++++++++++++++++++++++++++++++++++++++++++++++
 include/image.h         |    4 ++
 4 files changed, 196 insertions(+), 1 deletions(-)
 create mode 100644 include/android_image.h
common/cmd_bootm.c +86 -1
index 272d879..ec9bf39 100644
@@ -36,6 +36,7 @@
 #include <lmb.h>
 #include <linux/ctype.h>
 #include <asm/byteorder.h>
+#include <android_image.h>
 
 #if defined(CONFIG_CMD_USB)
 #include <usb.h>
@@ -211,10 +212,33 @@ static void bootm_start_lmb(void)
 #endif
 }
 
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+static u32 android_img_get_end(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;
+}
+
+static u32 android_img_get_kload(struct andr_img_hdr *hdr)
+{
+	return hdr->kernel_addr;
+}
+#endif
+
 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	void		*os_hdr;
 	int		ret;
+	int		img_type;
 
 	memset ((void *)&images, 0, sizeof (images));
 	images.verify = getenv_yesno ("verify");
@@ -230,7 +254,8 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 	}
 
 	/* get image parameters */
-	switch (genimg_get_format (os_hdr)) {
+	img_type = genimg_get_format(os_hdr);
+	switch (img_type) {
 	case IMAGE_FORMAT_LEGACY:
 		images.os.type = image_get_type (os_hdr);
 		images.os.comp = image_get_comp (os_hdr);
@@ -272,6 +297,16 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 		}
 		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.os.end = android_img_get_end(os_hdr);
+		images.os.load = android_img_get_kload(os_hdr);
+		break;
+#endif
 	default:
 		puts ("ERROR: unknown image format type!\n");
 		return 1;
@@ -289,6 +324,10 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 			return 1;
 		}
 #endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	} else if (img_type == IMAGE_FORMAT_ANDROID) {
+		images.ep = images.os.load;
+#endif
 	} else {
 		puts ("Could not find kernel entry point!\n");
 		return 1;
@@ -821,6 +860,36 @@ static int fit_check_kernel (const void *fit, int os_noffset, int verify)
 }
 #endif /* CONFIG_FIT */
 
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1];
+static int android_image_get_kernel(struct andr_img_hdr *hdr, int verify)
+{
+	/*
+	 * 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));
+	return 0;
+}
+#endif
+
 /**
  * boot_get_kernel - find kernel image
  * @os_data: pointer to a ulong variable, will hold os data start address
@@ -847,6 +916,9 @@ static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char * const
 	int		cfg_noffset;
 	int		os_noffset;
 #endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	struct andr_img_hdr *ahdr;
+#endif
 
 	/* find out kernel image address */
 	if (argc < 2) {
@@ -980,6 +1052,19 @@ static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char * const
 		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);
+		ahdr = (void *)img_addr;
+		if (android_image_get_kernel(ahdr, images->verify))
+			return NULL;
+
+		*os_data = img_addr;
+		*os_data += ahdr->page_size;
+		*os_len = ahdr->kernel_size;
+		images->ahdr = ahdr;
+		break;
+#endif
 	default:
 		printf ("Wrong Image Format for %s command\n", cmdtp->name);
 		show_boot_progress (-108);
common/image.c +17 -0
index 5eea2a1..12b3ec5 100644
@@ -26,6 +26,7 @@
 #ifndef USE_HOSTCC
 #include <common.h>
 #include <watchdog.h>
+#include <android_image.h>
 
 #ifdef CONFIG_SHOW_BOOT_PROGRESS
 #include <status_led.h>
@@ -671,7 +672,14 @@ int genimg_get_format (void *img_addr)
 			format = IMAGE_FORMAT_FIT;
 	}
 #endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	else {
+		const struct andr_img_hdr *ahdr = img_addr;
 
+		if (!memcmp(ANDR_BOOT_MAGIC, ahdr->magic, ANDR_BOOT_MAGIC_SIZE))
+			format = IMAGE_FORMAT_ANDROID;
+	}
+#endif
 	return format;
 }
 
@@ -993,6 +1001,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);
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+		if (images->ahdr && images->ahdr->ramdisk_size) {
+			rd_data = (unsigned long) images->ahdr;
+			rd_data += images->ahdr->page_size;
+			rd_data += ALIGN(images->ahdr->kernel_size,
+					images->ahdr->page_size);
+			rd_len = images->ahdr->ramdisk_size;
+		}
+#endif
 	} else {
 		/*
 		 * no initrd image
include/android_image.h new file +89 -0

89 lines not on this page · raw message

include/image.h +4 -0
index 352e4a0..4360d73 100644
@@ -261,6 +261,9 @@ typedef struct bootm_headers {
 #ifdef CONFIG_LMB
 	struct lmb	lmb;		/* for memory mgmt */
 #endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	struct andr_img_hdr	*ahdr;
+#endif
 } bootm_headers_t;
 
 /*
@@ -326,6 +329,7 @@ void genimg_print_size (uint32_t size);
 #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 (void *img_addr);
 int genimg_has_config (bootm_headers_t *images);
Signature · 1 line
1.7.6.3
#2 lore raw

PATCH v2 1/3 image: add support for Android's boot image format

Quoted 11 lines · * Sebastian Andrzej Siewior | 2011-09-20 16:02:01 [+0200]:

This patch adds support for the Android boot-image format. The header file is from the Android project and got slightly alterted so the struct + its defines are not generic but have something like a namespace. The header file is from bootloader/legacy/include/boot/bootimg.h. The header parsing has been written from scratch and I looked at bootloader/legacy/usbloader/usbloader.c for some details.
The image contains the physical address (load address) of the kernel and ramdisk. This address is considered only for the kernel image. The "second image" is currently ignored. I haven't found anything that is creating this.

Quoted 2 lines

ping

Sebastian

#3 lore raw

PATCH v2 1/3 image: add support for Android's boot image format

Quoted 13 lines · Sebastian Andrzej Siewior
Quoted 11 lines · * Sebastian Andrzej Siewior | 2011-09-20 16:02:01 [+0200]:

This patch adds support for the Android boot-image format. The header file is from the Android project and got slightly alterted so the struct + its defines are not generic but have something like a namespace. The header file is from bootloader/legacy/include/boot/bootimg.h. The header parsing has been written from scratch and I looked at bootloader/legacy/usbloader/usbloader.c for some details.
The image contains the physical address (load address) of the kernel and ramdisk. This address is considered only for the kernel image. The "second image" is currently ignored. I haven't found anything that is creating this.

Quoted 4 lines
Quoted 2 lines

ping

Wonder what happened to this series. Is this ready to be merged this merge window? If so, who is going to merge it in the absence of a USB custodian?

br,
Aneesh

#4 lore raw

PATCH v2 1/3 image: add support for Android's boot image format

Quoted 5 lines · * Aneesh V | 2011-12-29 13:13:29 [+0530]:
Quoted 1 line

ping

Wonder what happened to this series. Is this ready to be merged this merge window? If so, who is going to merge it in the absence of a USB custodian?

I've sent the series and Wolfgang kept nacking it due to some GPL vs BSD license incompatibilities which seem to exist. The FSF's license page claims the there is no such problem and I also don't see any. So we are stuck.

Quoted 2 lines

br,
Aneesh

Sebastian

#5 lore raw

PATCH v2 2/3 usb/gadget: add the fastboot gadget

In reply to Sebastian Andrzej Siewior

This patch contains an implementation of the fastboot protocol on the device side and a little of documentation.
The gadget expects the new-style gadget framework.
The gadget implements the getvar, reboot, download and reboot commands. What is missing is the flash handling i.e. writting the image to media.

---
 common/Makefile                      |    2 +
 common/cmd_fastboot.c                |   28 ++
 doc/README.android-fastboot          |   86 ++++++
 doc/README.android-fastboot-protocol |  170 ++++++++++
 drivers/usb/gadget/Makefile          |    5 +
 drivers/usb/gadget/f_fastboot.c      |  559 ++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/g_fastboot.h      |   20 ++
 drivers/usb/gadget/u_fastboot.c      |  308 +++++++++++++++++++
 include/usb/fastboot.h               |  100 ++++++
 9 files changed, 1278 insertions(+), 0 deletions(-)
 create mode 100644 common/cmd_fastboot.c
 create mode 100644 doc/README.android-fastboot
 create mode 100644 doc/README.android-fastboot-protocol
 create mode 100644 drivers/usb/gadget/f_fastboot.c
 create mode 100644 drivers/usb/gadget/g_fastboot.h
 create mode 100644 drivers/usb/gadget/u_fastboot.c
 create mode 100644 include/usb/fastboot.h
common/Makefile +2 -0
index d662468..da40d64 100644
@@ -157,6 +157,8 @@ COBJS-y += cmd_usb.o
 COBJS-y += usb.o
 COBJS-$(CONFIG_USB_STORAGE) += usb_storage.o
 endif
+COBJS-$(CONFIG_CMD_FASTBOOT) += cmd_fastboot.o
+
 COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o
 COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o
 
common/cmd_fastboot.c new file +28 -0
new file mode 100644
index 0000000..9a656dd
@@ -0,0 +1,28 @@
+#include <common.h>
+#include <command.h>
+#include <usb/fastboot.h>
+
+static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	int ret = 1;
+
+	if (!fastboot_init()) {
+		printf("Fastboot entered...\n");
+
+		ret = 0;
+
+		while (1) {
+			if (fastboot_poll())
+				break;
+		}
+	}
+
+	fastboot_shutdown();
+	return ret;
+}
+
+U_BOOT_CMD(
+	fastboot,	1,	1,	do_fastboot,
+	"fastboot- use USB Fastboot protocol\n",
+	""
+);
doc/README.android-fastboot new file +86 -0

86 lines not on this page · raw message

doc/README.android-fastboot-protocol new file +170 -0

170 lines not on this page · raw message

drivers/usb/gadget/Makefile +5 -0
index 7d5b504..75d4a12 100644
@@ -42,6 +42,11 @@ COBJS-$(CONFIG_SPEARUDC) += spr_udc.o
 endif
 endif
 
+ifdef CONFIG_CMD_FASTBOOT
+COBJS-y += f_fastboot.o u_fastboot.o
+COBJS-y += epautoconf.o usbstring.o
+endif
+
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
drivers/usb/gadget/f_fastboot.c new file +559 -0

559 lines not on this page · raw message

drivers/usb/gadget/g_fastboot.h new file +20 -0
new file mode 100644
index 0000000..ff2621c
@@ -0,0 +1,20 @@
+#ifndef _G_FASTBOOT_H_
+#define _G_FASTBOOT_H_
+
+#define EP_BUFFER_SIZE			4096
+#define FASTBOOT_INTERFACE_CLASS	0xff
+#define FASTBOOT_INTERFACE_SUB_CLASS	0x42
+#define FASTBOOT_INTERFACE_PROTOCOL	0x03
+#define FASTBOOT_VERSION		"0.4"
+
+extern struct fastboot_config fb_cfg;
+extern struct usb_ep *ep_in;
+extern struct usb_request *req_in;
+extern struct usb_ep *ep_out;
+extern struct usb_request *req_out;
+
+void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
+int fastboot_tx_write(const char *buffer, unsigned int buffer_size);
+const char *fb_find_usb_string(unsigned int id);
+
+#endif
drivers/usb/gadget/u_fastboot.c new file +308 -0

308 lines not on this page · raw message

include/usb/fastboot.h new file +100 -0

100 lines not on this page · raw message

Signature · 1 line
1.7.6.3
#6 lore raw

PATCH v2 3/3 fastboot: add board specific implementation

In reply to Sebastian Andrzej Siewior

This is just an example how the board specific implementation can look like.

---
 board/ti/sdp4430/Makefile   |    7 ++++---
 board/ti/sdp4430/fastboot.c |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 3 deletions(-)
 create mode 100644 board/ti/sdp4430/fastboot.c
board/ti/sdp4430/Makefile +4 -3
index 12f2743..89226ab 100644
@@ -26,11 +26,12 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(BOARD).o
 
 ifndef CONFIG_SPL_BUILD
-COBJS	:= sdp.o cmd_bat.o
+COBJS-y	:= sdp.o cmd_bat.o
+COBJS-$(CONFIG_CMD_FASTBOOT)	+= fastboot.o
 endif
 
-SRCS	:= $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS))
+SRCS	:= $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
 
 $(LIB):	$(obj).depend $(OBJS)
 	$(call cmd_link_o_target, $(OBJS))
board/ti/sdp4430/fastboot.c new file +34 -0
new file mode 100644
index 0000000..2dd276c
@@ -0,0 +1,34 @@
+#include <common.h>
+#include <usb/fastboot.h>
+
+static struct usb_string def_usb_fb_strings[] = {
+	{ FB_STR_SERIAL_IDX,            "abcd+efg" },
+	{ FB_STR_PROC_REV_IDX,          "ES0.0" },
+	{ FB_STR_PROC_TYPE_IDX,         "VirtIO" },
+	{  }
+};
+
+static struct usb_gadget_strings def_fb_strings = {
+	.language       = 0x0409, /* en-us */
+	.strings        = def_usb_fb_strings,
+};
+
+/*
+ * Hardcoded memory region to stash data which comes over USB before it is
+ * stored on media
+ */
+DECLARE_GLOBAL_DATA_PTR;
+#define SZ_16M                          0x01000000
+#define SZ_128M                         0x08000000
+#define CFG_FASTBOOT_TRANSFER_BUFFER (void *)(gd->bd->bi_dram[0].start + SZ_16M)
+#define CFG_FASTBOOT_TRANSFER_BUFFER_SIZE (SZ_128M - SZ_16M)
+
+int fastboot_board_init(struct fastboot_config *interface,
+		struct usb_gadget_strings **str) {
+
+	interface->transfer_buffer = CFG_FASTBOOT_TRANSFER_BUFFER;
+	interface->transfer_buffer_size = CFG_FASTBOOT_TRANSFER_BUFFER_SIZE;
+
+	*str = &def_fb_strings;
+	return 0;
+}
Signature · 1 line
1.7.6.3
#7 lore raw
In reply to Sebastian Andrzej Siewior
Quoted 13 lines

This series contains a smaller version of the fastboot gadget. I removed the flash/mmc/write to media part and re-add once I'm through with this basic thing :)
This "basic" gadget supports the retrieval of variables (like serial number), reboot functionality, download of binary data and booting them in case the binary data is a bootable image.
I did not include the fastboot client in this series. Remy asked about this. I could take it and stash it in tools if someone really wants this to have. This would include the fastboot and libzipfile folder from Andorid's system/core repository. An online version can be found at [0]. I haven't seen the library somewhere else than Android. For basic testing, the library could be excluded.

Quoted 7 lines

v1..v2:
fixed all issues that came up so far, including:
- s/andoir_img_get_kload/android_img_get_kload/ spotted by Mike
- adjusted Copyright message to GPLv2 or later for f_fastboot.c and removed "change" comments.
- removed two header files in example patch 3/3
I believe that the "All rights reserved" problem got resolved.

Hi,

what's the status of this patch/patchset?

Thanks
M

#8 lore raw
Quoted 1 line · * Marek Vasut | 2012-02-27 00:09:16 [+0100]:

Hi,

Hi,

Quoted 1 line

what's the status of this patch/patchset?

the status is that Wolfgang wants me to change the license to GPLv2 because he thinks that the BSD license is not compatible with GPLv2 or later and I can't. I can't change the copyright because I don't hold copyright on those files like the header file. For instance I haven't found any documentation on the file format which is only described in the header file. The header file is only available under BSD license (not accepted by Wolfgang) and under Apache v2 (not compatible with GPLv2 but with GPLv3 according FSF).

So unless
- Wolfgang changes his opinion on GPLv2 vs BSD license or
- we get the code relicensed by Google or
- we get some documentation under a reasonable license and (can)
re-implement it from scratch

I don't see any movement here.

Quoted 2 lines

Thanks
M

Sebastian

#9 lore raw
Quoted 10 lines · * Marek Vasut | 2012-02-27 00:09:16 [+0100]:
Quoted 1 line

Hi,

Hi,

Quoted 1 line

what's the status of this patch/patchset?

the status is that Wolfgang wants me to change the license to GPLv2 because he thinks that the BSD license is not compatible with GPLv2 or later and I can't.

It'd certainly be very preferable to make it GPLv2.

Quoted 7 lines

I can't change the copyright because I don't hold copyright on those files like the header file. For instance I haven't found any documentation on the file format which is only described in the header file. The header file is only available under BSD license (not accepted by Wolfgang) and under Apache v2 (not compatible with GPLv2 but with GPLv3 according FSF).

I see, this is troublesome.

Quoted 3 lines

So unless
- Wolfgang changes his opinion on GPLv2 vs BSD license or
- we get the code relicensed by Google or

Maybe you can try contacting these people to add another license?

Quoted 2 lines

- we get some documentation under a reasonable license and (can)
re-implement it from scratch

That'd put unnecessary strain on everybode.

Quoted 2 lines

I don't see any movement here.

I see, let's try solving this as well as possible.

Thanks for your effort so far!

Cheers!

M