/* Embedded OS Loader * * Copyright 2005 Vivien Chappelier * * initialization code and linux entry code * * the bootloader is loaded at 0x8c080000 (virtual, cached) * 0x10080000 (physical) = start of SDRAM * it is relocated at 0x8d000000 (virtual, cached) to leave room for the kernel */ .text .align _start: .type _start,#function .globl _start /* relocate */ mov r0, #0x8c000000 /* load address */ orr r0, r0, #0x080000 mov r1, #0x8d000000 /* run address */ ldr r2, end ldr r3, start sub r3, r2, r3 mov r2, r3, lsr #2 add r2, r2, #1 1: /* copy */ ldr r3, [r0] add r0, r0, #4 str r3, [r1] add r1, r1, #4 subs r2, r2, #1 bhi 1b ldr r0, p_enter_reloc /* position independent load */ mov pc, r0 /* jump to relocated code */ enter_reloc: /* call main bootloader */ bl main /* die in endless loop */ 2: b 2b irq_disable: .type irq_disable, #function .globl irq_disable /* disable interrupts */ mov r0, #0xd3 /* set SVC mode and */ msr cpsr_c, r0 /* disable irqs */ mov pc, lr /*****************************************************************************/ /* Prepare the CPU for the linux kernel and execute it * r0 = address r1 = machine type r2 = boot parameters tag list * * This code is position independent * * The requirements for linux are: * MMU = off, D-cache = off, I-cache = dont care, r0 = 0, r1 = machine nr. * * Memory at 0x10000000 (physical) is mapped at 0x10000000 (virtual, uncached). * The linux kernel is expected to be at 0x10008000 (physical). */ enter_linux: .type enter_linux, #function .globl enter_linux /* save address and machine type for later */ mov r4, r0 mov r5, r1 mov r6, r2 /* jump to common physical/virtual address space (uncached) */ ldr r0, p_enter_physical bic r0, r0, #0x8c000000 orr r0, r0, #0x10000000 /* common physical/virtual uncached base */ mov pc, r0 enter_physical: /* disable interrupts */ mov r0, #0xd3 /* set SVC mode and */ msr cpsr_c, r0 /* disable irqs */ /* get rid of any locked down entries in the TLB by setting the 8 */ /* entries to the first 8 kB of physical memory and clearing them. */ mrc p15, 0, r0, c10, c0, 0 /* set the preserve bit */ orr r0, r0, #1 mcr p15, 0, r0, c10, c0, 0 mov r1, #0 mov r2, #8 flush_tlb_locked_set: mcr p15, 0, r1, c8, c7, 1 /* invalidate single entry */ ldr r3, [r1] /* TLB miss to load the locked entry */ add r1, r1, #1024 /* increase modified virtual address */ subs r2, r2, #1 bhi flush_tlb_locked_set mov r1, #0 mov r2, #8 flush_tlb_locked_clear: mcr p15, 0, r1, c8, c7, 1 /* invalidate single entry */ add r1, r1, #1024 /* increase modified virtual address */ subs r2, r2, #1 bhi flush_tlb_locked_clear mrc p15, 0, r0, c10, c0, 0 /* clear the preserve bit */ bic r0, r0, #1 mcr p15, 0, r0, c10, c0, 0 /* flush the D-cache */ flush_cache: mrc p15, 0, r0, c7, c14, 3 /* test clean and invalidate */ bne flush_cache /* deactivate the D-cache and MMU */ mrc p15, 0, r0, c1, c0, 0 /* read control register */ bic r0, r0, #5 /* clear MMU and D-cache bits */ mcr p15, 0, r0, c1, c0, 0 /* write control register */ /* invalidate the TLB */ mcr p15, 0, r0, c8, c7 /* flush the unlocked entries */ /* set r0 to zero and r1 to machine type and r2 to boot params */ mov r0, #0 mov r1, r5 mov r2, r6 /* jump to linux */ mov pc, r4 /* linux load address */ /*****************************************************************************/ /* In case something went wrong during loading, fill the screen with red and enter an endless loop. */ dead_start: .type dead_end,#function .globl dead_start mov r0, #0x20000000 /* framebuffer address */ add r0, r0, #0x1000 add r0, r0, #0x20 mov r1, #0xf800 /* red color */ mov r2, #0x9700 /* framebuffer size */ add r2, r2, #0x40 1: strh r1, [r0] add r0, r0, #2 subs r2, r2, #1 bhi 1b /* die in endless loop */ 2: b 2b dead_end: .globl dead_end .align p_enter_physical: .word enter_physical p_enter_reloc: .word enter_reloc start: .word _start end: .word _end malloc_base: .word _malloc_base .globl start .globl end .globl malloc_base