/*
 * Based on: arch/ppc/boot/sandpoint/head.S
 *           arch/ppc/kernel/head.S
 *           http://www-106.ibm.com/developerworks/library/pa-ppccache.html
 */

#define HID0        0x3F0       /* Hardware Implementation Register 0 */
#define HID0_ICE    (1<<15)     /* Instruction Cache Enable */
#define HID0_DCE    (1<<14)     /* Data Cache Enable */

.section ".text"
.align 4
.globl load_kernel

load_kernel:
        /* save parameters */
        mr      r31,r3  /* pa_load_kernel */
        mr      r30,r4  /* pa_kernel_buf */
        mr      r29,r5  /* load_address */
        mr      r28,r6  /* bootdev */
        mr      r27,r7  /* boothowto */

        /* disable interrupt */
        mfmsr   r0
        rlwinm  r0,r0,0,17,15   /* clear MSR_EE in r0 */
        sync
        mtmsr   r0
        sync

        /* disable cache */
        bl      disable_cache
#if 1
	addi	r24,r31,bootstr-load_kernel
#endif
        /* jump to after_mmu_off */
        addi    r4,r31,after_mmu_off-load_kernel
        li      r3,0
        mtspr   SRR0,r4
        mtspr   SRR1,r3
        isync
        sync
        rfi

after_mmu_off:
        /* copy kernel image */
        mr      r4,r29		/* r4 <- start address */
3:
	lwz	r26,0(r30)	/* XXX save next ptr */
        addi    r30,r30,4	/* XXX skip next ptr */
	addi	r25,r30,4092	/* XXX store end-of-list to r25 */
2:      li      r0,1024		/* r0 <- (block/sizeof(int)) */
        lwz     r9,0(r30)	/* r9 <- r30[0] */

        mtctr   r0		/* counter <- r0 */
1:      lwz     r0,0(r9)	/* r0 <- *r9 */
        addi    r9,r9,4		/* r9 ++ */
        stw     r0,0(r4)	/* *r4 <- r0 */
        addi    r4,r4,4		/* r4 ++ */
        bdnz    1b		/* if (--counter) goto 1b */

        addi    r30,r30,4	/* r30 ++ */

	cmpw	r25,r30		/* if (r30 == end-of-list) goto next */
	beq	next

        lwz     r0,0(r30)	/* r0 <- *r30 */
        cmpwi   r0,0		/* if (r0 != 0) goto 2b */
        bne     2b
next:
	mr	r30,r26		/* r30 <- r26 : store next ptr */
	cmpwi	r30,0		/* if (next != 0) goto 3b */
	bne	3b
go:
        /* jump to new kernel */
        lis     r1,0x200        /* put stack at 32M */
        mr      r3,r28		/* argv[1] bootdev */
        mr      r4,r27		/* argv[2] boothowto */
        li	r5,0		/* argv[3] startsym */
#if 0
        li	r6,0		/* argv[4] endsym */
#else
	mr	r6,r24		/* argv[4] bootstr */
#endif
        mr      r9,r29		/* jump to start address */
        mtlr    r9
        blr

disable_cache:
        li      r2,1024 /* flush 16K cache */
        mtctr   r2
        mr      r3,r2
        lis     r4,0xc000
loop1:
        lwz     r6,0(r4)
        addi    r4,r4,16
        bdnz    loop1

        lis     r4,0xc000
        mtctr   r3
loop2:
        dcbf    r0,r4
        addi    r4,r4,16
        bdnz    loop2

        mfspr   r4,HID0
        li      r3,0
        ori     r3,r3,HID0_ICE|HID0_DCE
        andc    r4,r4,r3
        mtspr   HID0,r4
        isync
        blr

.align 4
.globl	bootstr
bootstr:
	.skip	256

.globl load_kernel_end
.align 4
load_kernel_end:
