From 1500d1a22fe284a0e9352447bf51c58642b45f1b Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 19 Sep 2003 19:42:24 +0100 Subject: [PATCH] [ARM] Update bootp kernel+initrd loader. Drop support for old param struct method, and clean up code. --- arch/arm/boot/bootp/init.S | 96 ++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 55 deletions(-) diff --git a/arch/arm/boot/bootp/init.S b/arch/arm/boot/bootp/init.S index 21c28e25d8f95..192ec8da69446 100644 --- a/arch/arm/boot/bootp/init.S +++ b/arch/arm/boot/bootp/init.S @@ -1,86 +1,69 @@ /* * linux/arch/arm/boot/bootp/init.S * - * Copyright (C) 2000-2002 Russell King + * Copyright (C) 2000-2003 Russell King. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Header file for splitting kernel + initrd. Note that we pass + * "Header" file for splitting kernel + initrd. Note that we pass * r0 through to r3 straight through. + * + * This demonstrates how to append code to the start of the kernel + * zImage, and boot the kernel without copying it around. This + * example would be simpler; if we didn't have an object of unknown + * size immediately following the kernel, we could build this into + * a binary blob, and concatenate the zImage using the cat command. */ .section .start,#alloc,#execinstr .type _start, #function .globl _start -_start: adr r10, initdata - ldr r11, initdata - sub r11, r10, r11 @ work out exec offset - b splitify - .size _entry,. - _entry - - .type initdata, #object -initdata: .word initdata @ compiled address of this - .size initdata,. - initdata -splitify: adr r13, data - ldmia r13!, {r4-r6} @ move the initrd - add r4, r4, r11 @ correction - bl move +_start: adr r12, kernel_start @ offset of kernel zImage + ldr r4, [r12, #0x2c] @ length of zImage + adr r13, data + add r4, r4, r12 @ end of zImage, start of initrd + ldmia r13!, {r5-r6} @ r5 = dest, r6 = length + bl move @ move the initrd /* - * Setup the initrd parameters to pass to the kernel. This can either be - * passed in via a param_struct or a tag list. We spot the param_struct - * method by looking at the first word; this should either indicate a page - * size of 4K, 16K or 32K. + * Setup the initrd parameters to pass to the kernel. This can only be + * passed in via the tagged list. */ - ldmia r13, {r4-r8} @ get size and addr of initrd - @ r5 = ATAG_INITRD - @ r6 = initrd start - @ r7 = initrd end - @ r8 = param_struct address - ldr r9, [r8, #0] @ no param struct? - teq r9, #0x1000 @ 4K? - teqne r9, #0x4000 @ 16K? - teqne r9, #0x8000 @ 32K? - beq param_struct - - ldr r9, [r8, #4] @ get first tag - teq r9, r4 - bne taglist @ ok, we have a tag list + ldmia r13, {r5-r9} @ get size and addr of initrd + @ r5 = ATAG_CORE + @ r6 = ATAG_INITRD2 + @ r7 = initrd start + @ r8 = initrd end + @ r9 = param_struct address + ldr r10, [r9, #4] @ get first tag + teq r10, r5 @ is it ATAG_CORE? /* - * We didn't find a valid tag list - create one. + * If we didn't find a valid tag list, create a dummy ATAG_CORE entry. */ - str r4, [r8, #4] - mov r4, #8 - str r4, [r8, #0] - mov r4, #0 - str r4, [r8, #8] + movne r10, #0 @ terminator + movne r4, #2 @ Size of this entry (2 words) + stmneia r8, {r4, r5, r10} @ Size, ATAG_CORE, terminator /* * find the end of the tag list, and then add an INITRD tag on the end. * If there is already an INITRD tag, then we ignore it; the last INITRD * tag takes precidence. */ -taglist: ldr r9, [r8, #0] @ tag length - teq r9, #0 @ last tag? - addne r8, r8, r9 +taglist: ldr r10, [r9, #0] @ tag length + teq r10, #0 @ last tag (zero length)? + addne r9, r9, r10, lsl #2 bne taglist - mov r4, #16 @ length of initrd tag - mov r9, #0 @ end of tag list terminator - stmia r8, {r4, r5, r6, r7, r9} - adr r12, kernel_start + mov r5, #4 @ Size of initrd tag (4 words) + stmia r9, {r5, r6, r7, r8, r10} mov pc, r12 @ call kernel /* - * We found a param struct. Modify the param struct for the initrd + * Move the block of memory length r6 from address r4 to address r5 */ -param_struct: add r8, r8, #16*4 - stmia r8, {r6,r7} @ save in param_struct - mov pc, r12 @ call kernel - move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time stmia r5!, {r7 - r10} ldmia r4!, {r7 - r10} @@ -89,15 +72,18 @@ move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time bcs move mov pc, lr -data: .word initrd_start - .word initrd_addr - .word initrd_len + .size _start, . - _start + + .type data,#object +data: .word initrd_addr @ destination initrd address + .word initrd_len @ initrd size .word 0x54410001 @ r4 = ATAG_CORE - .word 0x54420005 @ r5 = ATAG_INITRD + .word 0x54420005 @ r5 = ATAG_INITRD2 .word initrd_addr @ r6 .word initrd_len @ r7 .word params @ r8 + .size data, . - _data .type initrd_start,#object -- 2.53.0