]>
Commit | Line | Data |
---|---|---|
4d8d554a CW |
1 | /* -*-Asm-*- */ |
2 | /* | |
3 | * GRUB -- GRand Unified Bootloader | |
4 | * Copyright (C) 2009 Free Software Foundation, Inc. | |
5 | * | |
6 | * GRUB is free software: you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation, either version 3 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * GRUB is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include <grub/machine/boot.h> | |
21 | ||
22 | .text | |
23 | .align 4 | |
24 | .globl _start | |
25 | _start: | |
26 | /* OF CIF entry point arrives in %o4 */ | |
27 | pic_base: | |
28 | call boot_continue | |
29 | mov %o4, CIF_REG | |
30 | ||
31 | #ifndef CDBOOT | |
32 | /* The offsets to these locations are defined by the | |
33 | * GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h, | |
34 | * and grub-setup uses this to patch these next three values as needed. | |
35 | * | |
36 | * The boot_path will be the OF device path of the partition where the | |
37 | * rest of the GRUB kernel image resides. kernel_sector will be set to | |
38 | * the location of the first block of the GRUB kernel, and | |
39 | * kernel_address is the location where we should load that first block. | |
40 | * | |
41 | * After loading in that block we will execute it by jumping to the | |
42 | * load address plus the size of the prepended A.OUT header (32 bytes). | |
43 | */ | |
44 | .org GRUB_BOOT_MACHINE_BOOT_DEVPATH | |
45 | boot_path: | |
46 | .org GRUB_BOOT_MACHINE_KERNEL_BYTE | |
47 | boot_path_end: | |
48 | kernel_byte: .xword (2 << 9) | |
49 | kernel_address: .word GRUB_BOOT_MACHINE_KERNEL_ADDR | |
50 | #else | |
51 | #define boot_path (_start + 512 + SCRATCH_PAD_BOOT_SIZE) | |
52 | #define boot_path_end (_start + 1024) | |
53 | #include <grub/offsets.h> | |
54 | ||
55 | .org 8 | |
56 | kernel_byte: .xword (2 << 9) | |
57 | kernel_size: .word 512 | |
58 | kernel_address: .word GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS | |
59 | #endif | |
60 | ||
61 | prom_finddev_name: .asciz "finddevice" | |
62 | prom_chosen_path: .asciz "/chosen" | |
63 | prom_getprop_name: .asciz "getprop" | |
64 | prom_stdout_name: .asciz "stdout" | |
65 | prom_write_name: .asciz "write" | |
66 | prom_bootpath_name: .asciz "bootpath" | |
67 | prom_open_name: .asciz "open" | |
68 | prom_seek_name: .asciz "seek" | |
69 | prom_read_name: .asciz "read" | |
70 | prom_exit_name: .asciz "exit" | |
71 | grub_name: .asciz "GRUB " | |
e1c95655 ES |
72 | #ifdef CDBOOT |
73 | prom_close_name: .asciz "close" | |
74 | #endif | |
75 | ||
4d8d554a CW |
76 | #define GRUB_NAME_LEN 5 |
77 | ||
78 | .align 4 | |
79 | ||
80 | prom_open_error: | |
81 | GET_ABS(prom_open_name, %o2) | |
82 | call console_write | |
83 | mov 4, %o3 | |
84 | /* fallthru */ | |
85 | ||
86 | prom_error: | |
87 | GET_ABS(prom_exit_name, %o0) | |
88 | /* fallthru */ | |
89 | ||
90 | /* %o0: OF call name | |
91 | * %o1: input arg 1 | |
92 | */ | |
93 | prom_call_1_1_o2: | |
94 | clr %o2 | |
95 | ba prom_call_x_1 | |
96 | mov 1, %g1 | |
97 | ||
98 | prom_call_getprop: | |
99 | mov 4, %g1 | |
100 | stx %g1, [%l1 + 256] | |
101 | mov CHOSEN_NODE_REG, %o1 | |
102 | ba prom_call_x_1 | |
103 | GET_ABS(prom_getprop_name, %o0) | |
104 | ||
105 | prom_call_3_1_o1: | |
106 | ba prom_call_3_1 | |
107 | mov BOOTDEV_REG, %o1 | |
108 | ||
109 | ||
110 | /* %o2: message string | |
111 | * %o3: message length | |
112 | */ | |
113 | console_write: | |
114 | GET_ABS(prom_write_name, %o0) | |
115 | mov STDOUT_NODE_REG, %o1 | |
116 | /* fallthru */ | |
117 | ||
118 | /* %o0: OF call name | |
119 | * %o1: input arg 1 | |
120 | * %o2: input arg 2 | |
121 | * %o3: input arg 3 | |
122 | */ | |
123 | prom_call_3_1: | |
124 | mov 3, %g1 | |
125 | prom_call_x_1: | |
126 | mov 1, %o5 | |
127 | /* fallthru */ | |
128 | ||
129 | /* %o0: OF call name | |
130 | * %g1: num inputs | |
131 | * %o5: num outputs | |
132 | * %o1-%o4: inputs | |
133 | */ | |
134 | prom_call: | |
135 | stx %o0, [%l1 + 0x00] | |
136 | stx %g1, [%l1 + 0x08] | |
137 | stx %o5, [%l1 + 0x10] | |
138 | stx %o1, [%l1 + 0x18] | |
139 | stx %o2, [%l1 + 0x20] | |
140 | stx %o3, [%l1 + 0x28] | |
141 | stx %o4, [%l1 + 0x30] | |
142 | jmpl CIF_REG, %g0 | |
143 | mov %l1, %o0 | |
144 | ||
145 | boot_continue: | |
146 | mov %o7, PIC_REG /* PIC base */ | |
147 | #ifndef CDBOOT | |
148 | sethi %hi(SCRATCH_PAD_BOOT), %l1 /* OF argument slots */ | |
149 | #else | |
150 | GET_ABS(_start + 512, %l1) /* OF argument slots */ | |
151 | #endif | |
152 | ||
153 | /* Find the /chosen node so we can fetch the stdout handle, | |
154 | * and thus perform console output. | |
155 | * | |
156 | * chosen_node = prom_finddevice("/chosen") | |
157 | */ | |
158 | GET_ABS(prom_finddev_name, %o0) | |
159 | call prom_call_1_1_o2 | |
160 | GET_ABS(prom_chosen_path, %o1) | |
161 | ||
162 | ldx [%l1 + 0x20], CHOSEN_NODE_REG | |
163 | brz CHOSEN_NODE_REG, prom_error | |
164 | ||
165 | /* getprop(chosen_node, "stdout", &buffer, buffer_size) */ | |
166 | GET_ABS(prom_stdout_name, %o2) | |
167 | add %l1, 256, %o3 | |
168 | call prom_call_getprop | |
169 | mov 1024, %o4 | |
170 | ||
171 | lduw [%l1 + 256], STDOUT_NODE_REG | |
172 | brz,pn STDOUT_NODE_REG, prom_error | |
173 | ||
174 | /* write(stdout_node, "GRUB ", strlen("GRUB ")) */ | |
175 | GET_ABS(grub_name, %o2) | |
176 | call console_write | |
177 | mov GRUB_NAME_LEN, %o3 | |
178 | ||
179 | GET_ABS(boot_path, %o3) | |
180 | #ifndef CDBOOT | |
181 | ldub [%o3], %o1 | |
182 | brnz,pn %o1, bootpath_known | |
183 | #endif | |
184 | ||
185 | /* getprop(chosen_node, "bootpath", &buffer, buffer_size) */ | |
186 | GET_ABS(prom_bootpath_name, %o2) | |
187 | call prom_call_getprop | |
188 | mov (boot_path_end - boot_path), %o4 | |
189 | ||
190 | bootpath_known: | |
191 | ||
192 | /* Open up the boot_path, and use that handle to read the | |
193 | * first block of the GRUB kernel image. | |
194 | * | |
195 | * bootdev_handle = open(boot_path) | |
196 | */ | |
197 | GET_ABS(prom_open_name, %o0) | |
198 | call prom_call_1_1_o2 | |
199 | GET_ABS(boot_path, %o1) | |
200 | ||
201 | ldx [%l1 + 0x20], BOOTDEV_REG | |
202 | brz,pn BOOTDEV_REG, prom_open_error | |
203 | ||
204 | /* Since we have 64-bit cells, the high cell of the seek offset | |
205 | * is zero and the low cell is the entire value. | |
206 | * | |
207 | * seek(bootdev, 0, *kernel_byte) | |
208 | */ | |
209 | GET_ABS(prom_seek_name, %o0) | |
210 | clr %o2 | |
211 | call prom_call_3_1_o1 | |
212 | LDX_ABS(kernel_byte, 0x00, %o3) | |
213 | ||
214 | /* read(bootdev, *kernel_address, 512) */ | |
215 | GET_ABS(prom_read_name, %o0) | |
216 | LDUW_ABS(kernel_address, 0x00, %o2) | |
217 | call prom_call_3_1_o1 | |
218 | #ifdef CDBOOT | |
219 | LDUW_ABS(kernel_size, 0x00, %o3) | |
e1c95655 ES |
220 | |
221 | GET_ABS(prom_close_name, %o0) | |
222 | mov 1, %g1 | |
223 | mov 0, %o5 | |
224 | call prom_call | |
225 | mov BOOTDEV_REG, %o1 | |
4d8d554a CW |
226 | #else |
227 | mov 512, %o3 | |
228 | #endif | |
229 | ||
230 | LDUW_ABS(kernel_address, 0x00, %o2) | |
231 | jmpl %o2, %o7 | |
232 | #ifdef CDBOOT | |
233 | mov CIF_REG, %o4 | |
234 | #else | |
235 | nop | |
236 | #endif | |
237 | .org GRUB_BOOT_MACHINE_CODE_END | |
238 | ||
239 | /* the last 4 bytes in the sector 0 contain the signature */ | |
240 | .word GRUB_BOOT_MACHINE_SIGNATURE |