Commit 1500d1a2 authored by Russell King's avatar Russell King

[ARM] Update bootp kernel+initrd loader.

Drop support for old param struct method, and clean up code.
parent 7e0b6a45
/* /*
* linux/arch/arm/boot/bootp/init.S * 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 * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * 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. * 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 .section .start,#alloc,#execinstr
.type _start, #function .type _start, #function
.globl _start .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 _start: adr r12, kernel_start @ offset of kernel zImage
ldmia r13!, {r4-r6} @ move the initrd ldr r4, [r12, #0x2c] @ length of zImage
add r4, r4, r11 @ correction adr r13, data
bl move 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 * Setup the initrd parameters to pass to the kernel. This can only be
* passed in via a param_struct or a tag list. We spot the param_struct * passed in via the tagged list.
* method by looking at the first word; this should either indicate a page
* size of 4K, 16K or 32K.
*/ */
ldmia r13, {r4-r8} @ get size and addr of initrd ldmia r13, {r5-r9} @ get size and addr of initrd
@ r5 = ATAG_INITRD @ r5 = ATAG_CORE
@ r6 = initrd start @ r6 = ATAG_INITRD2
@ r7 = initrd end @ r7 = initrd start
@ r8 = param_struct address @ r8 = initrd end
ldr r9, [r8, #0] @ no param struct? @ r9 = param_struct address
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
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] movne r10, #0 @ terminator
mov r4, #8 movne r4, #2 @ Size of this entry (2 words)
str r4, [r8, #0] stmneia r8, {r4, r5, r10} @ Size, ATAG_CORE, terminator
mov r4, #0
str r4, [r8, #8]
/* /*
* find the end of the tag list, and then add an INITRD tag on the end. * 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 * If there is already an INITRD tag, then we ignore it; the last INITRD
* tag takes precidence. * tag takes precidence.
*/ */
taglist: ldr r9, [r8, #0] @ tag length taglist: ldr r10, [r9, #0] @ tag length
teq r9, #0 @ last tag? teq r10, #0 @ last tag (zero length)?
addne r8, r8, r9 addne r9, r9, r10, lsl #2
bne taglist bne taglist
mov r4, #16 @ length of initrd tag mov r5, #4 @ Size of initrd tag (4 words)
mov r9, #0 @ end of tag list terminator stmia r9, {r5, r6, r7, r8, r10}
stmia r8, {r4, r5, r6, r7, r9}
adr r12, kernel_start
mov pc, r12 @ call kernel 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 move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time
stmia r5!, {r7 - r10} stmia r5!, {r7 - r10}
ldmia r4!, {r7 - r10} ldmia r4!, {r7 - r10}
...@@ -89,15 +72,18 @@ move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time ...@@ -89,15 +72,18 @@ move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time
bcs move bcs move
mov pc, lr mov pc, lr
data: .word initrd_start .size _start, . - _start
.word initrd_addr
.word initrd_len .type data,#object
data: .word initrd_addr @ destination initrd address
.word initrd_len @ initrd size
.word 0x54410001 @ r4 = ATAG_CORE .word 0x54410001 @ r4 = ATAG_CORE
.word 0x54420005 @ r5 = ATAG_INITRD .word 0x54420005 @ r5 = ATAG_INITRD2
.word initrd_addr @ r6 .word initrd_addr @ r6
.word initrd_len @ r7 .word initrd_len @ r7
.word params @ r8 .word params @ r8
.size data, . - _data
.type initrd_start,#object .type initrd_start,#object
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment