import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / arm / boot / bootp / init.S
1 /*
2  *  linux/arch/arm/boot/bootp/init.S
3  *
4  *  Copyright (C) 2000-2002 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  *  Header file for splitting kernel + initrd.  Note that we pass
11  *  r0 through to r3 straight through.
12  */
13                 .section .start,#alloc,#execinstr
14                 .type   _start, #function
15                 .globl  _start
16 _start:         adr     r10, initdata
17                 ldr     r11, initdata
18                 sub     r11, r10, r11           @ work out exec offset
19                 b       splitify
20                 .size   _entry,. - _entry
21
22                 .type   initdata, #object
23 initdata:       .word   initdata                @ compiled address of this
24                 .size   initdata,. - initdata
25
26 splitify:       adr     r13, data
27                 ldmia   r13!, {r4-r6}           @ move the initrd
28                 add     r4, r4, r11             @ correction
29                 bl      move
30
31 /*
32  * Setup the initrd parameters to pass to the kernel.  This can either be
33  * passed in via a param_struct or a tag list.  We spot the param_struct
34  * method by looking at the first word; this should either indicate a page
35  * size of 4K, 16K or 32K.
36  */
37                 ldmia   r13, {r4-r8}            @ get size and addr of initrd
38                                                 @ r5 = ATAG_INITRD
39                                                 @ r6 = initrd start
40                                                 @ r7 = initrd end
41                                                 @ r8 = param_struct address
42                 ldr     r9, [r8, #0]            @ no param struct?
43                 teq     r9, #0x1000             @ 4K?
44                 teqne   r9, #0x4000             @ 16K?
45                 teqne   r9, #0x8000             @ 32K?
46                 beq     param_struct
47
48                 ldr     r9, [r8, #4]            @ get first tag
49                 teq     r9, r4
50                 beq     taglist                 @ ok, we have a tag list
51
52 /*
53  * We didn't find a valid tag list - create one.
54  */
55                 str     r4, [r8, #4]
56                 mov     r4, #(8 >> 2)
57                 str     r4, [r8, #0]
58                 mov     r4, #0
59                 str     r4, [r8, #8]
60 /*
61  * find the end of the tag list, and then add an INITRD tag on the end.
62  * If there is already an INITRD tag, then we ignore it; the last INITRD
63  * tag takes precidence.
64  */
65 taglist:        ldr     r9, [r8, #0]            @ tag length
66                 teq     r9, #0                  @ last tag?
67                 addne   r8, r8, r9, lsl #2
68                 bne     taglist
69                 mov     r4, #(16 >> 2)          @ length of initrd tag
70                 mov     r9, #0                  @ end of tag list terminator
71                 stmia   r8, {r4, r5, r6, r7, r9}
72                 adr     r12, kernel_start
73                 mov     pc, r12                 @ call kernel
74
75 /*
76  * We found a param struct.  Modify the param struct for the initrd
77  */
78 param_struct:   add     r8, r8, #16*4
79                 stmia   r8, {r6,r7}             @ save in param_struct
80                 adr     r12, kernel_start
81                 mov     pc, r12                 @ call kernel
82
83 move:           ldmia   r4!, {r7 - r10}         @ move 32-bytes at a time
84                 stmia   r5!, {r7 - r10}
85                 ldmia   r4!, {r7 - r10}
86                 stmia   r5!, {r7 - r10}
87                 subs    r6, r6, #8 * 4
88                 bcs     move
89                 mov     pc, lr
90
91 data:           .word   initrd_start
92                 .word   initrd_addr
93                 .word   initrd_len
94
95                 .word   0x54410001              @ r4 = ATAG_CORE
96                 .word   0x54420005              @ r5 = ATAG_INITRD
97                 .word   initrd_addr             @ r6
98                 .word   initrd_len              @ r7
99                 .word   params                  @ r8
100
101                 .type   initrd_start,#object
102
103 kernel_start: