diff options
Diffstat (limited to 'bootloader/x1000/boot.c')
-rw-r--r-- | bootloader/x1000/boot.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/bootloader/x1000/boot.c b/bootloader/x1000/boot.c index 153c2277aa..d6dfd4a193 100644 --- a/bootloader/x1000/boot.c +++ b/bootloader/x1000/boot.c | |||
@@ -148,6 +148,35 @@ void boot_linux(void) | |||
148 | * Be careful when modifying this code. | 148 | * Be careful when modifying this code. |
149 | */ | 149 | */ |
150 | 150 | ||
151 | #if defined(FIIO_M3K) || defined(SHANLING_Q1) | ||
152 | uint32_t saved_kernel_entry __attribute__((section(".idata"))); | ||
153 | void kernel_thunk(long, long, long, long) __attribute__((section(".icode"))); | ||
154 | |||
155 | void kernel_thunk(long a0, long a1, long a2, long a3) | ||
156 | { | ||
157 | /* cache flush */ | ||
158 | commit_discard_idcache(); | ||
159 | |||
160 | /* now we can jump to the kernel */ | ||
161 | typedef void(*entry_fn)(long, long, long, long); | ||
162 | entry_fn fn = (entry_fn)saved_kernel_entry; | ||
163 | fn(a0, a1, a2, a3); | ||
164 | while(1); | ||
165 | } | ||
166 | |||
167 | static void patch_stub_call(void* patch_addr) | ||
168 | { | ||
169 | uint32_t* code = patch_addr; | ||
170 | uint32_t stub_addr = (uint32_t)(void*)kernel_thunk; | ||
171 | |||
172 | /* generate call to stub */ | ||
173 | code[0] = 0x3c190000 | (stub_addr >> 16); /* lui t9, stub_hi */ | ||
174 | code[1] = 0x37390000 | (stub_addr & 0xffff); /* ori t9, t9, stub_lo */ | ||
175 | code[2] = 0x0320f809; /* jalr t9 */ | ||
176 | code[3] = 0x00000000; /* nop */ | ||
177 | } | ||
178 | #endif | ||
179 | |||
151 | static __attribute__((unused)) | 180 | static __attribute__((unused)) |
152 | void boot_of_helper(uint32_t addr, uint32_t flash_size, const char* args) | 181 | void boot_of_helper(uint32_t addr, uint32_t flash_size, const char* args) |
153 | { | 182 | { |
@@ -157,6 +186,19 @@ void boot_of_helper(uint32_t addr, uint32_t flash_size, const char* args) | |||
157 | if(handle < 0) | 186 | if(handle < 0) |
158 | return; | 187 | return; |
159 | 188 | ||
189 | #if defined(FIIO_M3K) || defined(SHANLING_Q1) | ||
190 | /* Fix for targets that use self-extracting kernel images */ | ||
191 | void* jump_addr = core_get_data(handle); | ||
192 | uint32_t entry_addr = mips_linux_stub_get_entry(&jump_addr, img_length); | ||
193 | if(entry_addr >= 0xa0000000 || entry_addr < 0x80000000) { | ||
194 | splash2(5*HZ, "Kernel patch failed", "Please send bugreport"); | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | saved_kernel_entry = entry_addr; | ||
199 | patch_stub_call(jump_addr); | ||
200 | #endif | ||
201 | |||
160 | gui_shutdown(); | 202 | gui_shutdown(); |
161 | 203 | ||
162 | x1000_dualboot_load_pdma_fw(); | 204 | x1000_dualboot_load_pdma_fw(); |