[coreboot-gerrit] New patch to review for coreboot: a34ce9e ipq806x: Load TZBSP blob from coreboot ramstage

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Tue Apr 14 15:32:02 CEST 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9690

-gerrit

commit a34ce9e263e6aea0848cca1af9d55c44b0c9059f
Author: Vikas Das <vdas at codeaurora.org>
Date:   Mon Sep 22 17:49:56 2014 -0700

    ipq806x: Load TZBSP blob from coreboot ramstage
    
    Read the TZBSP blob from CBFS and run it. A side effect of the blob
    execution is switching of the processor into User mode.
    
    Starting TZBSP requires processor running in Supervisor mode, TZBSP
    code is compiled for ARM. Coreboot is executing in System mode and is
    compiled for Thumb. An assembler wrapper switches the execution mode
    and inrefaces between Thumb and ARM modes.
    
    BUG=chrome-os-partner:34161
    BRANCH=Storm
    TEST=manual
      With the preceeding patches the system successfully loads to
      depthcharge in recovery mode.
    
    Change-Id: I812b5cef95ba5562a005e005162d6391e502ecf8
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 7065cf3d17964a1d9038ec8906b469a08a79c6e2
    Original-Change-Id: Ib14dbcbcbe489b595f4247d489d50f76a0e65948
    Original-Signed-off-by: Varadarajan Narayanan <varada at qti.qualcomm.com>
    Original-Signed-off-by: Vadim Bendebury <vbendeb at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/229026
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
---
 src/mainboard/google/storm/mainboard.c             |   2 +
 src/soc/qualcomm/ipq806x/Makefile.inc              |   2 +
 src/soc/qualcomm/ipq806x/blobs_init.c              |  56 +++++++----
 src/soc/qualcomm/ipq806x/include/soc/memlayout.ld  |   4 +-
 .../qualcomm/ipq806x/include/soc/soc_services.h    |   5 +
 src/soc/qualcomm/ipq806x/tz_wrapper.S              | 106 +++++++++++++++++++++
 6 files changed, 156 insertions(+), 19 deletions(-)

diff --git a/src/mainboard/google/storm/mainboard.c b/src/mainboard/google/storm/mainboard.c
index 3ed2c7f..5abf2f7 100644
--- a/src/mainboard/google/storm/mainboard.c
+++ b/src/mainboard/google/storm/mainboard.c
@@ -24,6 +24,7 @@
 #include <device/device.h>
 #include <gpio.h>
 #include <soc/clock.h>
+#include <soc/soc_services.h>
 #include <soc/usb.h>
 #include <symbols.h>
 
@@ -109,6 +110,7 @@ static void assert_sw_reset(void)
 
 static void mainboard_init(device_t dev)
 {
+	 start_tzbsp();
 	 setup_mmu();
 	 setup_usb();
 	 assert_sw_reset();
diff --git a/src/soc/qualcomm/ipq806x/Makefile.inc b/src/soc/qualcomm/ipq806x/Makefile.inc
index 7fb6290..e0f014a 100644
--- a/src/soc/qualcomm/ipq806x/Makefile.inc
+++ b/src/soc/qualcomm/ipq806x/Makefile.inc
@@ -40,6 +40,7 @@ romstage-y += timer.c
 romstage-$(CONFIG_DRIVERS_UART) += uart.c
 romstage-y += cbmem.c
 
+ramstage-y += blobs_init.c
 ramstage-y += cbmem.c
 ramstage-y += clock.c
 ramstage-y += gpio.c
@@ -48,6 +49,7 @@ ramstage-$(CONFIG_SPI_FLASH) += spi.c
 ramstage-y += timer.c
 ramstage-$(CONFIG_DRIVERS_UART) += uart.c
 ramstage-y += usb.c
+ramstage-y += tz_wrapper.S
 
 ifeq ($(CONFIG_USE_BLOBS),y)
 
diff --git a/src/soc/qualcomm/ipq806x/blobs_init.c b/src/soc/qualcomm/ipq806x/blobs_init.c
index 96a14dc..24f9e64 100644
--- a/src/soc/qualcomm/ipq806x/blobs_init.c
+++ b/src/soc/qualcomm/ipq806x/blobs_init.c
@@ -27,10 +27,11 @@
 
 #include "mbn_header.h"
 
-static struct mbn_header *map_ipq_blob(const char *file_name)
+static void *load_ipq_blob(const char *file_name)
 {
 	struct cbfs_file *blob_file;
 	struct mbn_header *blob_mbn;
+	void *blob_dest;
 
 	blob_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, file_name);
 	if (!blob_file)
@@ -44,35 +45,56 @@ static struct mbn_header *map_ipq_blob(const char *file_name)
 	    (blob_mbn->mbn_total_size > ntohl(blob_file->len)))
 		return NULL;
 
-	return blob_mbn;
+	blob_dest = (void *) blob_mbn->mbn_destination;
+	if (blob_mbn->mbn_destination) {
+		/* Copy the blob to the appropriate memory location. */
+		memcpy(blob_dest, blob_mbn + 1, blob_mbn->mbn_total_size);
+		cache_sync_instructions();
+		return blob_dest;
+	}
+
+	/*
+	 * The blob did not have to be relocated, return its address in CBFS
+	 * cache.
+	 */
+	return blob_mbn + 1;
 }
 
+#ifdef __PRE_RAM__
+
 int initialize_dram(void)
 {
-	struct mbn_header *cdt_mbn;
-	struct mbn_header *ddr_mbn;
+	void *cdt;
 	int (*ddr_init_function)(void *cdt_header);
 
-	cdt_mbn = map_ipq_blob("cdt.mbn");
-	ddr_mbn = map_ipq_blob("ddr.mbn");
+	cdt = load_ipq_blob("cdt.mbn");
+	ddr_init_function = load_ipq_blob("ddr.mbn");
 
-	if (!cdt_mbn || !ddr_mbn) {
-		printk(BIOS_ERR, "cdt.mbn: %p, ddr.mbn: %p\n",
-		       cdt_mbn, ddr_mbn);
+	if (!cdt || !ddr_init_function) {
+		printk(BIOS_ERR, "cdt: %p, ddr_init_function: %p\n",
+		       cdt, ddr_init_function);
 		die("could not find DDR initialization blobs\n");
 	}
 
-	/* Actual area where DDR init is going to be running */
-	ddr_init_function = (int (*)(void *))ddr_mbn->mbn_destination;
-
-	/* Copy core into the appropriate memory location. */
-	memcpy(ddr_init_function, ddr_mbn + 1, ddr_mbn->mbn_total_size);
-	cache_sync_instructions();
-
-	if (ddr_init_function(cdt_mbn + 1) < 0) /* Skip mbn header. */
+	if (ddr_init_function(cdt) < 0)
 		die("Fail to Initialize DDR\n");
 
 	printk(BIOS_INFO, "DDR initialized\n");
 
 	return 0;
 }
+
+#else  /* __PRE_RAM__ ^^^^^^ defined, vvvvvvvv NOT defined */
+
+void start_tzbsp(void)
+{
+	void *tzbsp = load_ipq_blob("tz.mbn");
+
+	if (!tzbsp)
+		die("could not find or map TZBSP\n");
+
+	tz_init_wrapper(0, 0, tzbsp);
+}
+
+#endif  /* __PRE_RAM__ ^^^^^^ NOT defined */
+
diff --git a/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld b/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld
index 873f61c..6a0d6ad 100644
--- a/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld
+++ b/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld
@@ -54,9 +54,9 @@ SECTIONS
 
 	DRAM_START(0x40000000)
 	RAMSTAGE(0x40640000, 128K)
-	SYMBOL(memlayout_cbmem_top, 0x59FA0000)
+	SYMBOL(memlayout_cbmem_top, 0x59F80000)
 #ifndef __PRE_RAM__
-	CBFS_CACHE(0x59FA0000, 256K)
+	CBFS_CACHE(0x59F80000, 384K)
 #endif
 	DMA_COHERENT(0x5A000000, 2M)
 }
diff --git a/src/soc/qualcomm/ipq806x/include/soc/soc_services.h b/src/soc/qualcomm/ipq806x/include/soc/soc_services.h
index 9e92bc7..b852d7f 100644
--- a/src/soc/qualcomm/ipq806x/include/soc/soc_services.h
+++ b/src/soc/qualcomm/ipq806x/include/soc/soc_services.h
@@ -27,4 +27,9 @@ extern u8 _memlayout_cbmem_top[];
 /* Returns zero on success, nonzero on failure. */
 int initialize_dram(void);
 
+/* Loads and runs TZBSP, switches into user mode. */
+void start_tzbsp(void);
+
+int tz_init_wrapper(int, int, void *);
+
 #endif
diff --git a/src/soc/qualcomm/ipq806x/tz_wrapper.S b/src/soc/qualcomm/ipq806x/tz_wrapper.S
new file mode 100644
index 0000000..4470b04
--- /dev/null
+++ b/src/soc/qualcomm/ipq806x/tz_wrapper.S
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * TZ expects the ARM core to be in 'ARM' mode. However, Coreboot seems
+ * to be compiled in mixed thumb/arm mode. Hence create a glue function
+ * to invoke TZ.
+ */
+
+#include <arch/asm.h>
+
+/*
+ * Force ARM mode. Else this gets assembled with mixed ARM and
+ * Thumb instructions. We setup everything and jump to TZBSP
+ * using the 'blx' instruction. For 'blx' if the last bit of the
+ * destination address is zero, it switches to ARM mode. Since,
+ * we are already in ARM mode, nothing to switch as such.
+ *
+ * However, when TZBSP returns, the CPU is still in ARM mode.
+ * If the assembler inserts Thumb instructions between the point
+ * of return from TZBSP to the 'bx' instruction we are hosed.
+ * Hence forcing ARM mode.
+ *
+ * Rest of the code can be compiled in mixed ARM/Thumb mode.
+ * Since tz_init_wrapper is being forced as an ARM symbol,
+ * callers will use 'blx' to come here forcing a switch to
+ * ARM mode. The wrapper does its job and returns back to the
+ * Thumb caller.
+ */
+.arm
+/*
+ * int tz_init_wrapper(int, int, void *);
+ */
+ENTRY(tz_init_wrapper)
+	.global tz_init_wrapper
+
+	/*
+	 *      r0 = tz_arg1
+	 *      r1 = tz_arg2
+	 *      r2 = tz_load_addr
+	 */
+
+	/*
+	 * Per the AAPCS
+	 *	r0, r1, r2, r3, r12 can be clobbered
+	 *	r4, r5, r6, r7, r8, r9, r10, r11 have to be preserved
+	 *
+	 * Following code clobbers
+	 *	r0 - Setting return value to zero
+	 *	r1 - For doing a thumb return
+	 *	r3 - Passing 'SP' from current mode to 'svc' mode
+	 *	r4 - To save & restore CPSR
+	 *
+	 * Per AAPCS, save and restore r4, rest are 'clobberable' :)
+	 * The invoked code takes care of saving and restoring the other
+	 * preserved registers (i.e. r5 - r11)
+	 *
+	 * Stack Usage:
+	 *	SP ->	| LR	|	(Lower address)
+	 *		| r4	|
+	 *		| CPSR	|
+	 *		|-------|
+	 *		|   .   |
+	 *		|   .   |
+	 *		|   .   |	(Higher address)
+	 */
+
+	sub	sp, sp, #12	/* Allocate stack frame */
+	str	lr, [sp]	/* Save return address */
+	str	r4, [sp, #4]	/* Use r4 to hold the new CPSR value */
+
+	mov	r3, sp		/* Get current stack pointer */
+
+	mrs	r4, CPSR	/* save CPSR */
+	str	r4, [sp, #8]
+
+	bic	r4, r4, 0x1f	/* Clear mode bits */
+	orr	r4, r4, 0x13	/* 'svc' mode */
+	msr	cpsr_cxf, r4	/* Switch to Supervisor mode. */
+	mov	sp, r3		/* Use the same stack as the previous mode */
+
+	blx	r2		/* Jump to TZ in ARM mode */
+
+	nop			/* back from TZ, in ARM mode */
+
+	ldr	r4, [sp, #8]	/* restore CPSR */
+	msr	cpsr_cxf, r4
+
+	ldr	r4, [sp, #4]	/* restore r4 */
+
+	ldr	lr, [sp]	/* saved return address */
+	add	sp, sp, #12	/* free stack frame */
+
+	bx	lr		/* back to thumb caller */
+
+ENDPROC(tz_init_wrapper)



More information about the coreboot-gerrit mailing list