bootstub support for aosp and legacy

The code searches for the AOSP header at a specified location.
If found, it performs all the required memcpy by using the
addresses and size provided in the AOSP header instead of those
hardcoded into bootstub.h.
Otherwise, it processes as usual for an OSII image.
Change the bootstub output to $(PRODUCT_OUT)/2ndbootloader

Change-Id: I25da96f99b2a01f457d3f8b8393080f9ec562c94
Signed-off-by: Florent Auger <florent.auger@intel.com>
Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Signed-off-by: Jocelyn Falempe <jocelyn.falempe@intel.com>
Reviewed-on: https://android.intel.com/215921
Reviewed-by: Betous, GuillaumeX <guillaumex.betous@intel.com>
diff --git a/2ndbootloader.lds b/2ndbootloader.lds
new file mode 100644
index 0000000..547692d
--- /dev/null
+++ b/2ndbootloader.lds
@@ -0,0 +1,37 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x10F00000;		/* 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/Android.mk b/Android.mk
index 73f89d6..a8ab4d8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -53,3 +53,55 @@
 $(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)
+
+# First compile 2ndbootloader.bin
+
+LOCAL_CC := gcc
+LOCAL_SRC_FILES := bootstub.c head.S e820_bios.S sfi.c ssp-uart.c imr_toc.c spi-uart.c
+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
+
+head.o : PRIVATE_CFLAGS := -D__ASSEMBLY__
+
+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 , $(BOOTSTUB_OBJS))
+$(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 bootstub 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 > $@
diff --git a/bootimg.h b/bootimg.h
new file mode 100644
index 0000000..4c5d00c
--- /dev/null
+++ b/bootimg.h
@@ -0,0 +1,96 @@
+/*
+ * 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 e89acce..74b87f9 100644
--- a/bootstub.c
+++ b/bootstub.c
@@ -26,6 +26,7 @@
 #include "ssp-uart.h"
 #include "mb.h"
 #include "sfi.h"
+#include "bootimg.h"
 
 #include <stdint.h>
 #include <stddef.h>
@@ -129,6 +130,11 @@
 	return 0;
 }
 
+static inline int is_image_aosp(unsigned char *magic)
+{
+	return !strncmp((char *)magic, (char *)BOOT_MAGIC, sizeof(BOOT_MAGIC)-1);
+}
+
 static void setup_boot_params(struct boot_params *bp, struct setup_header *sh)
 {
 	bp->screen_info.orig_video_mode = 0;
@@ -143,25 +149,43 @@
 static u32 bzImage_setup(struct boot_params *bp, struct setup_header *sh)
 {
 	void *cmdline = (void *)BOOT_CMDLINE_OFFSET;
+	struct boot_img_hdr *aosp = (struct boot_img_hdr *)AOSP_HEADER_ADDRESS;
 	size_t cmdline_len;
-	u8 *initramfs, *ptr = (u8*)BZIMAGE_OFFSET;
+	u8 *initramfs, *ptr;
 
+	if (is_image_aosp(aosp->magic)) {
+		ptr = (u8*)aosp->kernel_addr;
+		cmdline_len = strnlen((const char *)aosp->cmdline, sizeof(aosp->cmdline));
 
-	cmdline_len = strnlen((const char *)CMDLINE_OFFSET, CMDLINE_SIZE);
+		/*
+		* Copy the command line to be after bootparams so that it won't be
+		* overwritten by the kernel executable.
+		*/
+		memset(cmdline, 0, sizeof(aosp->cmdline));
+		memcpy(cmdline, (const void *)aosp->cmdline, cmdline_len);
 
-	/*
-	 * Copy the command line to be after bootparams so that it won't be
-	 * overwritten by the kernel executable.
-	 */
-	memset(cmdline, 0, CMDLINE_SIZE);
-	memcpy(cmdline, (const void *)CMDLINE_OFFSET, cmdline_len);
+		bp->hdr.ramdisk_size = aosp->ramdisk_size;
+
+		initramfs = (u8 *)aosp->ramdisk_addr;
+	} else {
+		ptr = (u8*)BZIMAGE_OFFSET;
+		cmdline_len = strnlen((const char *)CMDLINE_OFFSET, CMDLINE_SIZE);
+		/*
+		 * Copy the command line to be after bootparams so that it won't be
+		 * overwritten by the kernel executable.
+		 */
+		memset(cmdline, 0, CMDLINE_SIZE);
+		memcpy(cmdline, (const void *)CMDLINE_OFFSET, cmdline_len);
+
+		bp->hdr.ramdisk_size = *(u32 *)INITRD_SIZE_OFFSET;
+
+		initramfs = (u8 *)BZIMAGE_OFFSET + *(u32 *)BZIMAGE_SIZE_OFFSET;
+	}
 
 	bp->hdr.cmd_line_ptr = BOOT_CMDLINE_OFFSET;
 	bp->hdr.cmdline_size = cmdline_len;
-	bp->hdr.ramdisk_size = *(u32 *)INITRD_SIZE_OFFSET;
 	bp->hdr.ramdisk_image = (bp->alt_mem_k*1024 - bp->hdr.ramdisk_size) & 0xFFFFF000;
 
-	initramfs = (u8 *)BZIMAGE_OFFSET + *(u32 *)BZIMAGE_SIZE_OFFSET;
 	if (*initramfs) {
 		bs_printk("Relocating initramfs to high memory ...\n");
 		memcpy((u8*)bp->hdr.ramdisk_image, initramfs, bp->hdr.ramdisk_size);
@@ -449,15 +473,24 @@
 int bootstub(void)
 {
 	u32 jmp;
+	struct boot_img_hdr *aosp = (struct boot_img_hdr *)AOSP_HEADER_ADDRESS;
 	struct boot_params *bp = (struct boot_params *)BOOT_PARAMS_OFFSET;
-	struct setup_header *sh = (struct setup_header *)SETUP_HEADER_OFFSET;
+	struct setup_header *sh;
 	u32 imr_size;
 	int nr_entries;
 
-        setup_idt();
+	if (is_image_aosp(aosp->magic)) {
+		sh = (struct setup_header *)((unsigned  int)aosp->kernel_addr + 0x1F1);
+		/* disable the bs_printk through SPI/UART */
+		*(int *)SPI_UART_SUPPRESSION = 1;
+		*(int *)SPI_TYPE = SPI_2;
+	} else
+		sh = (struct setup_header *)SETUP_HEADER_OFFSET;
+
+	setup_idt();
 	setup_gdt();
 	setup_spi();
-	bs_printk("Bootstub Version: 1.3 ...\n");
+	bs_printk("Bootstub Version: 1.4 ...\n");
 
 	memset(bp, 0, sizeof (struct boot_params));
 
diff --git a/bootstub.h b/bootstub.h
index 0d4845a..a109c09 100644
--- a/bootstub.h
+++ b/bootstub.h
@@ -19,25 +19,28 @@
 #define MID_CPU_CHIP_ANNIEDALE	6
 #define MID_CPU_CHIP_OTHER		0xFF
 
-#define CMDLINE_OFFSET		0x1100000
+#define BASE_ADDRESS		0x01100000
+
+#define CMDLINE_OFFSET		BASE_ADDRESS
 #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
 #define SPI_1		1
 #define SPI_2		2
 
-
 #define FLAGS_RESERVED_0	(SPI_TYPE + 4)
 #define FLAGS_RESERVED_1	(FLAGS_RESERVED_0 + 4)
 #define VXE_FW_SIZE_OFFSET		(FLAGS_RESERVED_1 + 4)
 #define SEC_PLAT_SVCS_SIZE_OFFSET	(VXE_FW_SIZE_OFFSET + 4)
 #define XEN_SIZE_OFFSET		(SEC_PLAT_SVCS_SIZE_OFFSET + 4)
 
-#define BOOTSTUB_OFFSET		0x1101000
-#define STACK_OFFSET		BOOTSTUB_OFFSET
-#define BZIMAGE_OFFSET		0x1103000
+#define BOOTSTUB_OFFSET		(BASE_ADDRESS + 0x1000)
+#define STACK_OFFSET		0x10f00000
+#define BZIMAGE_OFFSET		(BASE_ADDRESS + 0x3000)
 
 #define SETUP_HEADER_OFFSET (BZIMAGE_OFFSET + 0x1F1)
 #define SETUP_HEADER_SIZE (0x0202 + *(unsigned char*)(0x0201+BZIMAGE_OFFSET))