sparc64: Close cdboot ihandle
[grub.git] / grub-core / boot / sparc64 / ieee1275 / boot.S
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 "
72 #ifdef CDBOOT
73 prom_close_name:        .asciz "close"
74 #endif
75
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)
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
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