comparison packages/hal/arm/arch/current/src/redboot_linux_exec.c @ 212:94b558c9fb67

Merge from eCos master repository on 2002-05-31-00:05:29-BST
author jlarmour
date Fri, 31 May 2002 01:05:53 +0000
parents d2c90368aeef
children ae6f2695b07a
comparison
equal deleted inserted replaced
211:6eb55882e01c 212:94b558c9fb67
88 "[-w timeout] [-b <load addr> [-l <length>]]\n" 88 "[-w timeout] [-b <load addr> [-l <length>]]\n"
89 " [-r <ramdisk addr> [-s <ramdisk length>]]\n" 89 " [-r <ramdisk addr> [-s <ramdisk length>]]\n"
90 " [-c \"kernel command line\"] [<entry_point>]", 90 " [-c \"kernel command line\"] [<entry_point>]",
91 do_exec 91 do_exec
92 ); 92 );
93
94 // CYGARC_HAL_MMU_OFF inserts code to turn off MMU and jump to a physical
95 // address. Some ARM implementations may need special handling and define
96 // their own version.
97 #ifndef CYGARC_HAL_MMU_OFF
98 #define CYGARC_HAL_MMU_OFF(__paddr__) \
99 " mcr p15,0,r0,c7,c10,4\n" \
100 " mcr p15,0,r0,c7,c7,0\n" \
101 " mrc p15,0,r0,c1,c0,0\n" \
102 " bic r0,r0,#0xd\n" \
103 " bic r0,r0,#0x1000\n" \
104 " mcr p15,0,r0,c1,c0,0\n" \
105 " mov pc," #__paddr__ "\n"
106 #endif
93 107
94 // 108 //
95 // Parameter info for Linux kernel 109 // Parameter info for Linux kernel
96 // ** C A U T I O N ** This setup must match "asm-arm/setup.h" 110 // ** C A U T I O N ** This setup must match "asm-arm/setup.h"
97 // 111 //
241 unsigned long base_addr, length; 255 unsigned long base_addr, length;
242 unsigned long ramdisk_addr, ramdisk_size; 256 unsigned long ramdisk_addr, ramdisk_size;
243 struct option_info opts[6]; 257 struct option_info opts[6];
244 char line[8]; 258 char line[8];
245 char *cmd_line; 259 char *cmd_line;
246 struct tag *params = (struct tag *)0x0100; 260 struct tag *params = (struct tag *)CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS;
247 261 extern char __tramp_start__[], __tramp_end__[];
248 entry = (unsigned long)CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS); // Default Linux execute address 262
263 // Default physical entry point for Linux is kernel base.
264 entry = (unsigned long)CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS;
265
249 base_addr = load_address; 266 base_addr = load_address;
250 length = load_address_end - load_address; 267 length = load_address_end - load_address;
251 ramdisk_size = 4096*1024; 268 ramdisk_size = 4096*1024;
252 init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 269 init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
253 (void **)&wait_time, (bool *)&wait_time_set, "wait timeout"); 270 (void **)&wait_time, (bool *)&wait_time_set, "wait timeout");
337 HAL_DCACHE_DISABLE(); 354 HAL_DCACHE_DISABLE();
338 HAL_DCACHE_SYNC(); 355 HAL_DCACHE_SYNC();
339 HAL_ICACHE_INVALIDATE_ALL(); 356 HAL_ICACHE_INVALIDATE_ALL();
340 HAL_DCACHE_INVALIDATE_ALL(); 357 HAL_DCACHE_INVALIDATE_ALL();
341 358
342 // Tricky code. We are currently running with the MMU on and the 359 // Tricky code. We are currently running with the MMU on and the
343 // memory map convoluted from 1-1. The trampoline code between 360 // memory map possibly convoluted from 1-1. The trampoline code
344 // labels 1 and 2 must be copied to RAM and then executed at the 361 // between labels __tramp_start__ and __tramp_end__ must be copied
345 // non-mapped address. Then when the code turns off the MMU, the 362 // to RAM and then executed at the non-mapped address.
346 // control flow is unchanged and control can be passed safely to
347 // the program to be executed.
348 // Note: This only works if phys=virt (or there are appropriate
349 // double mapping of the memory). This should be rewritten
350 // so a jump follows immediately after the MMU disable
351 // operation.
352 // 363 //
353 // This magic was created in order to 364 // This magic was created in order to be able to execute standard
354 // be able to execute standard Linux kernels with as little 365 // Linux kernels with as little change/perturberance as possible.
355 // change/perturberance as possible. 366
356 asm volatile ("\n" // Copy code between labels 1-2 to the 367 // copy the trampline code
357 " ldr r2,=1f;\n" // trampoline address... 368 memcpy((char *)CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS,
358 " ldr r3,=2f;\n" 369 __tramp_start__,
359 " mov r5,%0;\n" 370 __tramp_end__ - __tramp_start__);
360 "4:\n" 371
361 " ldr r1,[r2],#4;\n" 372 asm volatile (
362 " str r1,[r5],#4;\n" 373 CYGARC_HAL_MMU_OFF(%5)
363 " cmp r2,r3;\n" 374 "__tramp_start__:\n"
364 " bne 4b;\n" 375 " cmp %1,%4;\n" // Default kernel load address. Relocate
365 " nop;nop;nop;nop;nop;nop;nop;nop;\n" 376 " beq 2f;\n" // kernel image there if necessary, and
366 " mov r5,%1;\n" 377 " cmp %2,#0;\n" // if size is non-zero
367 " mov r2,%2;\n" 378 " beq 2f;\n"
368 " mov r3,%3;\n" 379 "1:\n"
369 " mov r7,%4;\n" 380 " ldr r0,[%1],#4;\n"
370 " mov r6,%5;\n" 381 " str r0,[%4],#4;\n"
371 " mov pc,%0;\n" //... and jump to it. 382 " subs %2,%2,#4;\n"
372 " \n" 383 " bne 1b;\n"
373 "1:\n" 384 "2:\n"
374 " mrs r1,cpsr;\n" // Put processor in IRQ mode 385 " mov r0,#0;\n" // Set board type
375 " bic r0,r1,#0x1F;\n" 386 " mov r1,%3;\n" // Machine type
376 " orr r0,r0,#0x12;\n" 387 " mov r2,%6;\n" // Kernel parameters
377 " msr cpsr,r0;\n" 388 " mov pc,%0;\n" // Jump to kernel
378 " msr spsr,r1;\n" 389 "__tramp_end__:\n"
379 " mov lr,r5;\n" // Set kernel entry point 390 : :
380 " mov sp,r5;\n" // Give the kernel a stack just below the entry point 391 "r"(entry),
381 " mov r1,#0;\n" // Turn off MMU and caches 392 "r"(CYGARC_PHYSICAL_ADDRESS(base_addr)),
382 " mcr p15,0,r1,c1,c0;\n" 393 "r"(length),
383 " nop;nop;nop;\n" 394 "r"(CYGHWR_REDBOOT_ARM_MACHINE_TYPE),
384 " cmp r2,r6;\n" // Default kernel load address. Relocate 395 "r"(CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS),
385 " beq 10f;\n" // kernel image there if necessary, and 396 "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS)),
386 " cmp r3,#0;\n" // if size is non-zero 397 "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_LINUX_TAGS_ADDRESS))
387 " beq 10f;\n" 398 : "r0", "r1"
388 "05:\n" 399 );
389 " ldr r4,[r2],#4;\n"
390 " str r4,[r6],#4;\n"
391 " sub r3,r3,#4;\n"
392 " cmp r3,#0;\n"
393 " bne 05b;\n"
394 "10:\n"
395 " mov r0,#0;\n" // Set board type and start the kernel
396 " mov r1,r7;\n"
397 " movs pc,lr;\n"
398 "2:\n"
399 : :
400 "r"(CYGARC_PHYSICAL_ADDRESS(CYGHWR_REDBOOT_ARM_TRAMPOLINE_ADDRESS)),
401 "r"(entry),
402 "r"(CYGARC_PHYSICAL_ADDRESS(base_addr)),
403 "r"(length),
404 "r"(CYGHWR_REDBOOT_ARM_MACHINE_TYPE),
405 "r"(CYGHWR_REDBOOT_ARM_LINUX_EXEC_ADDRESS) :
406 "r7","r6","r5","r2","r3","r1");
407 } 400 }
408 401
409 #endif // HAL_PLATFORM_MACHINE_TYPE - otherwise we do not support this stuff... 402 #endif // HAL_PLATFORM_MACHINE_TYPE - otherwise we do not support this stuff...
410 403
411 // EOF redboot_linux_exec.c 404 // EOF redboot_linux_exec.c