2 * Copyright (C) Paul Mackerras 1997.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
18 typedef void *ihandle
;
19 typedef void *phandle
;
23 /* Value picked to match that used by yaboot */
24 #define PROG_START 0x01400000 /* only used on 64-bit systems */
25 #define RAM_END (512<<20) /* Fixme: use OF */
26 #define ONE_MB 0x100000
31 static unsigned long claim_base
;
33 static int call_prom(const char *service
, int nargs
, int nret
, ...)
40 unsigned int args
[12];
44 args
.service
= service
;
49 for (i
= 0; i
< nargs
; i
++)
50 args
.args
[i
] = va_arg(list
, unsigned int);
53 for (i
= 0; i
< nret
; i
++)
54 args
.args
[nargs
+i
] = 0;
59 return (nret
> 0)? args
.args
[nargs
]: 0;
62 static int call_prom_ret(const char *service
, int nargs
, int nret
,
63 unsigned int *rets
, ...)
70 unsigned int args
[12];
74 args
.service
= service
;
79 for (i
= 0; i
< nargs
; i
++)
80 args
.args
[i
] = va_arg(list
, unsigned int);
83 for (i
= 0; i
< nret
; i
++)
84 args
.args
[nargs
+i
] = 0;
89 if (rets
!= (void *) 0)
90 for (i
= 1; i
< nret
; ++i
)
91 rets
[i
-1] = args
.args
[nargs
+i
];
93 return (nret
> 0)? args
.args
[nargs
]: 0;
97 * Older OF's require that when claiming a specific range of addresses,
98 * we claim the physical space in the /memory node and the virtual
99 * space in the chosen mmu node, and then do a map operation to
100 * map virtual to physical.
102 static int need_map
= -1;
103 static ihandle chosen_mmu
;
104 static phandle memory
;
106 /* returns true if s2 is a prefix of s1 */
107 static int string_match(const char *s1
, const char *s2
)
115 static int check_of_version(void)
117 phandle oprom
, chosen
;
120 oprom
= finddevice("/openprom");
121 if (oprom
== (phandle
) -1)
123 if (getprop(oprom
, "model", version
, sizeof(version
)) <= 0)
125 version
[sizeof(version
)-1] = 0;
126 printf("OF version = '%s'\r\n", version
);
127 if (!string_match(version
, "Open Firmware, 1.")
128 && !string_match(version
, "FirmWorks,3."))
130 chosen
= finddevice("/chosen");
131 if (chosen
== (phandle
) -1) {
132 chosen
= finddevice("/chosen@0");
133 if (chosen
== (phandle
) -1) {
134 printf("no chosen\n");
138 if (getprop(chosen
, "mmu", &chosen_mmu
, sizeof(chosen_mmu
)) <= 0) {
142 memory
= (ihandle
) call_prom("open", 1, 1, "/memory");
143 if (memory
== (ihandle
) -1) {
144 memory
= (ihandle
) call_prom("open", 1, 1, "/memory@0");
145 if (memory
== (ihandle
) -1) {
146 printf("no memory node\n");
150 printf("old OF detected\r\n");
154 static void *claim(unsigned long virt
, unsigned long size
, unsigned long align
)
160 need_map
= check_of_version();
161 if (align
|| !need_map
)
162 return (void *) call_prom("claim", 3, 1, virt
, size
, align
);
164 ret
= call_prom_ret("call-method", 5, 2, &result
, "claim", memory
,
166 if (ret
!= 0 || result
== -1)
168 ret
= call_prom_ret("call-method", 5, 2, &result
, "claim", chosen_mmu
,
170 /* 0x12 == coherent + read/write */
171 ret
= call_prom("call-method", 6, 1, "map", chosen_mmu
,
172 0x12, size
, virt
, virt
);
173 return (void *) virt
;
176 static void *of_try_claim(unsigned long size
)
178 unsigned long addr
= 0;
181 claim_base
= _ALIGN_UP((unsigned long)_end
, ONE_MB
);
183 for(; claim_base
< RAM_END
; claim_base
+= ONE_MB
) {
185 printf(" trying: 0x%08lx\n\r", claim_base
);
187 addr
= (unsigned long)claim(claim_base
, size
, 0);
188 if ((void *)addr
!= (void *)-1)
193 claim_base
= PAGE_ALIGN(claim_base
+ size
);
197 static void of_image_hdr(const void *hdr
)
199 const Elf64_Ehdr
*elf64
= hdr
;
201 if (elf64
->e_ident
[EI_CLASS
] == ELFCLASS64
) {
203 * Maintain a "magic" minimum address. This keeps some older
204 * firmware platforms running.
206 if (claim_base
< PROG_START
)
207 claim_base
= PROG_START
;
211 static void *of_vmlinux_alloc(unsigned long size
)
213 void *p
= malloc(size
);
216 fatal("Can't allocate memory for kernel image!\n\r");
221 static void of_exit(void)
223 call_prom("exit", 0, 0);
227 * OF device tree routines
229 static void *of_finddevice(const char *name
)
231 return (phandle
) call_prom("finddevice", 1, 1, name
);
234 static int of_getprop(const void *phandle
, const char *name
, void *buf
,
237 return call_prom("getprop", 4, 1, phandle
, name
, buf
, buflen
);
240 static int of_setprop(const void *phandle
, const char *name
, const void *buf
,
243 return call_prom("setprop", 4, 1, phandle
, name
, buf
, buflen
);
247 * OF console routines
249 static void *of_stdout_handle
;
251 static int of_console_open(void)
255 if (((devp
= finddevice("/chosen")) != NULL
)
256 && (getprop(devp
, "stdout", &of_stdout_handle
,
257 sizeof(of_stdout_handle
))
258 == sizeof(of_stdout_handle
)))
264 static void of_console_write(char *buf
, int len
)
266 call_prom("write", 3, 1, of_stdout_handle
, buf
, len
);
269 void platform_init(unsigned long a1
, unsigned long a2
, void *promptr
)
271 platform_ops
.image_hdr
= of_image_hdr
;
272 platform_ops
.malloc
= of_try_claim
;
273 platform_ops
.exit
= of_exit
;
274 platform_ops
.vmlinux_alloc
= of_vmlinux_alloc
;
276 dt_ops
.finddevice
= of_finddevice
;
277 dt_ops
.getprop
= of_getprop
;
278 dt_ops
.setprop
= of_setprop
;
280 console_ops
.open
= of_console_open
;
281 console_ops
.write
= of_console_write
;
283 prom
= (int (*)(void *))promptr
;
284 loader_info
.promptr
= promptr
;
285 if (a1
&& a2
&& a2
!= 0xdeadbeef) {
286 loader_info
.initrd_addr
= a1
;
287 loader_info
.initrd_size
= a2
;