3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
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.
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.
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/>.
20 #include <grub/machine/boot.h>
26 /* OF CIF entry point arrives in %o4 */
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.
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.
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).
44 .org GRUB_BOOT_MACHINE_BOOT_DEVPATH
46 .org GRUB_BOOT_MACHINE_KERNEL_BYTE
48 kernel_byte: .xword (2 << 9)
49 kernel_address: .word GRUB_BOOT_MACHINE_KERNEL_ADDR
51 #define boot_path (_start + 512 + SCRATCH_PAD_BOOT_SIZE)
52 #define boot_path_end (_start + 1024)
53 #include <grub/offsets.h>
56 kernel_byte: .xword (2 << 9)
57 kernel_size: .word 512
58 kernel_address: .word GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS
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 "
72 #define GRUB_NAME_LEN 5
77 GET_ABS(prom_open_name, %o2)
83 GET_ABS(prom_exit_name, %o0)
97 mov CHOSEN_NODE_REG, %o1
99 GET_ABS(prom_getprop_name, %o0)
106 /* %o2: message string
107 * %o3: message length
110 GET_ABS(prom_write_name, %o0)
111 mov STDOUT_NODE_REG, %o1
131 stx %o0, [%l1 + 0x00]
132 stx %g1, [%l1 + 0x08]
133 stx %o5, [%l1 + 0x10]
134 stx %o1, [%l1 + 0x18]
135 stx %o2, [%l1 + 0x20]
136 stx %o3, [%l1 + 0x28]
137 stx %o4, [%l1 + 0x30]
142 mov %o7, PIC_REG /* PIC base */
144 sethi %hi(SCRATCH_PAD_BOOT), %l1 /* OF argument slots */
146 GET_ABS(_start + 512, %l1) /* OF argument slots */
149 /* Find the /chosen node so we can fetch the stdout handle,
150 * and thus perform console output.
152 * chosen_node = prom_finddevice("/chosen")
154 GET_ABS(prom_finddev_name, %o0)
155 call prom_call_1_1_o2
156 GET_ABS(prom_chosen_path, %o1)
158 ldx [%l1 + 0x20], CHOSEN_NODE_REG
159 brz CHOSEN_NODE_REG, prom_error
161 /* getprop(chosen_node, "stdout", &buffer, buffer_size) */
162 GET_ABS(prom_stdout_name, %o2)
164 call prom_call_getprop
167 lduw [%l1 + 256], STDOUT_NODE_REG
168 brz,pn STDOUT_NODE_REG, prom_error
170 /* write(stdout_node, "GRUB ", strlen("GRUB ")) */
171 GET_ABS(grub_name, %o2)
173 mov GRUB_NAME_LEN, %o3
175 GET_ABS(boot_path, %o3)
178 brnz,pn %o1, bootpath_known
181 /* getprop(chosen_node, "bootpath", &buffer, buffer_size) */
182 GET_ABS(prom_bootpath_name, %o2)
183 call prom_call_getprop
184 mov (boot_path_end - boot_path), %o4
188 /* Open up the boot_path, and use that handle to read the
189 * first block of the GRUB kernel image.
191 * bootdev_handle = open(boot_path)
193 GET_ABS(prom_open_name, %o0)
194 call prom_call_1_1_o2
195 GET_ABS(boot_path, %o1)
197 ldx [%l1 + 0x20], BOOTDEV_REG
198 brz,pn BOOTDEV_REG, prom_open_error
200 /* Since we have 64-bit cells, the high cell of the seek offset
201 * is zero and the low cell is the entire value.
203 * seek(bootdev, 0, *kernel_byte)
205 GET_ABS(prom_seek_name, %o0)
207 call prom_call_3_1_o1
208 LDX_ABS(kernel_byte, 0x00, %o3)
210 /* read(bootdev, *kernel_address, 512) */
211 GET_ABS(prom_read_name, %o0)
212 LDUW_ABS(kernel_address, 0x00, %o2)
213 call prom_call_3_1_o1
215 LDUW_ABS(kernel_size, 0x00, %o3)
220 LDUW_ABS(kernel_address, 0x00, %o2)
227 .org GRUB_BOOT_MACHINE_CODE_END
229 /* the last 4 bytes in the sector 0 contain the signature */
230 .word GRUB_BOOT_MACHINE_SIGNATURE