diff options
Diffstat (limited to 'payloads/libpayload/arch/arm')
-rw-r--r-- | payloads/libpayload/arch/arm/Config.in | 44 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/Makefile.inc | 39 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/assembler.h | 60 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/cache.c | 329 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/coreboot.c | 301 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/dummy_media.c | 42 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/exception.c | 177 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/exception_asm.S | 116 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/head.S | 59 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/libpayload.ldscript | 93 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/main.c | 73 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/memcpy.S | 244 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/memset.S | 127 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/sysinfo.c | 64 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/timer.c | 54 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/util.S | 37 | ||||
-rw-r--r-- | payloads/libpayload/arch/arm/virtual.c | 38 |
17 files changed, 1897 insertions, 0 deletions
diff --git a/payloads/libpayload/arch/arm/Config.in b/payloads/libpayload/arch/arm/Config.in new file mode 100644 index 0000000000..b2ee527ab7 --- /dev/null +++ b/payloads/libpayload/arch/arm/Config.in @@ -0,0 +1,44 @@ +## +## This file is part of the libpayload project. +## +## Copyright (c) 2012 Google Inc. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. 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. +## 3. The name of the author may not be used to endorse or promote products +## derived from this software without specific prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +## + +if ARCH_ARM + +config ARCH_SPECIFIC_OPTIONS # dummy + def_bool y + select LITTLE_ENDIAN + +config COREBOOT_INFO_RANGE_BASE + hex "Base of the range to search for the coreboot tables" + +config COREBOOT_INFO_RANGE_SIZE + hex "Size of the range to search for the coreboot tables" + default 0x4000000 + + +endif diff --git a/payloads/libpayload/arch/arm/Makefile.inc b/payloads/libpayload/arch/arm/Makefile.inc new file mode 100644 index 0000000000..42d6ed2d5c --- /dev/null +++ b/payloads/libpayload/arch/arm/Makefile.inc @@ -0,0 +1,39 @@ +## +## This file is part of the libpayload project. +## +## Copyright (C) 2008 Advanced Micro Devices, Inc. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. 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. +## 3. The name of the author may not be used to endorse or promote products +## derived from this software without specific prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +## + +CFLAGS += -ffixed-r8 -mfloat-abi=hard -marm -mabi=aapcs-linux -march=armv7-a + +head.o-y += head.S +libc-y += main.c sysinfo.c +libc-y += timer.c coreboot.c util.S +libc-y += virtual.c +libc-y += memcpy.S memset.S +libc-y += exception_asm.S exception.c +libc-y += cache.c +libcbfs-$(CONFIG_LP_CBFS) += dummy_media.c diff --git a/payloads/libpayload/arch/arm/assembler.h b/payloads/libpayload/arch/arm/assembler.h new file mode 100644 index 0000000000..5e4789b145 --- /dev/null +++ b/payloads/libpayload/arch/arm/assembler.h @@ -0,0 +1,60 @@ +/* + * arch/arm/include/asm/assembler.h + * + * Copyright (C) 1996-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This file contains arm architecture specific defines + * for the different processors. + * + * Do not include any C declarations in this file - it is included by + * assembler source. + */ + +/* + * Endian independent macros for shifting bytes within registers. + */ +#ifndef __ARMEB__ +#define pull lsr +#define push lsl +#define get_byte_0 lsl #0 +#define get_byte_1 lsr #8 +#define get_byte_2 lsr #16 +#define get_byte_3 lsr #24 +#define put_byte_0 lsl #0 +#define put_byte_1 lsl #8 +#define put_byte_2 lsl #16 +#define put_byte_3 lsl #24 +#else +#define pull lsl +#define push lsr +#define get_byte_0 lsr #24 +#define get_byte_1 lsr #16 +#define get_byte_2 lsr #8 +#define get_byte_3 lsl #0 +#define put_byte_0 lsl #24 +#define put_byte_1 lsl #16 +#define put_byte_2 lsl #8 +#define put_byte_3 lsl #0 +#endif + +/* + * Data preload for architectures that support it + */ +#if defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) || \ + defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || \ + defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__) +#define PLD(code...) code +#else +#define PLD(code...) +#endif + +/* + * Cache alligned + */ +#define CALGN(code...) code diff --git a/payloads/libpayload/arch/arm/cache.c b/payloads/libpayload/arch/arm/cache.c new file mode 100644 index 0000000000..3944818110 --- /dev/null +++ b/payloads/libpayload/arch/arm/cache.c @@ -0,0 +1,329 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * cache.c: Cache maintenance routines for ARMv7-A and ARMv7-R + * + * Reference: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition + */ + +#include <stdint.h> + +#include <arch/cache.h> +#include <arch/virtual.h> + +#define bitmask(high, low) ((1UL << (high)) + \ + ((1UL << (high)) - 1) - ((1UL << (low)) - 1)) + +/* Basic log2() implementation. Note: log2(0) is 0 for our purposes. */ +/* FIXME: src/include/lib.h is difficult to work with due to romcc */ +static unsigned long log2(unsigned long u) +{ + int i = 0; + + while (u >>= 1) + i++; + + return i; +} + +void tlb_invalidate_all(void) +{ + /* + * FIXME: ARMv7 Architecture Ref. Manual claims that the distinction + * instruction vs. data TLBs is deprecated in ARMv7, however this does + * not seem to be the case as of Cortex-A15. + */ + tlbiall(); + dtlbiall(); + itlbiall(); + isb(); + dsb(); +} + +void icache_invalidate_all(void) +{ + /* + * icache can be entirely invalidated with one operation. + * Note: If branch predictors are architecturally-visible, ICIALLU + * also performs a BPIALL operation (B2-1283 in arch manual) + */ + iciallu(); + isb(); +} + +enum dcache_op { + OP_DCCSW, + OP_DCCISW, + OP_DCISW, + OP_DCCIMVAC, + OP_DCCMVAC, + OP_DCIMVAC, +}; + +/* + * Do a dcache operation on entire cache by set/way. This is done for + * portability because mapping of memory address to cache location is + * implementation defined (See note on "Requirements for operations by + * set/way" in arch ref. manual). + */ +static void dcache_op_set_way(enum dcache_op op) +{ + uint32_t ccsidr; + unsigned int associativity, num_sets, linesize_bytes; + unsigned int set, way; + unsigned int level; + + level = (read_csselr() >> 1) & 0x7; + + /* + * dcache must be invalidated by set/way for portability since virtual + * memory mapping is system-defined. The number of sets and + * associativity is given by CCSIDR. We'll use DCISW to invalidate the + * dcache. + */ + ccsidr = read_ccsidr(); + + /* FIXME: rounding up required here? */ + num_sets = ((ccsidr & bitmask(27, 13)) >> 13) + 1; + associativity = ((ccsidr & bitmask(12, 3)) >> 3) + 1; + /* FIXME: do we need to use CTR.DminLine here? */ + linesize_bytes = (1 << ((ccsidr & 0x7) + 2)) * 4; + + dsb(); + + /* + * Set/way operations require an interesting bit packing. See section + * B4-35 in the ARMv7 Architecture Reference Manual: + * + * A: Log2(associativity) + * B: L+S + * L: Log2(linesize) + * S: Log2(num_sets) + * + * The bits are packed as follows: + * 31 31-A B B-1 L L-1 4 3 1 0 + * |---|-------------|--------|-------|-----|-| + * |Way| zeros | Set | zeros |level|0| + * |---|-------------|--------|-------|-----|-| + */ + for (way = 0; way < associativity; way++) { + for (set = 0; set < num_sets; set++) { + uint32_t val = 0; + val |= way << (32 - log2(associativity)); + val |= set << log2(linesize_bytes); + val |= level << 1; + switch(op) { + case OP_DCCISW: + dccisw(val); + break; + case OP_DCISW: + dcisw(val); + break; + case OP_DCCSW: + dccsw(val); + break; + default: + break; + } + } + } + isb(); +} + +static void dcache_foreach(enum dcache_op op) +{ + uint32_t clidr; + int level; + + clidr = read_clidr(); + for (level = 0; level < 7; level++) { + unsigned int ctype = (clidr >> (level * 3)) & 0x7; + uint32_t csselr; + + switch(ctype) { + case 0x2: + case 0x3: + case 0x4: + csselr = level << 1; + write_csselr(csselr); + dcache_op_set_way(op); + break; + default: + /* no cache, icache only, or reserved */ + break; + } + } +} + +void dcache_clean_all(void) +{ + dcache_foreach(OP_DCCSW); +} + +void dcache_clean_invalidate_all(void) +{ + dcache_foreach(OP_DCCISW); +} + +void dcache_invalidate_all(void) +{ + dcache_foreach(OP_DCISW); +} + +static unsigned int line_bytes(void) +{ + uint32_t ccsidr; + unsigned int size; + + ccsidr = read_ccsidr(); + /* [2:0] - Indicates (Log2(number of words in cache line)) - 2 */ + size = 1 << ((ccsidr & 0x7) + 2); /* words per line */ + size *= sizeof(unsigned int); /* bytes per line */ + + return size; +} + +/* + * Do a dcache operation by modified virtual address. This is useful for + * maintaining coherency in drivers which do DMA transfers and only need to + * perform cache maintenance on a particular memory range rather than the + * entire cache. + */ +static void dcache_op_mva(void const *vaddr, size_t len, enum dcache_op op) +{ + unsigned long line, linesize; + unsigned long paddr = virt_to_phys(vaddr); + + linesize = line_bytes(); + line = paddr & ~(linesize - 1); + + dsb(); + while (line < paddr + len) { + switch(op) { + case OP_DCCIMVAC: + dccimvac(line); + break; + case OP_DCCMVAC: + dccmvac(line); + break; + case OP_DCIMVAC: + dcimvac(line); + break; + default: + break; + } + line += linesize; + } + isb(); +} + +void dcache_clean_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCCMVAC); +} + +void dcache_clean_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCCIMVAC); +} + +void dcache_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCIMVAC); +} + +void dcache_mmu_disable(void) +{ + uint32_t sctlr; + + dcache_clean_invalidate_all(); + sctlr = read_sctlr(); + sctlr &= ~(SCTLR_C | SCTLR_M); + write_sctlr(sctlr); +} + +void dcache_mmu_enable(void) +{ + uint32_t sctlr; + + sctlr = read_sctlr(); + dcache_clean_invalidate_all(); + sctlr |= SCTLR_C | SCTLR_M; + write_sctlr(sctlr); +} + +void arm_invalidate_caches(void) +{ + uint32_t clidr; + int level; + + /* Invalidate branch predictor */ + bpiall(); + + /* Iterate thru each cache identified in CLIDR and invalidate */ + clidr = read_clidr(); + for (level = 0; level < 7; level++) { + unsigned int ctype = (clidr >> (level * 3)) & 0x7; + uint32_t csselr; + + switch(ctype) { + case 0x0: + /* no cache */ + break; + case 0x1: + /* icache only */ + csselr = (level << 1) | 1; + write_csselr(csselr); + icache_invalidate_all(); + break; + case 0x2: + case 0x4: + /* dcache only or unified cache */ + csselr = level << 1; + write_csselr(csselr); + dcache_invalidate_all(); + break; + case 0x3: + /* separate icache and dcache */ + csselr = (level << 1) | 1; + write_csselr(csselr); + icache_invalidate_all(); + + csselr = level << 1; + write_csselr(csselr); + dcache_invalidate_all(); + break; + default: + /* reserved */ + break; + } + } + + /* Invalidate TLB */ + tlb_invalidate_all(); +} diff --git a/payloads/libpayload/arch/arm/coreboot.c b/payloads/libpayload/arch/arm/coreboot.c new file mode 100644 index 0000000000..1397fc1be2 --- /dev/null +++ b/payloads/libpayload/arch/arm/coreboot.c @@ -0,0 +1,301 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2009 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <libpayload-config.h> +#include <libpayload.h> +#include <coreboot_tables.h> + +/* + * Some of this is x86 specific, and the rest of it is generic. Right now, + * since we only support x86, we'll avoid trying to make lots of infrastructure + * we don't need. If in the future, we want to use coreboot on some other + * architecture, then take out the generic parsing code and move it elsewhere. + */ + +/* === Parsing code === */ +/* This is the generic parsing code. */ + +static void cb_parse_memory(void *ptr, struct sysinfo_t *info) +{ + struct cb_memory *mem = ptr; + int count = MEM_RANGE_COUNT(mem); + int i; + + if (count > SYSINFO_MAX_MEM_RANGES) + count = SYSINFO_MAX_MEM_RANGES; + + info->n_memranges = 0; + + for (i = 0; i < count; i++) { + struct cb_memory_range *range = MEM_RANGE_PTR(mem, i); + +#ifdef CONFIG_LP_MEMMAP_RAM_ONLY + if (range->type != CB_MEM_RAM) + continue; +#endif + + info->memrange[info->n_memranges].base = + cb_unpack64(range->start); + + info->memrange[info->n_memranges].size = + cb_unpack64(range->size); + + info->memrange[info->n_memranges].type = range->type; + + info->n_memranges++; + } +} + +static void cb_parse_serial(void *ptr, struct sysinfo_t *info) +{ + info->serial = ((struct cb_serial *)ptr); +} + +#ifdef CONFIG_LP_CHROMEOS +static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info) +{ + struct lb_range *vbnv = (struct lb_range *)ptr; + + info->vbnv_start = vbnv->range_start; + info->vbnv_size = vbnv->range_size; +} + +static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info) +{ + int i; + struct cb_gpios *gpios = (struct cb_gpios *)ptr; + + info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ? + (gpios->count) : SYSINFO_MAX_GPIOS; + + for (i = 0; i < info->num_gpios; i++) + info->gpios[i] = gpios->gpios[i]; +} + +static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info) +{ + struct lb_range *vdat = (struct lb_range *)ptr; + + info->vdat_addr = phys_to_virt(vdat->range_start); + info->vdat_size = vdat->range_size; +} +#endif + +static void cb_parse_dma(unsigned char *ptr) +{ + struct lb_range *dma = (struct lb_range *)ptr; + init_dma_memory(phys_to_virt(dma->range_start), dma->range_size); +} + +static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + info->tstamp_table = phys_to_virt(cbmem->cbmem_tab); +} + +static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + info->cbmem_cons = phys_to_virt(cbmem->cbmem_tab); +} + +static void cb_parse_mrc_cache(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + info->mrc_cache = phys_to_virt(cbmem->cbmem_tab); +} + +#ifdef CONFIG_LP_NVRAM +static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info) +{ + /* ptr points to a coreboot table entry and is already virtual */ + info->option_table = ptr; +} + +static void cb_parse_checksum(void *ptr, struct sysinfo_t *info) +{ + struct cb_cmos_checksum *cmos_cksum = ptr; + info->cmos_range_start = cmos_cksum->range_start; + info->cmos_range_end = cmos_cksum->range_end; + info->cmos_checksum_location = cmos_cksum->location; +} +#endif + +#ifdef CONFIG_LP_COREBOOT_VIDEO_CONSOLE +static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info) +{ + /* ptr points to a coreboot table entry and is already virtual */ + info->framebuffer = ptr; +} +#endif + +static void cb_parse_string(unsigned char *ptr, char **info) +{ + *info = (char *)((struct cb_string *)ptr)->string; +} + +static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) +{ + struct cb_header *header; + unsigned char *ptr = addr; + void *forward; + int i; + + for (i = 0; i < len; i += 16, ptr += 16) { + header = (struct cb_header *)ptr; + if (!strncmp((const char *)header->signature, "LBIO", 4)) + break; + } + + /* We walked the entire space and didn't find anything. */ + if (i >= len) + return -1; + + if (!header->table_bytes) + return 0; + + /* Make sure the checksums match. */ + if (ipchksum((u16 *) header, sizeof(*header)) != 0) + return -1; + + if (ipchksum((u16 *) (ptr + sizeof(*header)), + header->table_bytes) != header->table_checksum) + return -1; + + info->header = header; + + /* Now, walk the tables. */ + ptr += header->header_bytes; + + for (i = 0; i < header->table_entries; i++) { + struct cb_record *rec = (struct cb_record *)ptr; + + /* We only care about a few tags here (maybe more later). */ + switch (rec->tag) { + case CB_TAG_FORWARD: + forward = phys_to_virt((void *)(unsigned long)((struct cb_forward *)rec)->forward); + return cb_parse_header(forward, len, info); + continue; + case CB_TAG_MEMORY: + cb_parse_memory(ptr, info); + break; + case CB_TAG_SERIAL: + cb_parse_serial(ptr, info); + break; + case CB_TAG_VERSION: + cb_parse_string(ptr, &info->cb_version); + break; + case CB_TAG_EXTRA_VERSION: + cb_parse_string(ptr, &info->extra_version); + break; + case CB_TAG_BUILD: + cb_parse_string(ptr, &info->build); + break; + case CB_TAG_COMPILE_TIME: + cb_parse_string(ptr, &info->compile_time); + break; + case CB_TAG_COMPILE_BY: + cb_parse_string(ptr, &info->compile_by); + break; + case CB_TAG_COMPILE_HOST: + cb_parse_string(ptr, &info->compile_host); + break; + case CB_TAG_COMPILE_DOMAIN: + cb_parse_string(ptr, &info->compile_domain); + break; + case CB_TAG_COMPILER: + cb_parse_string(ptr, &info->compiler); + break; + case CB_TAG_LINKER: + cb_parse_string(ptr, &info->linker); + break; + case CB_TAG_ASSEMBLER: + cb_parse_string(ptr, &info->assembler); + break; +#ifdef CONFIG_LP_NVRAM + case CB_TAG_CMOS_OPTION_TABLE: + cb_parse_optiontable(ptr, info); + break; + case CB_TAG_OPTION_CHECKSUM: + cb_parse_checksum(ptr, info); + break; +#endif +#ifdef CONFIG_LP_COREBOOT_VIDEO_CONSOLE + // FIXME we should warn on serial if coreboot set up a + // framebuffer buf the payload does not know about it. + case CB_TAG_FRAMEBUFFER: + cb_parse_framebuffer(ptr, info); + break; +#endif + case CB_TAG_MAINBOARD: + info->mainboard = (struct cb_mainboard *)ptr; + break; +#ifdef CONFIG_LP_CHROMEOS + case CB_TAG_GPIO: + cb_parse_gpios(ptr, info); + break; + case CB_TAG_VDAT: + cb_parse_vdat(ptr, info); + break; + case CB_TAG_VBNV: + cb_parse_vbnv(ptr, info); + break; +#endif + case CB_TAG_DMA: + cb_parse_dma(ptr); + break; + case CB_TAG_TIMESTAMPS: + cb_parse_tstamp(ptr, info); + break; + case CB_TAG_CBMEM_CONSOLE: + cb_parse_cbmem_cons(ptr, info); + break; + case CB_TAG_MRC_CACHE: + cb_parse_mrc_cache(ptr, info); + break; + } + + ptr += rec->size; + } + + return 1; +} + +/* == Architecture specific == */ +/* FIXME put in actual address range */ + +int get_coreboot_info(struct sysinfo_t *info) +{ + int ret = cb_parse_header( + phys_to_virt(CONFIG_LP_COREBOOT_INFO_RANGE_BASE), + CONFIG_LP_COREBOOT_INFO_RANGE_SIZE, info); + + return (ret == 1) ? 0 : -1; +} diff --git a/payloads/libpayload/arch/arm/dummy_media.c b/payloads/libpayload/arch/arm/dummy_media.c new file mode 100644 index 0000000000..7926976422 --- /dev/null +++ b/payloads/libpayload/arch/arm/dummy_media.c @@ -0,0 +1,42 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ +#define LIBPAYLOAD + +#include <cbfs.h> +#include <string.h> + +/* The generic cbfs code relies on the libpayload_init_default_cbfs_media + * symbol. Therefore, provide an implementation that just throws an error. */ + +int libpayload_init_default_cbfs_media(struct cbfs_media *media); + +int libpayload_init_default_cbfs_media(struct cbfs_media *media) +{ + return -1; +} diff --git a/payloads/libpayload/arch/arm/exception.c b/payloads/libpayload/arch/arm/exception.c new file mode 100644 index 0000000000..8d8b50b175 --- /dev/null +++ b/payloads/libpayload/arch/arm/exception.c @@ -0,0 +1,177 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/exception.h> +#include <libpayload.h> +#include <stdint.h> + +void exception_test(void); + +static int test_abort; + +void exception_undefined_instruction(uint32_t *); +void exception_software_interrupt(uint32_t *); +void exception_prefetch_abort(uint32_t *); +void exception_data_abort(uint32_t *); +void exception_not_used(uint32_t *); +void exception_irq(uint32_t *); +void exception_fiq(uint32_t *); + +static void dump_stack(uintptr_t addr, size_t bytes) +{ + int i, j; + const int line = 8; + uint32_t *ptr = (uint32_t *)(addr & ~(line * sizeof(*ptr) - 1)); + + printf("Dumping stack:\n"); + for (i = bytes / sizeof(*ptr); i >= 0; i -= line) { + printf("%p: ", ptr + i); + for (j = i; j < i + line; j++) + printf("%08x ", *(ptr + j)); + printf("\n"); + } +} + +static void print_regs(uint32_t *regs) +{ + int i; + + for (i = 0; i < 16; i++) { + if (i == 15) + printf("PC"); + else if (i == 14) + printf("LR"); + else if (i == 13) + printf("SP"); + else if (i == 12) + printf("IP"); + else + printf("R%d", i); + printf(" = 0x%08x\n", regs[i]); + } +} + +void exception_undefined_instruction(uint32_t *regs) +{ + printf("exception _undefined_instruction\n"); + print_regs(regs); + dump_stack(regs[13], 512); + halt(); +} + +void exception_software_interrupt(uint32_t *regs) +{ + printf("exception _software_interrupt\n"); + print_regs(regs); + dump_stack(regs[13], 512); + halt(); +} + +void exception_prefetch_abort(uint32_t *regs) +{ + printf("exception _prefetch_abort\n"); + print_regs(regs); + dump_stack(regs[13], 512); + halt(); +} + +void exception_data_abort(uint32_t *regs) +{ + if (test_abort) { + regs[15] = regs[0]; + return; + } else { + printf("exception _data_abort\n"); + print_regs(regs); + dump_stack(regs[13], 512); + } + halt(); +} + +void exception_not_used(uint32_t *regs) +{ + printf("exception _not_used\n"); + print_regs(regs); + dump_stack(regs[13], 512); + halt(); +} + +void exception_irq(uint32_t *regs) +{ + printf("exception _irq\n"); + print_regs(regs); + dump_stack(regs[13], 512); + halt(); +} + +void exception_fiq(uint32_t *regs) +{ + printf("exception _fiq\n"); + print_regs(regs); + dump_stack(regs[13], 512); + halt(); +} + +static inline uint32_t get_sctlr(void) +{ + uint32_t val; + asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (val)); + return val; +} + +static inline void set_sctlr(uint32_t val) +{ + asm volatile("mcr p15, 0, %0, c1, c0, 0" :: "r" (val)); + asm volatile("" ::: "memory"); +} + +void exception_init(void) +{ + static const uint32_t sctlr_te = (0x1 << 30); + static const uint32_t sctlr_v = (0x1 << 13); + static const uint32_t sctlr_a = (0x1 << 1); + + uint32_t sctlr = get_sctlr(); + /* Handle exceptions in ARM mode. */ + sctlr &= ~sctlr_te; + /* Set V=0 in SCTLR so VBAR points to the exception vector table. */ + sctlr &= ~sctlr_v; + /* Enforce alignment temporarily. */ + set_sctlr(sctlr | sctlr_a); + + extern uint32_t exception_table[]; + set_vbar((uintptr_t)exception_table); + + test_abort = 1; + exception_test(); + test_abort = 0; + + /* Restore alignment settings. */ + set_sctlr(sctlr); +} diff --git a/payloads/libpayload/arch/arm/exception_asm.S b/payloads/libpayload/arch/arm/exception_asm.S new file mode 100644 index 0000000000..163fdbd52a --- /dev/null +++ b/payloads/libpayload/arch/arm/exception_asm.S @@ -0,0 +1,116 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +exception_stack: + .align 5 + .skip 0x2000, 0xa5 +exception_stack_end: + .word exception_stack_end + +exception_handler: + .word 0 + + + .align 6 + .arm + .global exception_table +exception_table: + b 1f + b 2f + b 3f + b 4f + b 5f + b 6f + b 7f + b 8f + +1: + ldr sp, _not_used + b exception_common +2: + ldr sp, _undefined_instruction + b exception_common +3: + ldr sp, _software_interrupt + b exception_common +4: + ldr sp, _prefetch_abort + b exception_common +5: + ldr sp, _data_abort + b exception_common +6: + ldr sp, _not_used + b exception_common +7: + ldr sp, _irq + b exception_common +8: + ldr sp, _fiq + b exception_common + +exception_common: + str sp, exception_handler + ldr sp, exception_stack_end + push { lr } + stmfd sp, { sp, lr }^ + sub sp, sp, $8 + push { r0 - r12 } + mov r0, sp + mov lr, pc + ldr pc, exception_handler + pop { r0 - r12 } + add sp, sp, $8 + ldmfd sp!, { pc }^ + + +_undefined_instruction: .word exception_undefined_instruction +_software_interrupt: .word exception_software_interrupt +_prefetch_abort: .word exception_prefetch_abort +_data_abort: .word exception_data_abort +_not_used: .word exception_not_used +_irq: .word exception_irq +_fiq: .word exception_fiq + + .thumb + .global set_vbar + .thumb_func +set_vbar: + mcr p15, 0, r0, c12, c0, 0 + bx lr + + .global exception_test + .thumb_func +exception_test: + mov r1, $1 + mov r0, pc + add r0, $3 + ldr r1, [r1] + bx lr + diff --git a/payloads/libpayload/arch/arm/head.S b/payloads/libpayload/arch/arm/head.S new file mode 100644 index 0000000000..7a706e3aa6 --- /dev/null +++ b/payloads/libpayload/arch/arm/head.S @@ -0,0 +1,59 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + + .global _entry, _leave + .text + .align 4 + +1: +.word _stack + +/* + * Our entry point + */ +_entry: + + /* TODO: disable interrupts */ + + /* TODO: Clear BSS */ + + /* Setup new stack */ + ldr sp, 1b + + /* TODO: Save old stack pointer */ + + /* Let's rock. */ + b start_main + + /* %eax has the return value - pass it on unmolested */ +_leave: + /* TODO: restore old stack pointer. */ + + /* Return to the original context. */ + mov pc, lr diff --git a/payloads/libpayload/arch/arm/libpayload.ldscript b/payloads/libpayload/arch/arm/libpayload.ldscript new file mode 100644 index 0000000000..5f65bd7f1a --- /dev/null +++ b/payloads/libpayload/arch/arm/libpayload.ldscript @@ -0,0 +1,93 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 Google, Inc. + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +BASE_ADDRESS = 0x4000000; + +OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +ENTRY(_entry) + +HEAP_SIZE = 2*64*1024; +STACK_SIZE = 16384; + +SECTIONS +{ + . = BASE_ADDRESS; + + . = ALIGN(16); + _start = .; + + .text : { + *(.text._entry) + *(.text) + *(.text.*) + } + + .rodata : { + *(.rodata) + *(.rodata.*) + } + + .data : { + *(.data) + *(.data.*) + } + + _edata = .; + + .bss : { + *(.sbss) + *(.sbss.*) + *(.bss) + *(.bss.*) + *(COMMON) + + /* Stack and heap */ + + . = ALIGN(16); + _heap = .; + . += HEAP_SIZE; + . = ALIGN(16); + _eheap = .; + + _estack = .; + . += STACK_SIZE; + . = ALIGN(16); + _stack = .; + } + + _end = .; + + /DISCARD/ : { + *(.comment) + *(.note*) + } +} diff --git a/payloads/libpayload/arch/arm/main.c b/payloads/libpayload/arch/arm/main.c new file mode 100644 index 0000000000..4e7c05dfe1 --- /dev/null +++ b/payloads/libpayload/arch/arm/main.c @@ -0,0 +1,73 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/exception.h> +#include <libpayload.h> + +unsigned int main_argc; /**< The argc value to pass to main() */ + +/** The argv value to pass to main() */ +char *main_argv[MAX_ARGC_COUNT]; + +/** + * This is our C entry function - set up the system + * and jump into the payload entry point. + */ +void start_main(void); +void start_main(void) +{ + extern int main(int argc, char **argv); + + /* Gather system information. */ + lib_get_sysinfo(); + + /* Optionally set up the consoles. */ +#ifndef CONFIG_LP_SKIP_CONSOLE_INIT + console_init(); +#endif + + exception_init(); + + /* + * Any other system init that has to happen before the + * user gets control goes here. + */ + + /* + * Go to the entry point. + * In the future we may care about the return value. + */ + + (void) main(main_argc, (main_argc != 0) ? main_argv : NULL); + + /* + * Returning here will go to the _leave function to return + * us to the original context. + */ +} diff --git a/payloads/libpayload/arch/arm/memcpy.S b/payloads/libpayload/arch/arm/memcpy.S new file mode 100644 index 0000000000..e68b28f542 --- /dev/null +++ b/payloads/libpayload/arch/arm/memcpy.S @@ -0,0 +1,244 @@ +/* + * linux/arch/arm/lib/memcpy.S + * + * Author: Nicolas Pitre + * Created: Sep 28, 2005 + * Copyright: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "assembler.h" + +#define W(instr) instr + +#define LDR1W_SHIFT 0 +#define STR1W_SHIFT 0 + + .macro ldr1w ptr reg abort + W(ldr) \reg, [\ptr], #4 + .endm + + .macro ldr4w ptr reg1 reg2 reg3 reg4 abort + ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4} + .endm + + .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort + ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} + .endm + + .macro ldr1b ptr reg cond=al abort + ldr\cond\()b \reg, [\ptr], #1 + .endm + + .macro str1w ptr reg abort + W(str) \reg, [\ptr], #4 + .endm + + .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort + stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} + .endm + + .macro str1b ptr reg cond=al abort + str\cond\()b \reg, [\ptr], #1 + .endm + + .macro enter reg1 reg2 + stmdb sp!, {r0, \reg1, \reg2} + .endm + + .macro exit reg1 reg2 + ldmfd sp!, {r0, \reg1, \reg2} + .endm + + .text + +/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ + +.type memcpy, function +.globl memcpy +memcpy: + + cmp r0, r1 + moveq pc, lr + + enter r4, lr + + subs r2, r2, #4 + blt 8f + ands ip, r0, #3 + PLD( pld [r1, #0] ) + bne 9f + ands ip, r1, #3 + bne 10f + +1: subs r2, r2, #(28) + stmfd sp!, {r5 - r8} + blt 5f + + CALGN( ands ip, r0, #31 ) + CALGN( rsb r3, ip, #32 ) + CALGN( sbcnes r4, r3, r2 ) @ C is always set here + CALGN( bcs 2f ) + CALGN( adr r4, 6f ) + CALGN( subs r2, r2, r3 ) @ C gets set + CALGN( add pc, r4, ip ) + + PLD( pld [r1, #0] ) +2: PLD( subs r2, r2, #96 ) + PLD( pld [r1, #28] ) + PLD( blt 4f ) + PLD( pld [r1, #60] ) + PLD( pld [r1, #92] ) + +3: PLD( pld [r1, #124] ) +4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f + subs r2, r2, #32 + str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f + bge 3b + PLD( cmn r2, #96 ) + PLD( bge 4b ) + +5: ands ip, r2, #28 + rsb ip, ip, #32 +#if LDR1W_SHIFT > 0 + lsl ip, ip, #LDR1W_SHIFT +#endif + addne pc, pc, ip @ C is always clear here + b 7f +6: + .rept (1 << LDR1W_SHIFT) + W(nop) + .endr + ldr1w r1, r3, abort=20f + ldr1w r1, r4, abort=20f + ldr1w r1, r5, abort=20f + ldr1w r1, r6, abort=20f + ldr1w r1, r7, abort=20f + ldr1w r1, r8, abort=20f + ldr1w r1, lr, abort=20f + +#if LDR1W_SHIFT < STR1W_SHIFT + lsl ip, ip, #STR1W_SHIFT - LDR1W_SHIFT +#elif LDR1W_SHIFT > STR1W_SHIFT + lsr ip, ip, #LDR1W_SHIFT - STR1W_SHIFT +#endif + add pc, pc, ip + nop + .rept (1 << STR1W_SHIFT) + W(nop) + .endr + str1w r0, r3, abort=20f + str1w r0, r4, abort=20f + str1w r0, r5, abort=20f + str1w r0, r6, abort=20f + str1w r0, r7, abort=20f + str1w r0, r8, abort=20f + str1w r0, lr, abort=20f + + CALGN( bcs 2b ) + +7: ldmfd sp!, {r5 - r8} + +8: movs r2, r2, lsl #31 + ldr1b r1, r3, ne, abort=21f + ldr1b r1, r4, cs, abort=21f + ldr1b r1, ip, cs, abort=21f + str1b r0, r3, ne, abort=21f + str1b r0, r4, cs, abort=21f + str1b r0, ip, cs, abort=21f + + exit r4, pc + +9: rsb ip, ip, #4 + cmp ip, #2 + ldr1b r1, r3, gt, abort=21f + ldr1b r1, r4, ge, abort=21f + ldr1b r1, lr, abort=21f + str1b r0, r3, gt, abort=21f + str1b r0, r4, ge, abort=21f + subs r2, r2, ip + str1b r0, lr, abort=21f + blt 8b + ands ip, r1, #3 + beq 1b + +10: bic r1, r1, #3 + cmp ip, #2 + ldr1w r1, lr, abort=21f + beq 17f + bgt 18f + + + .macro forward_copy_shift pull push + + subs r2, r2, #28 + blt 14f + + CALGN( ands ip, r0, #31 ) + CALGN( rsb ip, ip, #32 ) + CALGN( sbcnes r4, ip, r2 ) @ C is always set here + CALGN( subcc r2, r2, ip ) + CALGN( bcc 15f ) + +11: stmfd sp!, {r5 - r9} + + PLD( pld [r1, #0] ) + PLD( subs r2, r2, #96 ) + PLD( pld [r1, #28] ) + PLD( blt 13f ) + PLD( pld [r1, #60] ) + PLD( pld [r1, #92] ) + +12: PLD( pld [r1, #124] ) +13: ldr4w r1, r4, r5, r6, r7, abort=19f + mov r3, lr, pull #\pull + subs r2, r2, #32 + ldr4w r1, r8, r9, ip, lr, abort=19f + orr r3, r3, r4, push #\push + mov r4, r4, pull #\pull + orr r4, r4, r5, push #\push + mov r5, r5, pull #\pull + orr r5, r5, r6, push #\push + mov r6, r6, pull #\pull + orr r6, r6, r7, push #\push + mov r7, r7, pull #\pull + orr r7, r7, r8, push #\push + mov r8, r8, pull #\pull + orr r8, r8, r9, push #\push + mov r9, r9, pull #\pull + orr r9, r9, ip, push #\push + mov ip, ip, pull #\pull + orr ip, ip, lr, push #\push + str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f + bge 12b + PLD( cmn r2, #96 ) + PLD( bge 13b ) + + ldmfd sp!, {r5 - r9} + +14: ands ip, r2, #28 + beq 16f + +15: mov r3, lr, pull #\pull + ldr1w r1, lr, abort=21f + subs ip, ip, #4 + orr r3, r3, lr, push #\push + str1w r0, r3, abort=21f + bgt 15b + CALGN( cmp r2, #0 ) + CALGN( bge 11b ) + +16: sub r1, r1, #(\push / 8) + b 8b + + .endm + + + forward_copy_shift pull=8 push=24 + +17: forward_copy_shift pull=16 push=16 + +18: forward_copy_shift pull=24 push=8 diff --git a/payloads/libpayload/arch/arm/memset.S b/payloads/libpayload/arch/arm/memset.S new file mode 100644 index 0000000000..aa4f57a993 --- /dev/null +++ b/payloads/libpayload/arch/arm/memset.S @@ -0,0 +1,127 @@ +/* + * linux/arch/arm/lib/memset.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ASM optimised string functions + */ +#include "assembler.h" + + .text + .align 5 + .word 0 + +1: subs r2, r2, #4 @ 1 do we have enough + blt 5f @ 1 bytes to align with? + cmp r3, #2 @ 1 + strltb r1, [r0], #1 @ 1 + strleb r1, [r0], #1 @ 1 + strb r1, [r0], #1 @ 1 + add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) +/* + * The pointer is now aligned and the length is adjusted. Try doing the + * memset again. + */ + +.type memset, function +.globl memset +memset: + ands r3, r0, #3 @ 1 unaligned? + bne 1b @ 1 +/* + * we know that the pointer in r0 is aligned to a word boundary. + */ + orr r1, r1, r1, lsl #8 + orr r1, r1, r1, lsl #16 + mov r3, r1 + cmp r2, #16 + blt 4f + +#if ! CALGN(1)+0 + +/* + * We need an extra register for this loop - save the return address and + * use the LR + */ + str lr, [sp, #-4]! + mov ip, r1 + mov lr, r1 + +2: subs r2, r2, #64 + stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. + stmgeia r0!, {r1, r3, ip, lr} + stmgeia r0!, {r1, r3, ip, lr} + stmgeia r0!, {r1, r3, ip, lr} + bgt 2b + ldmeqfd sp!, {pc} @ Now <64 bytes to go. +/* + * No need to correct the count; we're only testing bits from now on + */ + tst r2, #32 + stmneia r0!, {r1, r3, ip, lr} + stmneia r0!, {r1, r3, ip, lr} + tst r2, #16 + stmneia r0!, {r1, r3, ip, lr} + ldr lr, [sp], #4 + +#else + +/* + * This version aligns the destination pointer in order to write + * whole cache lines at once. + */ + + stmfd sp!, {r4-r7, lr} + mov r4, r1 + mov r5, r1 + mov r6, r1 + mov r7, r1 + mov ip, r1 + mov lr, r1 + + cmp r2, #96 + tstgt r0, #31 + ble 3f + + and ip, r0, #31 + rsb ip, ip, #32 + sub r2, r2, ip + movs ip, ip, lsl #(32 - 4) + stmcsia r0!, {r4, r5, r6, r7} + stmmiia r0!, {r4, r5} + tst ip, #(1 << 30) + mov ip, r1 + strne r1, [r0], #4 + +3: subs r2, r2, #64 + stmgeia r0!, {r1, r3-r7, ip, lr} + stmgeia r0!, {r1, r3-r7, ip, lr} + bgt 3b + ldmeqfd sp!, {r4-r7, pc} + + tst r2, #32 + stmneia r0!, {r1, r3-r7, ip, lr} + tst r2, #16 + stmneia r0!, {r4-r7} + ldmfd sp!, {r4-r7, lr} + +#endif + +4: tst r2, #8 + stmneia r0!, {r1, r3} + tst r2, #4 + strne r1, [r0], #4 +/* + * When we get here, we've got less than 4 bytes to zero. We + * may have an unaligned pointer as well. + */ +5: tst r2, #2 + strneb r1, [r0], #1 + strneb r1, [r0], #1 + tst r2, #1 + strneb r1, [r0], #1 + mov pc, lr diff --git a/payloads/libpayload/arch/arm/sysinfo.c b/payloads/libpayload/arch/arm/sysinfo.c new file mode 100644 index 0000000000..5aa517594c --- /dev/null +++ b/payloads/libpayload/arch/arm/sysinfo.c @@ -0,0 +1,64 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <libpayload-config.h> +#include <libpayload.h> +#include <coreboot_tables.h> + +/** + * This is a global structure that is used through the library - we set it + * up initially with some dummy values - hopefully they will be overridden. + */ +struct sysinfo_t lib_sysinfo = { + .cpu_khz = 200, +}; + +int lib_get_sysinfo(void) +{ + int ret; + + /* Get the CPU speed (for delays). */ + lib_sysinfo.cpu_khz = get_cpu_speed(); + + /* Get information from the coreboot tables, + * if they exist */ + + ret = get_coreboot_info(&lib_sysinfo); + + if (!lib_sysinfo.n_memranges) { + /* If we can't get a good memory range, use the default. */ + lib_sysinfo.n_memranges = 2; + + lib_sysinfo.memrange[0].base = 0; + lib_sysinfo.memrange[0].size = 1024 * 1024; + lib_sysinfo.memrange[0].type = CB_MEM_RAM; + } + + return ret; +} diff --git a/payloads/libpayload/arch/arm/timer.c b/payloads/libpayload/arch/arm/timer.c new file mode 100644 index 0000000000..3902308562 --- /dev/null +++ b/payloads/libpayload/arch/arm/timer.c @@ -0,0 +1,54 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/** + * @file arm/timer.c + * ARM specific timer routines + */ + +#include <libpayload.h> + +/** + * @ingroup arch + * Global variable containing the speed of the processor in KHz. + */ +u32 cpu_khz; + +/** + * Calculate the speed of the processor for use in delays. + * + * @return The CPU speed in kHz. + */ +unsigned int get_cpu_speed(void) +{ + /* FIXME */ + cpu_khz = 1000000U; + + return cpu_khz; +} diff --git a/payloads/libpayload/arch/arm/util.S b/payloads/libpayload/arch/arm/util.S new file mode 100644 index 0000000000..e3f173eb2d --- /dev/null +++ b/payloads/libpayload/arch/arm/util.S @@ -0,0 +1,37 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2012 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + + .global halt + .text + .align 4 + +/* This function puts the system into a halt. */ + .type halt, function +halt: + b halt diff --git a/payloads/libpayload/arch/arm/virtual.c b/payloads/libpayload/arch/arm/virtual.c new file mode 100644 index 0000000000..59768dbd66 --- /dev/null +++ b/payloads/libpayload/arch/arm/virtual.c @@ -0,0 +1,38 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <unistd.h> + +unsigned long virtual_offset = 0; + + +int getpagesize(void) +{ + return 4096; +} |