diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-mvebu/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/spl.c | 12 | ||||
-rw-r--r-- | arch/sandbox/cpu/os.c | 59 | ||||
-rw-r--r-- | arch/sandbox/cpu/start.c | 16 | ||||
-rw-r--r-- | arch/sandbox/include/asm/global_data.h | 1 |
5 files changed, 72 insertions, 17 deletions
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index f5fd60d784..f99bd3bf65 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -14,6 +14,7 @@ config ARMADA_32BIT select SPL_OF_CONTROL if SPL select SPL_SIMPLE_BUS if SPL select SUPPORT_SPL + select TRANSLATION_OFFSET config ARMADA_64BIT bool diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 9dd7c84b68..530b98c1aa 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -93,15 +93,21 @@ void board_init_f(ulong dummy) */ #endif + /* + * Use special translation offset for SPL. This needs to be + * configured *before* spl_init() is called as this function + * calls dm_init() which calls the bind functions of the + * device drivers. Here the base address needs to be configured + * (translated) correctly. + */ + gd->translation_offset = 0xd0000000 - 0xf1000000; + ret = spl_init(); if (ret) { debug("spl_init() failed: %d\n", ret); hang(); } - /* Use special translation offset for SPL */ - dm_set_translation_offset(0xd0000000 - 0xf1000000); - preloader_console_init(); timer_init(); diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index a8d01e4001..47dfb476d3 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -209,8 +209,8 @@ void os_tty_raw(int fd, bool allow_sigs) void *os_malloc(size_t length) { - struct os_mem_hdr *hdr; int page_size = getpagesize(); + struct os_mem_hdr *hdr; /* * Use an address that is hopefully available to us so that pointers @@ -229,30 +229,34 @@ void *os_malloc(size_t length) void os_free(void *ptr) { - struct os_mem_hdr *hdr = ptr; + int page_size = getpagesize(); + struct os_mem_hdr *hdr; - hdr--; - if (ptr) - munmap(hdr, hdr->length + sizeof(*hdr)); + if (ptr) { + hdr = ptr - page_size; + munmap(hdr, hdr->length + page_size); + } } void *os_realloc(void *ptr, size_t length) { - struct os_mem_hdr *hdr = ptr; + int page_size = getpagesize(); + struct os_mem_hdr *hdr; void *buf = NULL; - hdr--; - if (length != 0) { + if (length) { buf = os_malloc(length); if (!buf) return buf; if (ptr) { + hdr = ptr - page_size; if (length > hdr->length) length = hdr->length; memcpy(buf, ptr, length); } } - os_free(ptr); + if (ptr) + os_free(ptr); return buf; } @@ -786,3 +790,40 @@ int os_mprotect_allow(void *start, size_t len) return mprotect(start, len, PROT_READ | PROT_WRITE); } + +void *os_find_text_base(void) +{ + char line[500]; + void *base = NULL; + int len; + int fd; + + /* + * This code assumes that the first line of /proc/self/maps holds + * information about the text, for example: + * + * 5622d9907000-5622d9a55000 r-xp 00000000 08:01 15067168 u-boot + * + * The first hex value is assumed to be the address. + * + * This is tested in Linux 4.15. + */ + fd = open("/proc/self/maps", O_RDONLY); + if (fd == -1) + return NULL; + len = read(fd, line, sizeof(line)); + if (len > 0) { + char *end = memchr(line, '-', len); + + if (end) { + unsigned long long addr; + + *end = '\0'; + if (sscanf(line, "%llx", &addr) == 1) + base = (void *)addr; + } + } + close(fd); + + return base; +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2f5e6e9518..82828f0c1d 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -303,10 +303,8 @@ int board_run_command(const char *cmdline) static void setup_ram_buf(struct sandbox_state *state) { /* Zero the RAM buffer if we didn't read it, to keep valgrind happy */ - if (!state->ram_buf_read) { + if (!state->ram_buf_read) memset(state->ram_buf, '\0', state->ram_size); - printf("clear %p %x\n", state->ram_buf, state->ram_size); - } gd->arch.ram_buf = state->ram_buf; gd->ram_size = state->ram_size; @@ -328,6 +326,10 @@ int main(int argc, char *argv[]) gd_t data; int ret; + memset(&data, '\0', sizeof(data)); + gd = &data; + gd->arch.text_base = os_find_text_base(); + ret = state_init(); if (ret) goto err; @@ -340,8 +342,6 @@ int main(int argc, char *argv[]) if (ret) goto err; - memset(&data, '\0', sizeof(data)); - gd = &data; #if CONFIG_VAL(SYS_MALLOC_F_LEN) gd->malloc_base = CONFIG_MALLOC_F_ADDR; #endif @@ -350,6 +350,12 @@ int main(int argc, char *argv[]) #endif setup_ram_buf(state); + /* + * Set up the relocation offset here, since sandbox symbols are always + * relocated by the OS before sandbox is entered. + */ + gd->reloc_off = (ulong)gd->arch.text_base; + /* Do pre- and post-relocation init */ board_init_f(0); diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h index f6a6a343d2..f4ce72d566 100644 --- a/arch/sandbox/include/asm/global_data.h +++ b/arch/sandbox/include/asm/global_data.h @@ -12,6 +12,7 @@ /* Architecture-specific global data */ struct arch_global_data { uint8_t *ram_buf; /* emulated RAM buffer */ + void *text_base; /* pointer to base of text region */ }; #include <asm-generic/global_data.h> |