#include #include #include .text /* * Boot loader philosophy: * ROM loads us to some arbitrary location * Move the boot code to the link address (8M) * Call decompress_kernel() * Relocate the initrd, zimage and residual data to 8M * Decompress the kernel to 0 * Jump to the kernel entry * -- Cort */ .globl start start: bl start_ start_: /* Enable, invalidate, Disable L1 icache/dcache */ li r8, 0 ori r8, r8, (HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI) mfspr r11,HID0 or r11,r11,r8 andc r10,r11,r8 isync mtspr HID0,r8 sync isync mtspr HID0,r10 sync isync mr r11,r3 /* Save pointer to residual/board data */ /* * Save the OF pointer to r25, but only if the entry point is in a sane * location; if not we store 0. If there is no entry point, or it is * invalid, we establish the default MSR value immediately. Otherwise, * we defer doing that, to allow OF functions to be called, until we * begin uncompressing the kernel. */ lis r3,0x0fff /* r3 = 0x0fffffff */ ori r3,r3,0xffff subc r3,r3,r5 /* r3 = (r5 <= r3) ? ~0 : 0 */ subfe r3,r3,r3 nand r3,r3,r3 and. r5,r5,r3 /* r5 will be cleared if (r5 > r3) */ bne+ haveOF li r3,MSR_IP|MSR_FP /* Not OF: set MSR immediately */ mtmsr r3 isync haveOF: mr r25,r5 /* compute the size of the whole image in words. */ lis r4,start@h ori r4,r4,start@l lis r5,end@h ori r5,r5,end@l addi r5,r5,3 /* round up */ sub r5,r5,r4 /* end - start */ srwi r5,r5,2 mr r7,r5 /* Save for later use. */ /* check if we need to relocate ourselves to the link addr or were * we loaded there to begin with -- Cort */ mflr r3 subi r3,r3,4 /* we get the nip, not the ip of the branch */ mr r8,r3 cmp 0,r3,r4 beq start_ldr /* If 0, we don't need to relocate */ /* * no matter where we're loaded, move ourselves to -Ttext address */ relocate: mflr r3 /* Compute code bias */ subi r3,r3,4 mr r8,r3 lis r4,start@h ori r4,r4,start@l mr r5,r7 /* Get the # of longwords again */ mtctr r5 /* Setup for loop */ li r6,0 subi r3,r3,4 subi r4,r4,4 00: lwzu r5,4(r3) stwu r5,4(r4) xor r6,r6,r5 bdnz 00b lis r3,start_ldr@h ori r3,r3,start_ldr@l mtlr r3 /* Easiest way to do an absolute jump */ blr start_ldr: /* Some boards don't boot up with the I-cache enabled. Do that * now because the decompress runs much faster that way. * As a side effect, we have to ensure the data cache is not enabled * so we can access the serial I/O without trouble. */ bl flush_instruction_cache /* Clear all of BSS */ lis r3,edata@h ori r3,r3,edata@l lis r4,end@h ori r4,r4,end@l subi r3,r3,4 subi r4,r4,4 li r0,0 50: stwu r0,4(r3) cmp 0,r3,r4 bne 50b 90: mr r9,r1 /* Save old stack pointer (in case it matters) */ lis r1,.stack@h ori r1,r1,.stack@l addi r1,r1,4096*2 subi r1,r1,256 li r2,0x000F /* Mask pointer to 16-byte boundary */ andc r1,r1,r2 /* Run loader */ mr r3,r8 /* Load point */ mr r4,r7 /* Program length */ mr r5,r6 /* Checksum */ mr r6,r11 /* Residual data */ mr r7,r25 /* Validated OFW interface */ bl decompress_kernel /* * We have to do this after decompress_kernel, just to make * sure we don't wipe out things mapped in BATs which we need. * -- Tom */ li r6,0 /* Test for a 601 */ mfspr r9,PVR srwi r9,r9,16 cmpi 0,r9,1 /* 601 ? */ beq .clearbats_601 /* Clear BATS */ mtspr DBAT0U,r6 mtspr DBAT0L,r6 mtspr DBAT1U,r6 mtspr DBAT1L,r6 mtspr DBAT2U,r6 mtspr DBAT2L,r6 mtspr DBAT3U,r6 mtspr DBAT3L,r6 .clearbats_601: mtspr IBAT0U,r6 mtspr IBAT0L,r6 mtspr IBAT1U,r6 mtspr IBAT1L,r6 mtspr IBAT2U,r6 mtspr IBAT2L,r6 mtspr IBAT3U,r6 mtspr IBAT3L,r6 isync sync sync /* Set segment registers */ li r6,16 /* load up segment register values */ mtctr r6 /* for context 0 */ lis r6,0x2000 /* Ku = 1, VSID = 0 */ li r10,0 3: mtsrin r6,r10 addi r6,r6,0x111 /* increment VSID */ addis r10,r10,0x1000 /* address of next segment */ bdnz 3b /* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD, * and tell the kernel to start on the 4th instruction since we * overwrite the first 3 sometimes (which are 'nop'). */ li r9,0xc mtlr r9 lis r10,0xdeadc0de@h ori r10,r10,0xdeadc0de@l li r9,0 stw r10,0(r9) blr .comm .stack,4096*2,4