From 428491df697e0a87eb14512151b3ce969dae8c54 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 3 Mar 2022 19:56:26 +0000 Subject: [PATCH] x1000: support new binary header in rolo Change-Id: I192c3d69616c39534ff329174c4d8d4a357d014d --- firmware/SOURCES | 1 + firmware/export/x1000.h | 3 + firmware/rolo.c | 3 +- .../target/mips/ingenic_x1000/boot-x1000.c | 109 ++++++++++++++++++ .../target/mips/ingenic_x1000/boot-x1000.h | 5 + 5 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 firmware/target/mips/ingenic_x1000/boot-x1000.c diff --git a/firmware/SOURCES b/firmware/SOURCES index 812174500e..001a86335e 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1646,6 +1646,7 @@ drivers/nand_id.c #if CONFIG_CPU == X1000 target/mips/ingenic_x1000/crt0.S target/mips/ingenic_x1000/aic-x1000.c +target/mips/ingenic_x1000/boot-x1000.c target/mips/ingenic_x1000/clk-x1000.c target/mips/ingenic_x1000/debug-x1000.c target/mips/ingenic_x1000/dma-x1000.c diff --git a/firmware/export/x1000.h b/firmware/export/x1000.h index de3d394c02..8384b214ed 100644 --- a/firmware/export/x1000.h +++ b/firmware/export/x1000.h @@ -57,6 +57,9 @@ #define X1000_STACKSIZE 0x1e00 #define X1000_IRQSTACKSIZE 0x300 +/* Standard DRAM base address for backward compatibility */ +#define X1000_STANDARD_DRAM_BASE 0x80004000 + /* Required for pcm_rec_dma_get_peak_buffer(), doesn't do anything * except on targets with recording. */ #define HAVE_PCM_DMA_ADDRESS diff --git a/firmware/rolo.c b/firmware/rolo.c index 24488e5934..d280e39243 100644 --- a/firmware/rolo.c +++ b/firmware/rolo.c @@ -129,9 +129,10 @@ static void rolo_error(const char *text) lcd_scroll_stop(); } -#if CONFIG_CPU == IMX31L || CONFIG_CPU == RK27XX +#if CONFIG_CPU == IMX31L || CONFIG_CPU == RK27XX || CONFIG_CPU == X1000 /* this is in firmware/target/arm/imx31/rolo_restart.c for IMX31 */ /* this is in firmware/target/arm/rk27xx/rolo_restart.c for rk27xx */ +/* this is in firmware/target/mips/ingenic_x1000/boot-x1000.c for X1000 */ extern void rolo_restart(const unsigned char* source, unsigned char* dest, int length); #else diff --git a/firmware/target/mips/ingenic_x1000/boot-x1000.c b/firmware/target/mips/ingenic_x1000/boot-x1000.c new file mode 100644 index 0000000000..d3e6eb35d7 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/boot-x1000.c @@ -0,0 +1,109 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2022 Aidan MacDonald + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "boot-x1000.h" +#include "system.h" +#include + +#define HDR_BEGIN 128 /* header must begin within this many bytes */ +#define HDR_LEN 256 /* header length cannot exceed this */ + +/* search for header value, label must be a 4-character string. + * Returns the found value or 0 if the label wasn't found. */ +static uint32_t search_header(const unsigned char* source, size_t length, + const char* label) +{ + size_t search_len = MIN(length, HDR_BEGIN); + if(search_len < 8) + return 0; + search_len -= 7; + + /* find the beginning marker */ + size_t i; + for(i = 8; i < search_len; i += 4) + if(!memcmp(&source[i], "BEGINHDR", 8)) + break; + if(i >= search_len) + return 0; + i += 8; + + /* search within the header */ + search_len = MIN(length, i + HDR_LEN) - 7; + for(; i < search_len; i += 8) { + if(!memcmp(&source[i], "ENDH", 4)) { + break; + } else if(!memcmp(&source[i], label, 4)) { + i += 4; + /* read little-endian value */ + uint32_t ret = source[i]; + ret |= source[i+1] << 8; + ret |= source[i+2] << 16; + ret |= source[i+3] << 24; + return ret; + } + } + + return 0; +} + +static void iram_memmove(void* dest, const void* source, size_t length) + __attribute__((section(".icode"))); + +static void iram_memmove(void* dest, const void* source, size_t length) +{ + unsigned char* d = dest; + const unsigned char* s = source; + + if(s < d && d < s + length) { + d += length; + s += length; + while(length--) + *--d = *--s; + } else { + while(length--) + *d++ = *s++; + } +} + +void x1000_boot_rockbox(const void* source, size_t length) +{ + uint32_t load_addr = search_header(source, length, "LOAD"); + if(!load_addr) + load_addr = X1000_STANDARD_DRAM_BASE; + + disable_irq(); + + /* --- Beyond this point, do not call into DRAM --- */ + + iram_memmove((void*)load_addr, source, length); + commit_discard_idcache(); + + typedef void(*entry_fn)(void); + entry_fn fn = (entry_fn)load_addr; + fn(); + while(1); +} + +void rolo_restart(const unsigned char* source, unsigned char* dest, int length) +{ + (void)dest; + x1000_boot_rockbox(source, length); +} diff --git a/firmware/target/mips/ingenic_x1000/boot-x1000.h b/firmware/target/mips/ingenic_x1000/boot-x1000.h index 400eb93dc1..620d7de89a 100644 --- a/firmware/target/mips/ingenic_x1000/boot-x1000.h +++ b/firmware/target/mips/ingenic_x1000/boot-x1000.h @@ -24,6 +24,8 @@ #include "x1000/cpm.h" #include +#include +#include enum { BOOT_OPTION_ROCKBOX = 0, @@ -43,6 +45,9 @@ enum { BOOT_FLAG_USB_BOOT = (1 << 30), }; +void x1000_boot_rockbox(const void* source, size_t length) + __attribute__((section(".icode"))); + /* Note: these functions are inlined to minimize SPL code size. * They are private to the X1000 early boot code anyway... */