Mercurial > ecos
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 |
