~funderscore blog cgit wiki get in touch
aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/aarch64/early_exceptions.S171
-rw-r--r--common/bl_common.c432
-rw-r--r--common/debug.c102
-rw-r--r--common/fip.c248
-rw-r--r--common/memtest.c369
5 files changed, 1322 insertions, 0 deletions
diff --git a/common/aarch64/early_exceptions.S b/common/aarch64/early_exceptions.S
new file mode 100644
index 0000000..90f5421
--- /dev/null
+++ b/common/aarch64/early_exceptions.S
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * 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 HOLDER 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.
+ */
+
+#include <asm_macros.S>
+#include <runtime_svc.h>
+
+ .globl early_exceptions
+
+ .section .vectors, "ax"; .align 11
+
+ /* -----------------------------------------------------
+ * Very simple stackless exception handlers used by BL2
+ * and BL3-1 bootloader stages. BL3-1 uses them before
+ * stacks are setup. BL2 uses them throughout.
+ * -----------------------------------------------------
+ */
+ .align 7
+early_exceptions:
+ /* -----------------------------------------------------
+ * Current EL with SP0 : 0x0 - 0x180
+ * -----------------------------------------------------
+ */
+SynchronousExceptionSP0:
+ mov x0, #SYNC_EXCEPTION_SP_EL0
+ bl plat_report_exception
+ b SynchronousExceptionSP0
+ check_vector_size SynchronousExceptionSP0
+
+ .align 7
+IrqSP0:
+ mov x0, #IRQ_SP_EL0
+ bl plat_report_exception
+ b IrqSP0
+ check_vector_size IrqSP0
+
+ .align 7
+FiqSP0:
+ mov x0, #FIQ_SP_EL0
+ bl plat_report_exception
+ b FiqSP0
+ check_vector_size FiqSP0
+
+ .align 7
+SErrorSP0:
+ mov x0, #SERROR_SP_EL0
+ bl plat_report_exception
+ b SErrorSP0
+ check_vector_size SErrorSP0
+
+ /* -----------------------------------------------------
+ * Current EL with SPx: 0x200 - 0x380
+ * -----------------------------------------------------
+ */
+ .align 7
+SynchronousExceptionSPx:
+ mov x0, #SYNC_EXCEPTION_SP_ELX
+ bl plat_report_exception
+ b SynchronousExceptionSPx
+ check_vector_size SynchronousExceptionSPx
+
+ .align 7
+IrqSPx:
+ mov x0, #IRQ_SP_ELX
+ bl plat_report_exception
+ b IrqSPx
+ check_vector_size IrqSPx
+
+ .align 7
+FiqSPx:
+ mov x0, #FIQ_SP_ELX
+ bl plat_report_exception
+ b FiqSPx
+ check_vector_size FiqSPx
+
+ .align 7
+SErrorSPx:
+ mov x0, #SERROR_SP_ELX
+ bl plat_report_exception
+ b SErrorSPx
+ check_vector_size SErrorSPx
+
+ /* -----------------------------------------------------
+ * Lower EL using AArch64 : 0x400 - 0x580
+ * -----------------------------------------------------
+ */
+ .align 7
+SynchronousExceptionA64:
+ mov x0, #SYNC_EXCEPTION_AARCH64
+ bl plat_report_exception
+ b SynchronousExceptionA64
+ check_vector_size SynchronousExceptionA64
+
+ .align 7
+IrqA64:
+ mov x0, #IRQ_AARCH64
+ bl plat_report_exception
+ b IrqA64
+ check_vector_size IrqA64
+
+ .align 7
+FiqA64:
+ mov x0, #FIQ_AARCH64
+ bl plat_report_exception
+ b FiqA64
+ check_vector_size FiqA64
+
+ .align 7
+SErrorA64:
+ mov x0, #SERROR_AARCH64
+ bl plat_report_exception
+ b SErrorA64
+ check_vector_size SErrorA64
+
+ /* -----------------------------------------------------
+ * Lower EL using AArch32 : 0x0 - 0x180
+ * -----------------------------------------------------
+ */
+ .align 7
+SynchronousExceptionA32:
+ mov x0, #SYNC_EXCEPTION_AARCH32
+ bl plat_report_exception
+ b SynchronousExceptionA32
+ check_vector_size SynchronousExceptionA32
+
+ .align 7
+IrqA32:
+ mov x0, #IRQ_AARCH32
+ bl plat_report_exception
+ b IrqA32
+ check_vector_size IrqA32
+
+ .align 7
+FiqA32:
+ mov x0, #FIQ_AARCH32
+ bl plat_report_exception
+ b FiqA32
+ check_vector_size FiqA32
+
+ .align 7
+SErrorA32:
+ mov x0, #SERROR_AARCH32
+ bl plat_report_exception
+ b SErrorA32
+ check_vector_size SErrorA32
diff --git a/common/bl_common.c b/common/bl_common.c
new file mode 100644
index 0000000..f0d32d0
--- /dev/null
+++ b/common/bl_common.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * 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 HOLDER 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.
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+unsigned long page_align(unsigned long value, unsigned dir)
+{
+ unsigned long page_size = 1 << FOUR_KB_SHIFT;
+
+ /* Round up the limit to the next page boundary */
+ if (value & (page_size - 1)) {
+ value &= ~(page_size - 1);
+ if (dir == UP)
+ value += page_size;
+ }
+
+ return value;
+}
+
+static inline unsigned int is_page_aligned (unsigned long addr) {
+ const unsigned long page_size = 1 << FOUR_KB_SHIFT;
+
+ return (addr & (page_size - 1)) == 0;
+}
+
+void change_security_state(unsigned int target_security_state)
+{
+ unsigned long scr = read_scr();
+
+ if (target_security_state == SECURE)
+ scr &= ~SCR_NS_BIT;
+ else if (target_security_state == NON_SECURE)
+ scr |= SCR_NS_BIT;
+ else
+ assert(0);
+
+ write_scr(scr);
+}
+
+
+/*******************************************************************************
+ * The next function has a weak definition. Platform specific code can override
+ * it if it wishes to.
+ ******************************************************************************/
+#pragma weak init_bl2_mem_layout
+
+/*******************************************************************************
+ * Function that takes a memory layout into which BL2 has been either top or
+ * bottom loaded along with the address where BL2 has been loaded in it. Using
+ * this information, it populates bl2_mem_layout to tell BL2 how much memory
+ * it has access to and how much is available for use.
+ ******************************************************************************/
+void init_bl2_mem_layout(meminfo_t *bl1_mem_layout,
+ meminfo_t *bl2_mem_layout,
+ unsigned int load_type,
+ unsigned long bl2_base)
+{
+ unsigned tmp;
+
+ if (load_type == BOT_LOAD) {
+ bl2_mem_layout->total_base = bl2_base;
+ tmp = bl1_mem_layout->free_base - bl2_base;
+ bl2_mem_layout->total_size = bl1_mem_layout->free_size + tmp;
+
+ } else {
+ bl2_mem_layout->total_base = bl1_mem_layout->free_base;
+ tmp = bl1_mem_layout->total_base + bl1_mem_layout->total_size;
+ bl2_mem_layout->total_size = tmp - bl1_mem_layout->free_base;
+ }
+
+ bl2_mem_layout->free_base = bl1_mem_layout->free_base;
+ bl2_mem_layout->free_size = bl1_mem_layout->free_size;
+ bl2_mem_layout->attr = load_type;
+
+ flush_dcache_range((unsigned long) bl2_mem_layout, sizeof(meminfo_t));
+ return;
+}
+
+static void dump_load_info(unsigned long image_load_addr,
+ unsigned long image_size,
+ const meminfo_t *mem_layout)
+{
+#if 0
+ printf("Trying to load image at address 0x%lx, size = 0x%lx\r\n",
+ image_load_addr, image_size);
+ printf("Current memory layout:\r\n");
+ printf(" total region = [0x%lx, 0x%lx]\r\n", mem_layout->total_base,
+ mem_layout->total_base + mem_layout->total_size);
+ printf(" free region = [0x%lx, 0x%lx]\r\n", mem_layout->free_base,
+ mem_layout->free_base + mem_layout->free_size);
+#endif
+}
+
+/* Generic function to return the size of an image */
+unsigned long image_size(const char *image_name)
+{
+ uintptr_t dev_handle;
+ uintptr_t image_handle;
+ uintptr_t image_spec;
+ size_t image_size = 0;
+ int io_result = IO_FAIL;
+
+ assert(image_name != NULL);
+
+ /* Obtain a reference to the image by querying the platform layer */
+ io_result = plat_get_image_source(image_name, &dev_handle, &image_spec);
+ if (io_result != IO_SUCCESS) {
+ WARN("Failed to obtain reference to image '%s' (%i)\n",
+ image_name, io_result);
+ return 0;
+ }
+
+ /* Attempt to access the image */
+ io_result = io_open(dev_handle, image_spec, &image_handle);
+ if (io_result != IO_SUCCESS) {
+ WARN("Failed to access image '%s' (%i)\n",
+ image_name, io_result);
+ return 0;
+ }
+
+ /* Find the size of the image */
+ io_result = io_size(image_handle, &image_size);
+ if ((io_result != IO_SUCCESS) || (image_size == 0)) {
+ WARN("Failed to determine the size of the image '%s' file (%i)\n",
+ image_name, io_result);
+ }
+ io_result = io_close(image_handle);
+ /* Ignore improbable/unrecoverable error in 'close' */
+
+ /* TODO: Consider maintaining open device connection from this
+ * bootloader stage
+ */
+ io_result = io_dev_close(dev_handle);
+ /* Ignore improbable/unrecoverable error in 'dev_close' */
+
+ return image_size;
+}
+/*******************************************************************************
+ * Generic function to load an image into the trusted RAM,
+ * given a name, extents of free memory & whether the image should be loaded at
+ * the bottom or top of the free memory. It updates the memory layout if the
+ * load is successful. It also updates the image information and the entry point
+ * information in the params passed. The caller might pass a NULL pointer for
+ * the entry point if it is not interested in this information, e.g. because
+ * the image just needs to be loaded in memory but won't ever be executed.
+ ******************************************************************************/
+int load_image(meminfo_t *mem_layout,
+ const char *image_name,
+ unsigned int load_type,
+ unsigned long fixed_addr,
+ image_info_t *image_data,
+ entry_point_info_t *entry_point_info)
+{
+ uintptr_t dev_handle;
+ uintptr_t image_handle;
+ uintptr_t image_spec;
+ unsigned long temp_image_base = 0;
+ unsigned long image_base = 0;
+ long offset = 0;
+ size_t image_size = 0;
+ size_t bytes_read = 0;
+ int io_result = IO_FAIL;
+
+ assert(mem_layout != NULL);
+ assert(image_name != NULL);
+ assert(image_data->h.version >= VERSION_1);
+
+ /* Obtain a reference to the image by querying the platform layer */
+ io_result = plat_get_image_source(image_name, &dev_handle, &image_spec);
+ if (io_result != IO_SUCCESS) {
+ WARN("Failed to obtain reference to image '%s' (%i)\n",
+ image_name, io_result);
+ return io_result;
+ }
+
+ /* Attempt to access the image */
+ io_result = io_open(dev_handle, image_spec, &image_handle);
+ if (io_result != IO_SUCCESS) {
+ WARN("Failed to access image '%s' (%i)\n",
+ image_name, io_result);
+ return io_result;
+ }
+
+ /* Find the size of the image */
+ io_result = io_size(image_handle, &image_size);
+ if ((io_result != IO_SUCCESS) || (image_size == 0)) {
+ WARN("Failed to determine the size of the image '%s' file (%i)\n",
+ image_name, io_result);
+ goto exit;
+ }
+
+ /* See if we have enough space */
+ if (image_size > mem_layout->free_size) {
+ WARN("Cannot load '%s' file: Not enough space.\n",
+ image_name);
+ dump_load_info(0, image_size, mem_layout);
+ goto exit;
+ }
+
+ switch (load_type) {
+
+ case TOP_LOAD:
+
+ /* Load the image in the top of free memory */
+ temp_image_base = mem_layout->free_base + mem_layout->free_size;
+ temp_image_base -= image_size;
+
+ /* Page align base address and check whether the image still fits */
+ image_base = page_align(temp_image_base, DOWN);
+ assert(image_base <= temp_image_base);
+
+ if (image_base < mem_layout->free_base) {
+ WARN("Cannot load '%s' file: Not enough space.\n",
+ image_name);
+ dump_load_info(image_base, image_size, mem_layout);
+ io_result = -ENOMEM;
+ goto exit;
+ }
+
+ /* Calculate the amount of extra memory used due to alignment */
+ offset = temp_image_base - image_base;
+
+ break;
+
+ case BOT_LOAD:
+
+ /* Load the BL2 image in the bottom of free memory */
+ temp_image_base = mem_layout->free_base;
+ image_base = page_align(temp_image_base, UP);
+ assert(image_base >= temp_image_base);
+
+ /* Page align base address and check whether the image still fits */
+ if (image_base + image_size >
+ mem_layout->free_base + mem_layout->free_size) {
+ WARN("Cannot load '%s' file: Not enough space.\n",
+ image_name);
+ dump_load_info(image_base, image_size, mem_layout);
+ io_result = -ENOMEM;
+ goto exit;
+ }
+
+ /* Calculate the amount of extra memory used due to alignment */
+ offset = image_base - temp_image_base;
+
+ break;
+
+ default:
+ assert(0);
+
+ }
+
+ /*
+ * Some images must be loaded at a fixed address, not a dynamic one.
+ *
+ * This has been implemented as a hack on top of the existing dynamic
+ * loading mechanism, for the time being. If the 'fixed_addr' function
+ * argument is different from zero, then it will force the load address.
+ * So we still have this principle of top/bottom loading but the code
+ * determining the load address is bypassed and the load address is
+ * forced to the fixed one.
+ *
+ * This can result in quite a lot of wasted space because we still use
+ * 1 sole meminfo structure to represent the extents of free memory,
+ * where we should use some sort of linked list.
+ *
+ * E.g. we want to load BL2 at address 0x04020000, the resulting memory
+ * layout should look as follows:
+ * ------------ 0x04040000
+ * | | <- Free space (1)
+ * |----------|
+ * | BL2 |
+ * |----------| 0x04020000
+ * | | <- Free space (2)
+ * |----------|
+ * | BL1 |
+ * ------------ 0x04000000
+ *
+ * But in the current hacky implementation, we'll need to specify
+ * whether BL2 is loaded at the top or bottom of the free memory.
+ * E.g. if BL2 is considered as top-loaded, the meminfo structure
+ * will give the following view of the memory, hiding the chunk of
+ * free memory above BL2:
+ * ------------ 0x04040000
+ * | |
+ * | |
+ * | BL2 |
+ * |----------| 0x04020000
+ * | | <- Free space (2)
+ * |----------|
+ * | BL1 |
+ * ------------ 0x04000000
+ */
+ if (fixed_addr != 0) {
+ /* Load the image at the given address. */
+ image_base = fixed_addr;
+
+ /* Check whether the image fits. */
+ if ((image_base < mem_layout->free_base) ||
+ (image_base + image_size >
+ mem_layout->free_base + mem_layout->free_size)) {
+ WARN("Cannot load '%s' file: Not enough space.\n",
+ image_name);
+ dump_load_info(image_base, image_size, mem_layout);
+ io_result = -ENOMEM;
+ goto exit;
+ }
+
+ /* Check whether the fixed load address is page-aligned. */
+ if (!is_page_aligned(image_base)) {
+ WARN("Cannot load '%s' file at unaligned address 0x%lx\n",
+ image_name, fixed_addr);
+ io_result = -ENOMEM;
+ goto exit;
+ }
+
+ /*
+ * Calculate the amount of extra memory used due to fixed
+ * loading.
+ */
+ if (load_type == TOP_LOAD) {
+ unsigned long max_addr, space_used;
+ /*
+ * ------------ max_addr
+ * | /wasted/ | | offset
+ * |..........|..............................
+ * | image | | image_flen
+ * |----------| fixed_addr
+ * | |
+ * | |
+ * ------------ total_base
+ */
+ max_addr = mem_layout->total_base + mem_layout->total_size;
+ /*
+ * Compute the amount of memory used by the image.
+ * Corresponds to all space above the image load
+ * address.
+ */
+ space_used = max_addr - fixed_addr;
+ /*
+ * Calculate the amount of wasted memory within the
+ * amount of memory used by the image.
+ */
+ offset = space_used - image_size;
+ } else /* BOT_LOAD */
+ /*
+ * ------------
+ * | |
+ * | |
+ * |----------|
+ * | image |
+ * |..........| fixed_addr
+ * | /wasted/ | | offset
+ * ------------ total_base
+ */
+ offset = fixed_addr - mem_layout->total_base;
+ }
+
+ /* We have enough space so load the image now */
+ /* TODO: Consider whether to try to recover/retry a partially successful read */
+ io_result = io_read(image_handle, image_base, image_size, &bytes_read);
+ if ((io_result != IO_SUCCESS) || (bytes_read < image_size)) {
+ WARN("Failed to load '%s' file (%i)\n", image_name, io_result);
+ goto exit;
+ }
+
+ image_data->image_base = image_base;
+ image_data->image_size = image_size;
+
+ if (entry_point_info != NULL)
+ entry_point_info->pc = image_base;
+
+ /*
+ * File has been successfully loaded. Update the free memory
+ * data structure & flush the contents of the TZRAM so that
+ * the next EL can see it.
+ */
+ /* Update the memory contents */
+ flush_dcache_range(image_base, image_size);
+
+ mem_layout->free_size -= image_size + offset;
+
+ /* Update the base of free memory since its moved up */
+ if (load_type == BOT_LOAD)
+ mem_layout->free_base += offset + image_size;
+
+exit:
+ io_close(image_handle);
+ /* Ignore improbable/unrecoverable error in 'close' */
+
+ /* TODO: Consider maintaining open device connection from this bootloader stage */
+ io_dev_close(dev_handle);
+ /* Ignore improbable/unrecoverable error in 'dev_close' */
+
+ return io_result;
+} \ No newline at end of file
diff --git a/common/debug.c b/common/debug.c
new file mode 100644
index 0000000..4657d55
--- /dev/null
+++ b/common/debug.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. 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.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * 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 HOLDER 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.
+ */
+#include <serial.h>
+#include <debug.h>
+#include <stdio.h>
+
+/******************************************************************
+* This function is invoked from assembler error handling routines and
+* prints out the string and the value in 64 bit hex format. These
+* are passed to the function as input parameters.
+********************************************************************/
+void print_string_value(char *s, unsigned long *mem)
+{
+ unsigned char i, temp;
+ unsigned long val;
+
+ while (*s) {
+ i = 16;
+ while (*s)
+ serial_putc(*s++);
+
+ s++;
+
+ serial_putc('\t');
+ serial_putc(':');
+ serial_putc('0');
+ serial_putc('x');
+
+ val = *mem++;
+
+ while (i--) {
+ temp = (val >> (i << 2)) & 0xf;
+ if (temp < 0xa)
+ serial_putc('0' + temp);
+ else
+ serial_putc('A' + (temp - 0xa));
+ }
+ serial_putc('\n');
+ }
+}
+
+/***********************************************************
+ * The common implementation of do_panic for all BL stages
+ ***********************************************************/
+
+#if DEBUG
+void __dead2 do_panic(const char *file, int line)
+{
+ serial_puts("PANIC in file: ");
+ serial_puts(file);
+ serial_puts(" line: ");
+ serial_put_dec(line);
+ serial_puts("\n");
+ while (1)
+ ;
+}
+#else
+void __dead2 do_panic(void)
+{
+ unsigned long pc_reg;
+ __asm__ volatile("mov %0, x30\n"
+ : "=r" (pc_reg) : );
+
+ /* x30 reports the next eligible instruction whereas we want the
+ * place where panic() is invoked. Hence decrement by 4.
+ */
+ //printf("PANIC in PC location 0x%016X\n", pc_reg - 0x4);
+ serial_puts("PANIC in PC location 0x");
+ serial_put_hex(pc_reg - 0x4, 64);
+ serial_puts("\n");
+ while (1)
+ ;
+
+}
+#endif
diff --git a/common/fip.c b/common/fip.c
new file mode 100644
index 0000000..cdc579a
--- /dev/null
+++ b/common/fip.c
@@ -0,0 +1,248 @@
+
+/*
+ * arch/arm/cpu/armv8/common/firmware/common/fip.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <fip.h>
+#include <storage.h>
+#include <string.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stdio.h>
+#include <asm/arch/cpu_config.h>
+#include <storage.h>
+#include <sha2.h>
+#include <mailbox.h>
+#include <asm/arch/romboot.h>
+#include <cache.h>
+#include <fip.h>
+#include <asm/arch/watchdog.h>
+#include <timer.h>
+#include <io.h>
+
+static int aml_check(unsigned long pBufferSRC,unsigned long pBufferDST,unsigned int nLength,unsigned int nAESFlag);
+
+void bl2_load_image(void){
+ /* dump ddr data when function enabled and flag set */
+ dump_ddr_data();
+
+ //meminfo_t *bl2_tzram_layout;
+ bl31_params_t *bl2_to_bl31_params;
+ entry_point_info_t *bl31_ep_info;
+ //meminfo_t bl33_mem_info;
+ unsigned int * pCHK = (unsigned int *)FM_FIP_HEADER_LOAD_ADDR;
+ unsigned int nAESFlag = 1;
+ unsigned int nBL3XLoadAddr = readl(0xc8100228);
+ nBL3XLoadAddr = readl(0xc8100228);
+ int nSecFlag = nBL3XLoadAddr & (1<<4);
+ /*load fip header*/
+ aml_fip_header_t *fip_header;
+ fip_header = (aml_fip_header_t *)(uint64_t)FM_FIP_HEADER_LOAD_ADDR;
+#if defined(CONFIG_AML_SECURE_UBOOT)
+ extern void platform_stack_set_bl2 (unsigned long);
+ platform_stack_set_bl2(BL2_SEC_BOOT_SP_BASE);
+#endif
+ storage_load(BL2_SIZE, (uint64_t)fip_header, sizeof(aml_fip_header_t), "fip header");
+ memcpy((void*)FM_FIP_BL3X_TEMP_LOAD_ADDR,(void*)FM_FIP_HEADER_LOAD_ADDR,sizeof(aml_fip_header_t));
+ if (TOC_HEADER_NAME == *pCHK && TOC_HEADER_SERIAL_NUMBER == *(pCHK+1))
+ {
+ nAESFlag = 0;
+ }
+
+ aml_check(FM_FIP_BL3X_TEMP_LOAD_ADDR,FM_FIP_HEADER_LOAD_ADDR,sizeof(aml_fip_header_t),nAESFlag);
+
+ /*load and process bl30*/
+ image_info_t bl30_image_info;
+ entry_point_info_t bl30_ep_info;
+ nBL3XLoadAddr = nSecFlag ? FM_FIP_BL3X_TEMP_LOAD_ADDR : FM_BL30_LOAD_ADDR;
+ storage_load(BL2_SIZE + (fip_header->bl30_entry.offset),nBL3XLoadAddr, (fip_header->bl30_entry.size), "bl30");
+ parse_blx(&bl30_image_info, &bl30_ep_info,nBL3XLoadAddr, FM_BL30_LOAD_ADDR, (fip_header->bl30_entry.size),nAESFlag);
+ /*process bl30*/
+ process_bl30x(&bl30_image_info, &bl30_ep_info, "bl30");
+
+#if (NEED_BL301)
+ /*load and process bl301*/
+ image_info_t bl301_image_info;
+ entry_point_info_t bl301_ep_info;
+ nBL3XLoadAddr = nSecFlag ? FM_FIP_BL3X_TEMP_LOAD_ADDR : FM_BL301_LOAD_ADDR;
+ storage_load(BL2_SIZE + (fip_header->bl301_entry.offset),nBL3XLoadAddr, (fip_header->bl301_entry.size), "bl301");
+ parse_blx(&bl301_image_info, &bl301_ep_info, nBL3XLoadAddr ,FM_BL301_LOAD_ADDR, (fip_header->bl301_entry.size),nAESFlag);
+ /*process bl301*/
+ process_bl30x(&bl301_image_info, &bl301_ep_info, "bl301");
+#endif
+
+ /*load and process bl31*/
+ bl2_to_bl31_params = bl2_plat_get_bl31_params();
+ bl31_ep_info = bl2_plat_get_bl31_ep_info();
+ /* Set the X0 parameter to bl31 */
+ bl31_ep_info->args.arg0 = (unsigned long)bl2_to_bl31_params;
+ nBL3XLoadAddr = nSecFlag ? FM_FIP_BL3X_TEMP_LOAD_ADDR : FM_BL31_LOAD_ADDR;
+ storage_load(BL2_SIZE + (fip_header->bl31_entry.offset), nBL3XLoadAddr, (fip_header->bl31_entry.size), "bl31");
+ parse_blx(bl2_to_bl31_params->bl31_image_info, bl31_ep_info,nBL3XLoadAddr, FM_BL31_LOAD_ADDR, (fip_header->bl31_entry.size),nAESFlag);
+ bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info, bl31_ep_info);
+
+#if (NEED_BL32)
+ /*
+ * Load the BL32 image if there's one. It is upto to platform
+ * to specify where BL32 should be loaded if it exists. It
+ * could create space in the secure sram or point to a
+ * completely different memory.
+ *
+ * If a platform does not want to attempt to load BL3-2 image
+ * it must leave NEED_BL32=0
+ */
+ meminfo_t bl32_mem_info;
+ bl2_plat_get_bl32_meminfo(&bl32_mem_info);
+ nBL3XLoadAddr = nSecFlag ? FM_FIP_BL3X_TEMP_LOAD_ADDR : FM_BL32_LOAD_ADDR;
+ storage_load(BL2_SIZE + fip_header->bl32_entry.offset, nBL3XLoadAddr , fip_header->bl32_entry.size, "bl32");
+ parse_blx(bl2_to_bl31_params->bl32_image_info, bl2_to_bl31_params->bl32_ep_info,
+ nBL3XLoadAddr, FM_BL32_LOAD_ADDR, fip_header->bl32_entry.size,nAESFlag);
+ bl2_plat_set_bl32_ep_info(bl2_to_bl31_params->bl32_image_info, bl2_to_bl31_params->bl32_ep_info);
+#endif /* NEED_BL32 */
+
+ /*load and process bl33*/
+ nBL3XLoadAddr = nSecFlag ? FM_FIP_BL3X_TEMP_LOAD_ADDR : FM_BL33_LOAD_ADDR;
+ storage_load(BL2_SIZE + fip_header->bl33_entry.offset,nBL3XLoadAddr, fip_header->bl33_entry.size, "bl33");
+ parse_blx(bl2_to_bl31_params->bl33_image_info, bl2_to_bl31_params->bl33_ep_info,
+ nBL3XLoadAddr, FM_BL33_LOAD_ADDR, fip_header->bl33_entry.size,nAESFlag);
+ //bl2_plat_get_bl33_meminfo(&bl33_mem_info);
+ bl2_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info, bl2_to_bl31_params->bl33_ep_info);
+
+ /* Flush the params to be passed to memory */
+ bl2_plat_flush_bl31_params();
+
+ /*disable mmu and dcache, flush dcache, then enter next firmware*/
+ disable_mmu_el1();
+ watchdog_disable();
+ /*
+ * Run BL31 via an SMC to BL1. Information on how to pass control to
+ * the BL32 (if present) and BL33 software images will be passed to
+ * BL31 as an argument.
+ */
+
+ smc(RUN_IMAGE, (unsigned long)bl31_ep_info, 0, 0, 0, 0, 0, 0);
+
+/*
+ typedef unsigned long (*FUNC_TPL)(void );
+ unsigned long bl33_entry = FM_BL33_LOAD_ADDR;
+ serial_puts("bl33 entry: 0x");
+ serial_put_hex(bl33_entry, 32);
+ serial_puts("\n");
+ FUNC_TPL func_tpl=(FUNC_TPL)bl33_entry;
+ func_tpl();
+*/
+}
+
+static int aml_check(unsigned long pBufferSRC,unsigned long pBufferDST,unsigned int nLength,unsigned int nAESFlag)
+{
+ int nReturn = aml_data_check(pBufferSRC,pBufferDST,nLength,nAESFlag);
+ if (nReturn)
+ {
+ //printf("aml log : SIG CHK : %d for address 0x%08X\n",nReturn,pBufferSRC);
+ serial_puts("aml log : SIG CHK : ");
+ serial_put_dec(nReturn);
+ serial_puts(" for address 0x");
+ serial_put_hex(pBufferSRC, 32);
+ serial_puts("\n");
+ //while(1);
+ check_handler();
+ }
+
+ return nReturn;
+}
+
+/*blx header parse function*/
+void parse_blx(image_info_t *image_data,
+ entry_point_info_t *entry_point_info,
+ unsigned int src,
+ unsigned int dst,
+ unsigned int length,
+ unsigned int nAESFlag)
+{
+ image_data->image_base = dst;
+ image_data->image_size = length;
+ if (entry_point_info != NULL)
+ entry_point_info->pc = dst;
+
+ aml_check(src,dst,length,nAESFlag);
+}
+
+/*process bl30x, transfer to m3, etc..*/
+void process_bl30x(image_info_t *image_data,
+ entry_point_info_t *entry_point_info, const char * name)
+{
+ //serial_puts("start sha2\n");
+ uint8_t _sha2[32] = {0};
+ sha2((const uint8_t *)image_data->image_base,
+ image_data->image_size,
+ _sha2,
+ 0); /*0 means sha256, else means sha224*/
+
+#if 0
+ serial_puts(name);
+ serial_puts(" sha2:");
+ int print_loop = 0;
+ for (print_loop=0; print_loop<32; print_loop++) {
+ if (0 == (print_loop % 16))
+ serial_puts("\n");
+ serial_put_hex(_sha2[print_loop], 8);
+ serial_puts(" ");
+ }
+ serial_puts("\n");
+#endif
+
+ send_bl30x(image_data->image_base, image_data->image_size, \
+ _sha2, sizeof(_sha2), name);
+ return;
+}
+
+void bl2_to_romcode(uintptr_t entry)
+{
+ bl31_params_t *bl2_to_bl31_params;
+ entry_point_info_t *bl31_ep_info;
+
+ bl2_to_bl31_params = bl2_plat_get_bl31_params();
+ bl31_ep_info = bl2_plat_get_bl31_ep_info();
+ /* Set the X0 parameter to bl31 */
+ bl31_ep_info->args.arg0 = (unsigned long)bl2_to_bl31_params;
+
+ bl31_ep_info->pc = entry;
+ SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
+ bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_DBG_BIT));
+
+ watchdog_disable();
+ disable_mmu_el1();
+
+ bl31_ep_info->args.arg0 = 0;
+ smc(RUN_IMAGE, (unsigned long)bl31_ep_info, 0, 0, 0, 0, 0, 0);
+}
+
+void check_handler(void) {
+ if (BOOT_DEVICE_USB == get_boot_device()) {
+ serial_puts("USB mode!\n");
+ bl2_to_romcode(USB_BL2_RETURN_ROM_ADDR);
+ }
+ else{
+ serial_puts("reset...\n");
+ reset_system();
+ }
+}
diff --git a/common/memtest.c b/common/memtest.c
new file mode 100644
index 0000000..e7bdb6b
--- /dev/null
+++ b/common/memtest.c
@@ -0,0 +1,369 @@
+/**********************************************************************
+ *
+ * Filename: memtest.c
+ *
+ * Description: General-purpose memory testing functions.
+ *
+ * Notes: This software can be easily ported to systems with
+ * different data bus widths by redefining 'unsigned int'.
+ *
+ *
+ * Copyright (c) 1998 by Michael Barr. This software is placed into
+ * the public domain and may be used for any purpose. However, this
+ * notice must not be changed or removed and no warranty is either
+ * expressed or implied by its publication or distribution.
+ **********************************************************************/
+
+#define MEM_TEST_DEBUG 0
+
+#include <stdio.h>
+
+/**********************************************************************
+ *
+ * Function: memTestDataBus()
+ *
+ * Description: Test the data bus wiring in a memory region by
+ * performing a walking 1's test at a fixed address
+ * within that region. The address (and hence the
+ * memory region) is selected by the caller.
+ *
+ * Notes:
+ *
+ * Returns: 0 if the test succeeds.
+ * A non-zero result is the first pattern that failed.
+ *
+ **********************************************************************/
+unsigned int
+memTestDataBus(volatile unsigned int * address)
+{
+ unsigned int pattern;
+ unsigned int data;
+ unsigned int ret = 0;
+ /*
+ * Perform a walking 1's test at the given address.
+ */
+ for (pattern = 1; pattern != 0; pattern <<= 1)
+ {
+ /*
+ * Write the test pattern.
+ */
+ *address = pattern;
+ data = *address;
+ /*
+ * Read it back (immediately is okay for this test).
+ */
+ if (data != pattern)
+ {
+#if (MEM_TEST_DEBUG)
+ //printf(" memTestDataBus - write: 0x%8x, read back: 0x%8x\n", pattern, data);
+ serial_puts(" memTestDataBus - write: 0x");
+ serial_put_hex(pattern, 32);
+ serial_puts(", read back: 0x");
+ serial_put_hex(data, 32);
+ serial_puts("\n");
+ ret = 1;
+#else
+ return (pattern);
+#endif
+ }
+ }
+ return (ret);
+} /* memTestDataBus() */
+
+
+/**********************************************************************
+ *
+ * Function: memTestAddressBus()
+ *
+ * Description: Test the address bus wiring in a memory region by
+ * performing a walking 1's test on the relevant bits
+ * of the address and checking for aliasing. This test
+ * will find single-bit address failures such as stuck
+ * -high, stuck-low, and shorted pins. The base address
+ * and size of the region are selected by the caller.
+ *
+ * Notes: For best results, the selected base address should
+ * have enough LSB 0's to guarantee single address bit
+ * changes. For example, to test a 64-Kbyte region,
+ * select a base address on a 64-Kbyte boundary. Also,
+ * select the region size as a power-of-two--if at all
+ * possible.
+ *
+ * Returns: NULL if the test succeeds.
+ * A non-zero result is the first address at which an
+ * aliasing problem was uncovered. By examining the
+ * contents of memory, it may be possible to gather
+ * additional information about the problem.
+ *
+ **********************************************************************/
+unsigned int
+memTestAddressBus(volatile unsigned int * baseAddress, unsigned int nBytes)
+{
+ unsigned int addressMask = (nBytes/sizeof(unsigned int) - 1);
+ unsigned int offset;
+ unsigned int testOffset;
+
+ unsigned int pattern = (unsigned int) 0xAAAAAAAA;
+ unsigned int antipattern = (unsigned int) 0x55555555;
+
+ unsigned int data1, data2;
+
+ /* align the mask address */
+ unsigned int temp_i=1, temp_j=0;
+ temp_j = addressMask;
+ do {
+ temp_i=(temp_i<<1);
+ temp_j=(temp_j>>1);
+ }while((temp_j));
+ addressMask=((temp_i)-1);
+
+ unsigned int ret = 0;
+
+ /*
+ * Write the default pattern at each of the power-of-two offsets.
+ */
+ for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
+ {
+ baseAddress[offset] = pattern;
+ }
+
+ /*
+ * Check for address bits stuck high.
+ */
+ testOffset = 0;
+ baseAddress[testOffset] = antipattern;
+
+ for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
+ {
+ data1 = baseAddress[offset];
+ data2 = baseAddress[offset];
+ if (data1 != data2)
+ {
+#if (MEM_TEST_DEBUG)
+ //printf(" memTestAddressBus - read twice different[offset]: 0x%8x-0x%8x\n", data1, data2);
+ serial_puts(" memTestAddressBus - read twice different[offset]: 0x");
+ serial_put_hex(data1, 32);
+ serial_puts("-0x");
+ serial_put_hex(data2, 32);
+ serial_puts("\n");
+#endif
+ ret = 1;
+ }
+ if (data1 != pattern)
+ {
+#if (MEM_TEST_DEBUG)
+ /*printf(" memTestAddressBus - write[0x%8x]: 0x%8x, read[0x%8x]: 0x%8x\n", \
+ offset, pattern, offset, data1);
+ */
+ serial_puts(" memTestAddressBus - write[0x");
+ serial_put_hex(offset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(pattern, 32);
+ serial_puts(", read[0x");
+ serial_put_hex(offset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(data1, 32);
+ serial_puts("\n");
+ ret = 1;
+#else
+ return ((unsigned int)(unsigned long) &baseAddress[offset]);
+#endif
+ }
+ }
+
+ baseAddress[testOffset] = pattern;
+
+ /*
+ * Check for address bits stuck low or shorted.
+ */
+ for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1)
+ {
+ baseAddress[testOffset] = antipattern;
+
+ if (baseAddress[0] != pattern)
+ {
+#if (MEM_TEST_DEBUG)
+ /*printf(" memTestAddressBus2 - write baseAddress[0x%8x]: 0x%8x, read baseAddress[0]: 0x%8x\n", \
+ testOffset, antipattern, baseAddress[0]);
+ */
+ serial_puts(" memTestAddressBus2 - write baseAddress[0x");
+ serial_put_hex(testOffset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(antipattern, 32);
+ serial_puts(", read baseAddress[0]: 0x");
+ serial_put_hex(baseAddress[0], 32);
+ serial_puts("\n");
+ ret = 1;
+#else
+ return ((unsigned int)(unsigned long) &baseAddress[testOffset]);
+#endif
+ }
+
+ for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
+ {
+ data1 = baseAddress[offset];
+ if ((data1 != pattern) && (offset != testOffset))
+ {
+#if (MEM_TEST_DEBUG)
+ /*printf(" memTestAddressBus3 - write baseAddress[0x%8x]: 0x%8x, read baseAddress[0x%8x]: 0x%8x\n", \
+ testOffset, antipattern, testOffset, data1);
+ */
+ serial_puts(" memTestAddressBus3 - write baseAddress[0x");
+ serial_put_hex(testOffset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(antipattern, 32);
+ serial_puts(", read baseAddress[0x");
+ serial_put_hex(testOffset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(data1, 32);
+ serial_puts("\n");
+ ret = 1;
+#else
+ return ((unsigned int)(unsigned long) &baseAddress[testOffset]);
+#endif
+ }
+ }
+
+ baseAddress[testOffset] = pattern;
+ }
+ return (ret);
+} /* memTestAddressBus() */
+
+
+/**********************************************************************
+ *
+ * Function: memTestDevice()
+ *
+ * Description: Test the integrity of a physical memory device by
+ * performing an increment/decrement test over the
+ * entire region. In the process every storage bit
+ * in the device is tested as a zero and a one. The
+ * base address and the size of the region are
+ * selected by the caller.
+ *
+ * Notes:
+ *
+ * Returns: NULL if the test succeeds.
+ *
+ * A non-zero result is the first address at which an
+ * incorrect value was read back. By examining the
+ * contents of memory, it may be possible to gather
+ * additional information about the problem.
+ *
+ **********************************************************************/
+/*#define AML_DEBUG_ROM*/
+#if MEM_TEST_DEVICE
+unsigned int
+memTestDevice(volatile unsigned int * baseAddress, unsigned int nBytes)
+{
+
+ unsigned int offset;
+ unsigned int nWords = nBytes / sizeof(unsigned int);
+ unsigned int ret = 0;
+ unsigned int data;
+ unsigned int pattern;
+ unsigned int antipattern;
+ serial_puts("\nTotal Size 0x");
+ serial_put_hex(nBytes, 32);
+ serial_puts("\n");
+
+ /*
+ * Fill memory with a known pattern.
+ */
+ for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
+ {
+ baseAddress[offset] = pattern;
+#ifdef AML_DEBUG_ROM
+ if ((offset&0x3ffff) == 0)
+ {
+ serial_puts("\r0x");
+ serial_put_hex(offset<<2, 32);
+ }
+#endif
+
+ }
+ serial_puts("\n");
+
+ /*
+ * Check each location and invert it for the second pass.
+ */
+ for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
+ {
+ data = baseAddress[offset];
+ if ( data!= pattern)
+ {
+#if (MEM_TEST_DEBUG)
+ /*printf(" memTestDevice - write baseAddress[0x%8x]: 0x%8x, read baseAddress[0x%8x]: 0x%8x\n", \
+ offset, pattern, offset, data);
+ */
+ serial_puts(" memTestDevice - write baseAddress[0x");
+ serial_put_hex(offset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(pattern, 32);
+ serial_puts(", read baseAddress[0x");
+ serial_put_hex(offset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(data, 32);
+ serial_puts("\n");
+ ret = 1;
+#else
+ return ((unsigned int)(unsigned long) &baseAddress[offset]);
+#endif
+ }
+
+ antipattern = ~pattern;
+ baseAddress[offset] = antipattern;
+#ifdef AML_DEBUG_ROM
+ if ((offset&0x3ffff) == 0)
+ {
+ serial_puts("\r0x");
+ serial_put_hex((offset<<2), 32);
+ }
+#endif
+
+ }
+ serial_puts("\n");
+
+ /*
+ * Check each location for the inverted pattern and zero it.
+ */
+ for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
+ {
+ antipattern = ~pattern;
+ data = baseAddress[offset];
+ if (data != antipattern)
+ {
+#if (MEM_TEST_DEBUG)
+ /*printf(" memTestDevice2 - write baseAddress[0x%8x]: 0x%8x, read baseAddress[0x%8x]: 0x%8x\n", \
+ offset, antipattern, offset, data);
+ */
+ serial_puts(" memTestDevice2 - write baseAddress[0x");
+ serial_put_hex(offset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(pattern, 32);
+ serial_puts(", read baseAddress[0x");
+ serial_put_hex(offset, 32);
+ serial_puts("]: 0x");
+ serial_put_hex(data, 32);
+ serial_puts("\n");
+ ret = 1;
+#else
+ return ((unsigned int)(unsigned long) &baseAddress[offset]);
+#endif
+ }
+#ifdef AML_DEBUG_ROM
+ if ((offset&0x3ffff) == 0)
+ {
+ serial_puts("\r0x");
+ serial_put_hex((offset<<2), 32);
+ }
+#endif
+
+ }
+#undef AML_DEBUG_ROM
+ serial_puts("\n");
+
+ return (ret);
+} /* memTestDevice() */
+#endif// #if MEM_TEST_DEVICE
+