Factorize bootstub makefile

Bug: 19708986

This patch aims to remove the huge code duplications in Android.mk and
also add a new kind of bootstub target: ramdump, which is used to boot a
post-crash OS with different memory constraints.

Change-Id: I962b48290994b75a44eb2e47487e1c1a8293f4df
Signed-off-by: Sylvain Chouleur <sylvain.chouleur@intel.com>
diff --git a/2ndbootloader.lds b/2ndbootloader.lds
index 547692d..5189d98 100644
--- a/2ndbootloader.lds
+++ b/2ndbootloader.lds
@@ -3,7 +3,7 @@
 ENTRY(_start)
 SECTIONS
 {
-	. = 0x10F00000;		/* bootstub entry in DRAM */
+	. = BOOTSTUB_ENTRY;		/* bootstub entry in DRAM */
 	.text.head : {
 		_head = . ;
 		*(.text.head)
diff --git a/Android.mk b/Android.mk
index 8a70a83..5dab544 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,107 +1,28 @@
 LOCAL_PATH := $(call my-dir)
 
-ifeq ($(TARGET_BOARD_PLATFORM),moorefield)
-
-CMDLINE_SIZE ?= 0x400
-BOOTSTUB_SIZE ?= 8192
-
-BOOTSTUB_SRC_FILES := bootstub.c sfi.c ssp-uart.c imr_toc.c spi-uart.c
-BOOTSTUB_SRC_FILES_x86 := head.S e820_bios.S
-
 include $(CLEAR_VARS)
-
 # bootstub.bin
-LOCAL_SRC_FILES := $(BOOTSTUB_SRC_FILES)
-LOCAL_SRC_FILES_x86 := $(BOOTSTUB_SRC_FILES_x86)
-ANDROID_TOOLCHAIN_FLAGS := -m32 -ffreestanding
-LOCAL_CFLAGS := $(ANDROID_TOOLCHAIN_FLAGS) -Wall -O1 -DCMDLINE_SIZE=${CMDLINE_SIZE}
-LOCAL_MODULE := bootstub.bin
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_FORCE_STATIC_EXECUTABLE := true
+BOOTSTUB_BINARY := bootstub
+BOOTSTUB_AOSP_HEADER_ADDRESS := 0x10007800
+BOOTSTUB_CFLAGS :=
+BOOTSTUB_STACK_OFFSET := 0X10F00000
+BOOTSTUB_ENTRY := 0x1101000
+include $(LOCAL_PATH)/bootstub.mk
 
-
-include $(BUILD_SYSTEM)/binary.mk
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CFLAGS := $(LOCAL_CFLAGS)
-$(LOCAL_BUILT_MODULE) : PRIVATE_ELF_FILE := $(intermediates)/$(PRIVATE_MODULE).elf
-$(LOCAL_BUILT_MODULE) : PRIVATE_LINK_SCRIPT := $(LOCAL_PATH)/bootstub.lds
-$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS := $(patsubst %.c, %.o , $(LOCAL_SRC_FILES))
-$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS += $(patsubst %.S, %.o , $(LOCAL_SRC_FILES_x86))
-$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS := $(addprefix $(intermediates)/, $(BOOTSTUB_OBJS))
-
-$(LOCAL_BUILT_MODULE): $(all_objects)
-	@$(mkdir -p $(dir $@)
-	@echo "Generating bootstub.bin: $@"
-	$(hide) $(TARGET_LD) \
-		-m elf_i386 \
-		-T $(PRIVATE_LINK_SCRIPT) \
-		$(BOOTSTUB_OBJS) \
-		-o $(PRIVATE_ELF_FILE)
-	$(hide) $(TARGET_OBJCOPY) -O binary -R .note -R .comment -S $(PRIVATE_ELF_FILE) $@
-
-# Then assemble the final bootstub file
-bootstub_bin := $(PRODUCT_OUT)/bootstub.bin
-bootstub_full := $(PRODUCT_OUT)/bootstub
-
-CHECK_BOOTSTUB_SIZE : $(bootstub_bin)
-	$(hide) ACTUAL_SIZE=`$(call get-file-size,$(bootstub_bin))`; \
-	if [ "$$ACTUAL_SIZE" -gt "$(BOOTSTUB_SIZE)" ]; then \
-		echo "$(bootstub_bin): $$ACTUAL_SIZE exceeds size limit of $(BOOTSTUB_SIZE) bytes, aborting."; \
-		exit 1; \
-	fi
-
-$(bootstub_full) : CHECK_BOOTSTUB_SIZE
-	@echo "Generating bootstub: $@"
-	$(hide) cat $(bootstub_bin) /dev/zero | dd bs=$(BOOTSTUB_SIZE) count=1 > $@
-
-# build specific bootstub for GPT/AOSP image support
 include $(CLEAR_VARS)
-
 # 2ndbootloader.bin
-LOCAL_SRC_FILES := $(BOOTSTUB_SRC_FILES)
-LOCAL_SRC_FILES_x86 := $(BOOTSTUB_SRC_FILES_x86)
-ANDROID_TOOLCHAIN_FLAGS := -m32 -ffreestanding
-LOCAL_CFLAGS := $(ANDROID_TOOLCHAIN_FLAGS) -Wall -O1 -DCMDLINE_SIZE=${CMDLINE_SIZE} -DBUILD_RAMDUMP
-LOCAL_MODULE := 2ndbootloader.bin
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_FORCE_STATIC_EXECUTABLE := true
+BOOTSTUB_BINARY := 2ndbootloader
+BOOTSTUB_AOSP_HEADER_ADDRESS := 0x10007800
+BOOTSTUB_CFLAGS :=
+BOOTSTUB_STACK_OFFSET := 0x10F00000
+BOOTSTUB_ENTRY := 0x10F00000
+include $(LOCAL_PATH)/bootstub.mk
 
-include $(BUILD_SYSTEM)/binary.mk
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CFLAGS := $(LOCAL_CFLAGS)
-$(LOCAL_BUILT_MODULE) : PRIVATE_ELF_FILE := $(intermediates)/$(PRIVATE_MODULE).elf
-$(LOCAL_BUILT_MODULE) : PRIVATE_LINK_SCRIPT := $(LOCAL_PATH)/2ndbootloader.lds
-$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS := $(patsubst %.c, %.o , $(LOCAL_SRC_FILES))
-$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS += $(patsubst %.S, %.o , $(LOCAL_SRC_FILES_x86))
-$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS := $(addprefix $(intermediates)/, $(BOOTSTUB_OBJS))
-
-$(LOCAL_BUILT_MODULE): $(all_objects)
-	@$(mkdir -p $(dir $@)
-	@echo "Generating bootstub $@"
-	$(hide) $(TARGET_LD) \
-		-m elf_i386 \
-		-T $(PRIVATE_LINK_SCRIPT) \
-		$(BOOTSTUB_OBJS) \
-		-o $(PRIVATE_ELF_FILE)
-	$(hide) $(TARGET_OBJCOPY) -O binary -R .note -R .comment -S $(PRIVATE_ELF_FILE) $@
-
-# Then assemble the final 2ndbootloader file
-bootstub_aosp_bin := $(PRODUCT_OUT)/2ndbootloader.bin
-bootstub_aosp_full := $(PRODUCT_OUT)/2ndbootloader
-
-CHECK_BOOTSTUB_AOSP_SIZE : $(bootstub_aosp_bin)
-	$(hide) ACTUAL_SIZE=`$(call get-file-size,$(bootstub_aosp_bin))`; \
-	if [ "$$ACTUAL_SIZE" -gt "$(BOOTSTUB_SIZE)" ]; then \
-		echo "$(bootstub_aosp_bin): $$ACTUAL_SIZE exceeds size limit of $(BOOTSTUB_SIZE) bytes, aborting."; \
-		exit 1; \
-	fi
-
-$(bootstub_aosp_full) : CHECK_BOOTSTUB_AOSP_SIZE
-	@echo "Generating bootstub $@"
-	$(hide) cat $(bootstub_aosp_bin) /dev/zero | dd bs=$(BOOTSTUB_SIZE) count=1 > $@
-
-endif #($(TARGET_BOARD_PLATFORM),moorefield)
+include $(CLEAR_VARS)
+# bootstub_ramdump.bin
+BOOTSTUB_BINARY := bootstub_ramdump
+BOOTSTUB_AOSP_HEADER_ADDRESS := 0x79000000
+BOOTSTUB_CFLAGS := -DBUILD_RAMDUMP
+BOOTSTUB_STACK_OFFSET := 0x78F00000
+BOOTSTUB_ENTRY := 0x78F00000
+include $(LOCAL_PATH)/bootstub.mk
diff --git a/bootimg.h b/bootimg.h
deleted file mode 100644
index 4c5d00c..0000000
--- a/bootimg.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _BOOT_IMAGE_H_
-#define _BOOT_IMAGE_H_
-
-typedef struct boot_img_hdr boot_img_hdr;
-
-#define BOOT_MAGIC "ANDROID!"
-#define BOOT_MAGIC_SIZE 8
-#define BOOT_NAME_SIZE 16
-#define BOOT_ARGS_SIZE 512
-
-struct boot_img_hdr
-{
-    unsigned char magic[BOOT_MAGIC_SIZE];
-
-    unsigned kernel_size;  /* size in bytes */
-    unsigned kernel_addr;  /* physical load addr */
-
-    unsigned ramdisk_size; /* size in bytes */
-    unsigned ramdisk_addr; /* physical load addr */
-
-    unsigned second_size;  /* size in bytes */
-    unsigned second_addr;  /* physical load addr */
-
-    unsigned tags_addr;    /* physical addr for kernel tags */
-    unsigned page_size;    /* flash page size we assume */
-    unsigned unused[2];    /* future expansion: should be 0 */
-
-    unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
-    unsigned char cmdline[BOOT_ARGS_SIZE];
-
-    unsigned 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
-*/
-
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
-                        void *ramdisk, unsigned ramdisk_size,
-                        void *second, unsigned second_size,
-                        unsigned page_size,
-                        unsigned *bootimg_size);
-
-void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
-#endif
diff --git a/bootstub.c b/bootstub.c
index c968d04..7c3dc49 100644
--- a/bootstub.c
+++ b/bootstub.c
@@ -1,5 +1,5 @@
 /*
- * bootstub 32 bit entry setting routings 
+ * bootstub 32 bit entry setting routings
  *
  * Copyright (C) 2008-2010 Intel Corporation.
  * Author: Alek Du <alek.du@intel.com>
@@ -14,7 +14,7 @@
  * more details.
  *
  * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 
+ * this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
@@ -26,7 +26,7 @@
 #include "ssp-uart.h"
 #include "mb.h"
 #include "sfi.h"
-#include "bootimg.h"
+#include <bootimg.h>
 
 #include <stdint.h>
 #include <stddef.h>
@@ -84,14 +84,14 @@
         char *xs = s;
 	size_t _count = count / 4;
 	unsigned long  _c = c << 24 | c << 16 | c << 8 | c;
- 
+
 	while (_count--) {
 		*(long *)xs = _c;
 		xs += 4;
 	}
 	count %= 4;
         while (count--)
-                *xs++ = c; 
+                *xs++ = c;
         return s;
 }
 
@@ -150,19 +150,21 @@
 {
 	void *cmdline = (void *)BOOT_CMDLINE_OFFSET;
 	struct boot_img_hdr *aosp = (struct boot_img_hdr *)AOSP_HEADER_ADDRESS;
-	size_t cmdline_len;
+	size_t cmdline_len, extra_cmdline_len;
 	u8 *initramfs, *ptr;
 
 	if (is_image_aosp(aosp->magic)) {
 		ptr = (u8*)aosp->kernel_addr;
 		cmdline_len = strnlen((const char *)aosp->cmdline, sizeof(aosp->cmdline));
+		extra_cmdline_len = strnlen((const char *)aosp->extra_cmdline, sizeof(aosp->extra_cmdline));
 
 		/*
-		* Copy the command line to be after bootparams so that it won't be
-		* overwritten by the kernel executable.
+		* Copy the command + extra command line to be after bootparams
+		* so that it won't be overwritten by the kernel executable.
 		*/
-		memset(cmdline, 0, sizeof(aosp->cmdline));
+		memset(cmdline, 0, sizeof(aosp->cmdline) + sizeof(aosp->extra_cmdline));
 		memcpy(cmdline, (const void *)aosp->cmdline, cmdline_len);
+		memcpy(cmdline + cmdline_len, (const void *)aosp->extra_cmdline, extra_cmdline_len);
 
 		bp->hdr.ramdisk_size = aosp->ramdisk_size;
 
@@ -184,6 +186,7 @@
 
 	bp->hdr.cmd_line_ptr = BOOT_CMDLINE_OFFSET;
 	bp->hdr.cmdline_size = cmdline_len;
+#ifndef BUILD_RAMDUMP
 	bp->hdr.ramdisk_image = (bp->alt_mem_k*1024 - bp->hdr.ramdisk_size) & 0xFFFFF000;
 
 	if (*initramfs) {
@@ -192,6 +195,9 @@
 	} else {
 		bs_printk("Won't relocate initramfs, are you in SLE?\n");
 	}
+#else
+	bp->hdr.ramdisk_image = (u32) initramfs;
+#endif
 
 	while (1){
 		if (*(u32 *)ptr == SETUP_SIGNATURE && *(u32 *)(ptr+4) == 0)
@@ -468,7 +474,8 @@
 	int nr_entries;
 
 	if (is_image_aosp(aosp->magic)) {
-		sh = (struct setup_header *)((unsigned  int)aosp->kernel_addr + 0x1F1);
+		sh = (struct setup_header *)((unsigned  int)aosp->kernel_addr + \
+		                             (unsigned  int)offsetof(struct boot_params,hdr));
 		/* disable the bs_printk through SPI/UART */
 		*(int *)SPI_UART_SUPPRESSION = 1;
 		*(int *)SPI_TYPE = SPI_2;
diff --git a/bootstub.h b/bootstub.h
index a109c09..799c1b3 100644
--- a/bootstub.h
+++ b/bootstub.h
@@ -1,4 +1,4 @@
-/* define bootstub constrains here, like memory map etc. 
+/* define bootstub constrains here, like memory map etc.
  */
 
 #ifndef _BOOT_STUB_HEAD
@@ -25,7 +25,6 @@
 #define BZIMAGE_SIZE_OFFSET	(CMDLINE_OFFSET + CMDLINE_SIZE)
 #define INITRD_SIZE_OFFSET	(BZIMAGE_SIZE_OFFSET + 4)
 #define SPI_UART_SUPPRESSION	(INITRD_SIZE_OFFSET + 4)
-#define AOSP_HEADER_ADDRESS     0x10007800
 
 #define SPI_TYPE		(SPI_UART_SUPPRESSION + 4) /*0:SPI0  1:SPI1*/
 #define SPI_0		0
@@ -39,7 +38,7 @@
 #define XEN_SIZE_OFFSET		(SEC_PLAT_SVCS_SIZE_OFFSET + 4)
 
 #define BOOTSTUB_OFFSET		(BASE_ADDRESS + 0x1000)
-#define STACK_OFFSET		0x10f00000
+
 #define BZIMAGE_OFFSET		(BASE_ADDRESS + 0x3000)
 
 #define SETUP_HEADER_OFFSET (BZIMAGE_OFFSET + 0x1F1)
diff --git a/bootstub.lds b/bootstub.lds
deleted file mode 100644
index 80c8771..0000000
--- a/bootstub.lds
+++ /dev/null
@@ -1,37 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")

-OUTPUT_ARCH(i386)

-ENTRY(_start)

-SECTIONS

-{

-	. = 0x1101000;		/* bootstub entry in DRAM */

-	.text.head : {

-		_head = . ;

-		*(.text.head)

-		_ehead = . ;

-	}

-	.text :	{

-		_text = .; 	/* Text */

-		*(.text)

-		*(.text.*)

-		_etext = . ;

-	}

-	.rodata : {

-		_rodata = . ;

-		*(.rodata)	 /* read-only data */

-		*(.rodata.*)

-		_erodata = . ;

-	}

-	.data :	{

-		_data = . ;

-		*(.data)

-		*(.data.*)

-		_edata = . ;

-	}

-	.bss : {

-		_bss = . ;

-		*(.bss)

-		*(.bss.*)

-		*(COMMON)

-		_end = . ;

-	}

-}

diff --git a/bootstub.mk b/bootstub.mk
new file mode 100644
index 0000000..56adcfe
--- /dev/null
+++ b/bootstub.mk
@@ -0,0 +1,60 @@
+CMDLINE_SIZE ?= 0x400
+BOOTSTUB_SIZE ?= 8192
+
+BOOTSTUB_SRC_FILES := bootstub.c sfi.c ssp-uart.c imr_toc.c spi-uart.c
+BOOTSTUB_SRC_FILES_x86 := head.S e820_bios.S
+
+ifeq ($(TARGET_IS_64_BIT),true)
+BOOTSTUB_2ND_ARCH_VAR_PREFIX := $(TARGET_2ND_ARCH_VAR_PREFIX)
+else
+BOOTSTUB_2ND_ARCH_VAR_PREFIX :=
+endif
+
+LOCAL_SRC_FILES := $(BOOTSTUB_SRC_FILES)
+LOCAL_SRC_FILES_x86 := $(BOOTSTUB_SRC_FILES_x86)
+ANDROID_TOOLCHAIN_FLAGS := -m32 -ffreestanding
+LOCAL_CFLAGS := $(ANDROID_TOOLCHAIN_FLAGS) -Wall -O1 -DCMDLINE_SIZE=${CMDLINE_SIZE} -DAOSP_HEADER_ADDRESS=$(BOOTSTUB_AOSP_HEADER_ADDRESS) $(BOOTSTUB_CFLAGS)
+LOCAL_ASFLAGS := -DSTACK_OFFSET=$(BOOTSTUB_STACK_OFFSET)
+LOCAL_C_INCLUDES = system/core/mkbootimg
+LOCAL_MODULE := $(BOOTSTUB_BINARY).bin
+LOCAL_MODULE_TAGS := optional
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(BOOTSTUB_2ND_ARCH_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/binary.mk
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CFLAGS := $(LOCAL_CFLAGS)
+$(LOCAL_BUILT_MODULE) : PRIVATE_ELF_FILE := $(intermediates)/$(PRIVATE_MODULE).elf
+$(LOCAL_BUILT_MODULE) : PRIVATE_LINK_SCRIPT := $(LOCAL_PATH)/2ndbootloader.lds
+$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS := $(patsubst %.c, %.o , $(LOCAL_SRC_FILES))
+$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS += $(patsubst %.S, %.o , $(LOCAL_SRC_FILES_x86))
+$(LOCAL_BUILT_MODULE) : BOOTSTUB_OBJS := $(addprefix $(intermediates)/, $(BOOTSTUB_OBJS))
+$(LOCAL_BUILT_MODULE) : BOOTSTUB_ENTRY := $(BOOTSTUB_ENTRY)
+
+$(LOCAL_BUILT_MODULE): $(all_objects)
+	$(hide) mkdir -p $(dir $@)
+	@echo "Generating bootstub.bin: $@"
+	$(hide) $(TARGET_LD) \
+		-m elf_i386 \
+		-T $(PRIVATE_LINK_SCRIPT) --defsym=BOOTSTUB_ENTRY=$(BOOTSTUB_ENTRY) \
+		$(BOOTSTUB_OBJS) \
+		-o $(PRIVATE_ELF_FILE)
+	$(hide) $(TARGET_OBJCOPY) -O binary -R .note -R .comment -S $(PRIVATE_ELF_FILE) $@
+
+# Then assemble the final bootstub file
+
+bootstub_full := $(PRODUCT_OUT)/$(BOOTSTUB_BINARY)
+$(BOOTSTUB_BINARY)_CHECK_BOOTSTUB_SIZE : $(LOCAL_BUILT_MODULE)
+	$(hide) ACTUAL_SIZE=`$(call get-file-size,$<)`; \
+	if [ "$$ACTUAL_SIZE" -gt "$(BOOTSTUB_SIZE)" ]; then \
+		echo "$<: $$ACTUAL_SIZE exceeds size limit of $(BOOTSTUB_SIZE) bytes, aborting."; \
+		exit 1; \
+	fi
+
+$(bootstub_full) : $(LOCAL_BUILT_MODULE) $(BOOTSTUB_BINARY)_CHECK_BOOTSTUB_SIZE
+	@echo "Generating bootstub: $@"
+	$(hide) cat $< /dev/zero | dd bs=$(BOOTSTUB_SIZE) count=1 > $@
+