rendered paste body/* Embedded OS Loader
*
* Copyright 2005 Vivien Chappelier <vivien.chappelier@free.fr>
*
* 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