mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-04-12 00:47:49 -04:00
x1000: bootloader: fix Linux self-extracting kernel boot
Basically, there's longstanding bug in Linux with self-extracting kernels on MIPS which just happened to manifest now on the M3K as a hang on boot. The fix is applied to the M3K and Q1 since they both use this type of kernel image. Change-Id: I17d2bad6eebd677cd6d2e0bf146450c71fcf1229
This commit is contained in:
parent
44fbb1a593
commit
6a6c6083fa
4 changed files with 143 additions and 3 deletions
|
|
@ -148,6 +148,35 @@ void boot_linux(void)
|
|||
* Be careful when modifying this code.
|
||||
*/
|
||||
|
||||
#if defined(FIIO_M3K) || defined(SHANLING_Q1)
|
||||
uint32_t saved_kernel_entry __attribute__((section(".idata")));
|
||||
void kernel_thunk(long, long, long, long) __attribute__((section(".icode")));
|
||||
|
||||
void kernel_thunk(long a0, long a1, long a2, long a3)
|
||||
{
|
||||
/* cache flush */
|
||||
commit_discard_idcache();
|
||||
|
||||
/* now we can jump to the kernel */
|
||||
typedef void(*entry_fn)(long, long, long, long);
|
||||
entry_fn fn = (entry_fn)saved_kernel_entry;
|
||||
fn(a0, a1, a2, a3);
|
||||
while(1);
|
||||
}
|
||||
|
||||
static void patch_stub_call(void* patch_addr)
|
||||
{
|
||||
uint32_t* code = patch_addr;
|
||||
uint32_t stub_addr = (uint32_t)(void*)kernel_thunk;
|
||||
|
||||
/* generate call to stub */
|
||||
code[0] = 0x3c190000 | (stub_addr >> 16); /* lui t9, stub_hi */
|
||||
code[1] = 0x37390000 | (stub_addr & 0xffff); /* ori t9, t9, stub_lo */
|
||||
code[2] = 0x0320f809; /* jalr t9 */
|
||||
code[3] = 0x00000000; /* nop */
|
||||
}
|
||||
#endif
|
||||
|
||||
static __attribute__((unused))
|
||||
void boot_of_helper(uint32_t addr, uint32_t flash_size, const char* args)
|
||||
{
|
||||
|
|
@ -157,6 +186,19 @@ void boot_of_helper(uint32_t addr, uint32_t flash_size, const char* args)
|
|||
if(handle < 0)
|
||||
return;
|
||||
|
||||
#if defined(FIIO_M3K) || defined(SHANLING_Q1)
|
||||
/* Fix for targets that use self-extracting kernel images */
|
||||
void* jump_addr = core_get_data(handle);
|
||||
uint32_t entry_addr = mips_linux_stub_get_entry(&jump_addr, img_length);
|
||||
if(entry_addr >= 0xa0000000 || entry_addr < 0x80000000) {
|
||||
splash2(5*HZ, "Kernel patch failed", "Please send bugreport");
|
||||
return;
|
||||
}
|
||||
|
||||
saved_kernel_entry = entry_addr;
|
||||
patch_stub_call(jump_addr);
|
||||
#endif
|
||||
|
||||
gui_shutdown();
|
||||
|
||||
x1000_dualboot_load_pdma_fw();
|
||||
|
|
|
|||
|
|
@ -41,13 +41,12 @@ struct uimage_header;
|
|||
# define BL_SELECT_NAME "PLAY"
|
||||
# define BL_QUIT_NAME "POWER"
|
||||
# define BOOTBACKUP_FILE "/fiiom3k-boot.bin"
|
||||
// FIXME: OF kernel hangs on the m3k
|
||||
//# define OF_PLAYER_NAME "FiiO player"
|
||||
# define OF_PLAYER_NAME "FiiO player"
|
||||
# define OF_PLAYER_ADDR 0x20000
|
||||
# define OF_PLAYER_LENGTH (4 * 1024 * 1024)
|
||||
# define OF_PLAYER_ARGS OF_RECOVERY_ARGS \
|
||||
" init=/linuxrc ubi.mtd=3 root=ubi0:rootfs ubi.mtd=4 rootfstype=ubifs rw loglevel=8"
|
||||
//# define OF_RECOVERY_NAME "FiiO recovery"
|
||||
# define OF_RECOVERY_NAME "FiiO recovery"
|
||||
# define OF_RECOVERY_ADDR 0x420000
|
||||
# define OF_RECOVERY_LENGTH (5 * 1024 * 1024)
|
||||
# define OF_RECOVERY_ARGS \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue