/* Relocatable DOL copier for netboot_launch(). * * WHY THIS EXISTS IN ASSEMBLY, IN ITS OWN FILE: * a DOL's sections load over the memory this program is running from (the * standard load address is 0x80003100, right where our own .text sits), so a * copier compiled as an ordinary C function would overwrite its own * instructions partway through the copy and hang the console. This routine is * copied into a reserved region at the top of MEM1 and executed THERE, so the * image cannot touch it. * * It must therefore be strictly position independent: no globals, no literal * pool, no TOC references, no calls. Only PC-relative branches and * register-relative loads. Anything else silently reads from the address it * was LINKED at rather than the one it is RUNNING at. * * r3 = descriptor, in the same reserved region: * 0x00 entry point * 0x04 stack pointer to hand the new image * 0x08 section count * 0x0C bss address * 0x10 bss length * 0x14 section count * (src, dst, len) */ .text .globl nb_stub .globl nb_stub_end .align 2 nb_stub: /* ---- copy every section ---- */ lwz 4, 8(3) /* nsec */ addi 5, 3, 0x14 /* -> first (src,dst,len) */ 1: cmpwi 4, 0 beq 3f lwz 6, 0(5) /* src */ lwz 7, 4(5) /* dst */ lwz 8, 8(5) /* len */ cmpwi 8, 0 beq 2f mtctr 8 4: lbz 9, 0(6) stb 9, 0(7) addi 6, 6, 1 addi 7, 7, 1 bdnz 4b 2: addi 5, 5, 12 addi 4, 4, -1 b 1b 3: /* ---- zero BSS ---- */ lwz 7, 0xC(3) lwz 8, 0x10(3) cmpwi 8, 0 beq 6f li 9, 0 mtctr 8 5: stb 9, 0(7) addi 7, 7, 1 bdnz 5b 6: /* ---- make the copies visible to the instruction fetcher ---- * Flush each destination out of the data cache and invalidate the * matching instruction-cache lines. Without this the CPU happily * executes stale instructions from icache at the entry point. */ lwz 4, 8(3) addi 5, 3, 0x14 7: cmpwi 4, 0 beq 9f lwz 7, 4(5) lwz 8, 8(5) cmpwi 8, 0 beq 8f addi 8, 8, 31 /* round up to whole 32-byte lines */ srwi 8, 8, 5 mtctr 8 10: dcbf 0, 7 icbi 0, 7 addi 7, 7, 32 bdnz 10b 8: addi 5, 5, 12 addi 4, 4, -1 b 7b 9: sync isync lwz 1, 4(3) /* stack for the new image */ lwz 9, 0(3) /* entry */ mtlr 9 li 3, 0 li 4, 0 li 5, 0 blr nb_stub_end: