aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/boot/Makefile3
-rw-r--r--arch/powerpc/boot/flatdevtree.h46
-rw-r--r--arch/powerpc/boot/main.c250
-rw-r--r--arch/powerpc/boot/of.c (renamed from arch/powerpc/boot/prom.c)144
-rw-r--r--arch/powerpc/boot/ops.h100
-rw-r--r--arch/powerpc/boot/prom.h41
-rw-r--r--arch/powerpc/boot/stdio.c4
-rw-r--r--arch/powerpc/boot/stdio.h8
-rw-r--r--arch/powerpc/boot/types.h23
9 files changed, 441 insertions, 178 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index afc776f821e5..e73774136b55 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -36,7 +36,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h
36$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) 36$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
37#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) 37#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
38 38
39src-boot := crt0.S string.S prom.c stdio.c main.c div64.S 39src-boot-$(CONFIG_PPC_MULTIPLATFORM) := of.c
40src-boot := crt0.S string.S stdio.c main.c div64.S $(src-boot-y)
40src-boot += $(zlib) 41src-boot += $(zlib)
41src-boot := $(addprefix $(obj)/, $(src-boot)) 42src-boot := $(addprefix $(obj)/, $(src-boot))
42obj-boot := $(addsuffix .o, $(basename $(src-boot))) 43obj-boot := $(addsuffix .o, $(basename $(src-boot)))
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h
new file mode 100644
index 000000000000..761c8dc84008
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree.h
@@ -0,0 +1,46 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17#ifndef FLATDEVTREE_H
18#define FLATDEVTREE_H
19
20#include "types.h"
21
22/* Definitions used by the flattened device tree */
23#define OF_DT_HEADER 0xd00dfeed /* marker */
24#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
25#define OF_DT_END_NODE 0x2 /* End node */
26#define OF_DT_PROP 0x3 /* Property: name off, size, content */
27#define OF_DT_NOP 0x4 /* nop */
28#define OF_DT_END 0x9
29
30#define OF_DT_VERSION 0x10
31
32struct boot_param_header {
33 u32 magic; /* magic word OF_DT_HEADER */
34 u32 totalsize; /* total size of DT block */
35 u32 off_dt_struct; /* offset to structure */
36 u32 off_dt_strings; /* offset to strings */
37 u32 off_mem_rsvmap; /* offset to memory reserve map */
38 u32 version; /* format version */
39 u32 last_comp_version; /* last compatible version */
40 /* version 2 fields below */
41 u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
42 /* version 3 fields below */
43 u32 dt_strings_size; /* size of the DT strings block */
44};
45
46#endif /* FLATDEVTREE_H */
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index b66634c9ea34..d719bb9333d1 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -14,17 +14,12 @@
14#include "page.h" 14#include "page.h"
15#include "string.h" 15#include "string.h"
16#include "stdio.h" 16#include "stdio.h"
17#include "prom.h"
18#include "zlib.h" 17#include "zlib.h"
18#include "ops.h"
19#include "flatdevtree.h"
19 20
20extern void flush_cache(void *, unsigned long); 21extern void flush_cache(void *, unsigned long);
21 22
22
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
27
28extern char _start[]; 23extern char _start[];
29extern char __bss_start[]; 24extern char __bss_start[];
30extern char _end[]; 25extern char _end[];
@@ -33,14 +28,6 @@ extern char _vmlinux_end[];
33extern char _initrd_start[]; 28extern char _initrd_start[];
34extern char _initrd_end[]; 29extern char _initrd_end[];
35 30
36/* A buffer that may be edited by tools operating on a zImage binary so as to
37 * edit the command line passed to vmlinux (by setting /chosen/bootargs).
38 * The buffer is put in it's own section so that tools may locate it easier.
39 */
40static char builtin_cmdline[512]
41 __attribute__((section("__builtin_cmdline")));
42
43
44struct addr_range { 31struct addr_range {
45 unsigned long addr; 32 unsigned long addr;
46 unsigned long size; 33 unsigned long size;
@@ -51,21 +38,16 @@ static struct addr_range vmlinuz;
51static struct addr_range initrd; 38static struct addr_range initrd;
52 39
53static unsigned long elfoffset; 40static unsigned long elfoffset;
41static int is_64bit;
54 42
55static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */ 43/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */
44static char scratch[46912];
56static char elfheader[256]; 45static char elfheader[256];
57 46
58 47typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
59typedef void (*kernel_entry_t)( unsigned long,
60 unsigned long,
61 void *,
62 void *);
63
64 48
65#undef DEBUG 49#undef DEBUG
66 50
67static unsigned long claim_base;
68
69#define HEAD_CRC 2 51#define HEAD_CRC 2
70#define EXTRA_FIELD 4 52#define EXTRA_FIELD 4
71#define ORIG_NAME 8 53#define ORIG_NAME 8
@@ -123,24 +105,6 @@ static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
123 zlib_inflateEnd(&s); 105 zlib_inflateEnd(&s);
124} 106}
125 107
126static unsigned long try_claim(unsigned long size)
127{
128 unsigned long addr = 0;
129
130 for(; claim_base < RAM_END; claim_base += ONE_MB) {
131#ifdef DEBUG
132 printf(" trying: 0x%08lx\n\r", claim_base);
133#endif
134 addr = (unsigned long)claim(claim_base, size, 0);
135 if ((void *)addr != (void *)-1)
136 break;
137 }
138 if (addr == 0)
139 return 0;
140 claim_base = PAGE_ALIGN(claim_base + size);
141 return addr;
142}
143
144static int is_elf64(void *hdr) 108static int is_elf64(void *hdr)
145{ 109{
146 Elf64_Ehdr *elf64 = hdr; 110 Elf64_Ehdr *elf64 = hdr;
@@ -169,16 +133,7 @@ static int is_elf64(void *hdr)
169 vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; 133 vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
170 vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; 134 vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
171 135
172#if defined(PROG_START) 136 is_64bit = 1;
173 /*
174 * Maintain a "magic" minimum address. This keeps some older
175 * firmware platforms running.
176 */
177
178 if (claim_base < PROG_START)
179 claim_base = PROG_START;
180#endif
181
182 return 1; 137 return 1;
183} 138}
184 139
@@ -212,47 +167,9 @@ static int is_elf32(void *hdr)
212 return 1; 167 return 1;
213} 168}
214 169
215void export_cmdline(void* chosen_handle) 170static void prep_kernel(unsigned long *a1, unsigned long *a2)
216{
217 int len;
218 char cmdline[2] = { 0, 0 };
219
220 if (builtin_cmdline[0] == 0)
221 return;
222
223 len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline));
224 if (len > 0 && cmdline[0] != 0)
225 return;
226
227 setprop(chosen_handle, "bootargs", builtin_cmdline,
228 strlen(builtin_cmdline) + 1);
229}
230
231
232void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
233{ 171{
234 int len; 172 int len;
235 kernel_entry_t kernel_entry;
236
237 memset(__bss_start, 0, _end - __bss_start);
238
239 prom = (int (*)(void *)) promptr;
240 chosen_handle = finddevice("/chosen");
241 if (chosen_handle == (void *) -1)
242 exit();
243 if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
244 exit();
245
246 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
247
248 /*
249 * The first available claim_base must be above the end of the
250 * the loaded kernel wrapper file (_start to _end includes the
251 * initrd image if it is present) and rounded up to a nice
252 * 1 MB boundary for good measure.
253 */
254
255 claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
256 173
257 vmlinuz.addr = (unsigned long)_vmlinux_start; 174 vmlinuz.addr = (unsigned long)_vmlinux_start;
258 vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); 175 vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
@@ -263,43 +180,51 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
263 gunzip(elfheader, sizeof(elfheader), 180 gunzip(elfheader, sizeof(elfheader),
264 (unsigned char *)vmlinuz.addr, &len); 181 (unsigned char *)vmlinuz.addr, &len);
265 } else 182 } else
266 memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader)); 183 memcpy(elfheader, (const void *)vmlinuz.addr,
184 sizeof(elfheader));
267 185
268 if (!is_elf64(elfheader) && !is_elf32(elfheader)) { 186 if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
269 printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); 187 printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
270 exit(); 188 exit();
271 } 189 }
190 if (platform_ops.image_hdr)
191 platform_ops.image_hdr(elfheader);
272 192
273 /* We need to claim the memsize plus the file offset since gzip 193 /* We need to alloc the memsize plus the file offset since gzip
274 * will expand the header (file offset), then the kernel, then 194 * will expand the header (file offset), then the kernel, then
275 * possible rubbish we don't care about. But the kernel bss must 195 * possible rubbish we don't care about. But the kernel bss must
276 * be claimed (it will be zero'd by the kernel itself) 196 * be claimed (it will be zero'd by the kernel itself)
277 */ 197 */
278 printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize); 198 printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
279 vmlinux.addr = try_claim(vmlinux.memsize); 199 vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
280 if (vmlinux.addr == 0) { 200 if (vmlinux.addr == 0) {
281 printf("Can't allocate memory for kernel image !\n\r"); 201 printf("Can't allocate memory for kernel image !\n\r");
282 exit(); 202 exit();
283 } 203 }
284 204
285 /* 205 /*
286 * Now we try to claim memory for the initrd (and copy it there) 206 * Now we try to alloc memory for the initrd (and copy it there)
287 */ 207 */
288 initrd.size = (unsigned long)(_initrd_end - _initrd_start); 208 initrd.size = (unsigned long)(_initrd_end - _initrd_start);
289 initrd.memsize = initrd.size; 209 initrd.memsize = initrd.size;
290 if ( initrd.size > 0 ) { 210 if ( initrd.size > 0 ) {
291 printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size); 211 printf("Allocating 0x%lx bytes for initrd ...\n\r",
292 initrd.addr = try_claim(initrd.size); 212 initrd.size);
213 initrd.addr = (unsigned long)malloc((u32)initrd.size);
293 if (initrd.addr == 0) { 214 if (initrd.addr == 0) {
294 printf("Can't allocate memory for initial ramdisk !\n\r"); 215 printf("Can't allocate memory for initial "
216 "ramdisk !\n\r");
295 exit(); 217 exit();
296 } 218 }
297 a1 = initrd.addr; 219 *a1 = initrd.addr;
298 a2 = initrd.size; 220 *a2 = initrd.size;
299 printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r", 221 printf("initial ramdisk moving 0x%lx <- 0x%lx "
300 initrd.addr, (unsigned long)_initrd_start, initrd.size); 222 "(0x%lx bytes)\n\r", initrd.addr,
301 memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size); 223 (unsigned long)_initrd_start, initrd.size);
302 printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr)); 224 memmove((void *)initrd.addr, (void *)_initrd_start,
225 initrd.size);
226 printf("initrd head: 0x%lx\n\r",
227 *((unsigned long *)initrd.addr));
303 } 228 }
304 229
305 /* Eventually gunzip the kernel */ 230 /* Eventually gunzip the kernel */
@@ -311,11 +236,10 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
311 (unsigned char *)vmlinuz.addr, &len); 236 (unsigned char *)vmlinuz.addr, &len);
312 printf("done 0x%lx bytes\n\r", len); 237 printf("done 0x%lx bytes\n\r", len);
313 } else { 238 } else {
314 memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); 239 memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,
240 vmlinuz.size);
315 } 241 }
316 242
317 export_cmdline(chosen_handle);
318
319 /* Skip over the ELF header */ 243 /* Skip over the ELF header */
320#ifdef DEBUG 244#ifdef DEBUG
321 printf("... skipping 0x%lx bytes of ELF header\n\r", 245 printf("... skipping 0x%lx bytes of ELF header\n\r",
@@ -324,23 +248,107 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
324 vmlinux.addr += elfoffset; 248 vmlinux.addr += elfoffset;
325 249
326 flush_cache((void *)vmlinux.addr, vmlinux.size); 250 flush_cache((void *)vmlinux.addr, vmlinux.size);
251}
327 252
328 kernel_entry = (kernel_entry_t)vmlinux.addr; 253void __attribute__ ((weak)) ft_init(void *dt_blob)
329#ifdef DEBUG 254{
330 printf( "kernel:\n\r" 255}
331 " entry addr = 0x%lx\n\r"
332 " a1 = 0x%lx,\n\r"
333 " a2 = 0x%lx,\n\r"
334 " prom = 0x%lx,\n\r"
335 " bi_recs = 0x%lx,\n\r",
336 (unsigned long)kernel_entry, a1, a2,
337 (unsigned long)prom, NULL);
338#endif
339 256
340 kernel_entry(a1, a2, prom, NULL); 257/* A buffer that may be edited by tools operating on a zImage binary so as to
258 * edit the command line passed to vmlinux (by setting /chosen/bootargs).
259 * The buffer is put in it's own section so that tools may locate it easier.
260 */
261static char builtin_cmdline[COMMAND_LINE_SIZE]
262 __attribute__((__section__("__builtin_cmdline")));
341 263
342 printf("Error: Linux kernel returned to zImage bootloader!\n\r"); 264static void get_cmdline(char *buf, int size)
265{
266 void *devp;
267 int len = strlen(builtin_cmdline);
343 268
344 exit(); 269 buf[0] = '\0';
270
271 if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */
272 len = min(len, size-1);
273 strncpy(buf, builtin_cmdline, len);
274 buf[len] = '\0';
275 }
276 else if ((devp = finddevice("/chosen")))
277 getprop(devp, "bootargs", buf, size);
278}
279
280static void set_cmdline(char *buf)
281{
282 void *devp;
283
284 if ((devp = finddevice("/chosen")))
285 setprop(devp, "bootargs", buf, strlen(buf) + 1);
345} 286}
346 287
288/* Section where ft can be tacked on after zImage is built */
289union blobspace {
290 struct boot_param_header hdr;
291 char space[8*1024];
292} dt_blob __attribute__((__section__("__builtin_ft")));
293
294struct platform_ops platform_ops;
295struct dt_ops dt_ops;
296struct console_ops console_ops;
297
298void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
299{
300 int have_dt = 0;
301 kernel_entry_t kentry;
302 char cmdline[COMMAND_LINE_SIZE];
303
304 memset(__bss_start, 0, _end - __bss_start);
305 memset(&platform_ops, 0, sizeof(platform_ops));
306 memset(&dt_ops, 0, sizeof(dt_ops));
307 memset(&console_ops, 0, sizeof(console_ops));
308
309 /* Override the dt_ops and device tree if there was an flat dev
310 * tree attached to the zImage.
311 */
312 if (dt_blob.hdr.magic == OF_DT_HEADER) {
313 have_dt = 1;
314 ft_init(&dt_blob);
315 }
316
317 if (platform_init(promptr))
318 exit();
319 if (console_ops.open && (console_ops.open() < 0))
320 exit();
321 if (platform_ops.fixups)
322 platform_ops.fixups();
323
324 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
325 _start, sp);
326
327 prep_kernel(&a1, &a2);
328
329 /* If cmdline came from zimage wrapper or if we can edit the one
330 * in the dt, print it out and edit it, if possible.
331 */
332 if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) {
333 get_cmdline(cmdline, COMMAND_LINE_SIZE);
334 printf("\n\rLinux/PowerPC load: %s", cmdline);
335 if (console_ops.edit_cmdline)
336 console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
337 printf("\n\r");
338 set_cmdline(cmdline);
339 }
340
341 if (console_ops.close)
342 console_ops.close();
343
344 kentry = (kernel_entry_t) vmlinux.addr;
345 if (have_dt)
346 kentry(dt_ops.ft_addr(), 0, NULL);
347 else
348 /* XXX initrd addr/size should be passed in properties */
349 kentry(a1, a2, promptr);
350
351 /* console closed so printf below may not work */
352 printf("Error: Linux kernel returned to zImage boot wrapper!\n\r");
353 exit();
354}
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/of.c
index fa0057736f6b..fd99f789a37b 100644
--- a/arch/powerpc/boot/prom.c
+++ b/arch/powerpc/boot/of.c
@@ -8,15 +8,29 @@
8 */ 8 */
9#include <stdarg.h> 9#include <stdarg.h>
10#include <stddef.h> 10#include <stddef.h>
11#include "types.h"
12#include "elf.h"
11#include "string.h" 13#include "string.h"
12#include "stdio.h" 14#include "stdio.h"
13#include "prom.h" 15#include "page.h"
16#include "ops.h"
14 17
15int (*prom)(void *); 18typedef void *ihandle;
16phandle chosen_handle; 19typedef void *phandle;
17ihandle stdout;
18 20
19int call_prom(const char *service, int nargs, int nret, ...) 21extern char _end[];
22
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
27
28int (*prom) (void *);
29
30
31static unsigned long claim_base;
32
33static int call_prom(const char *service, int nargs, int nret, ...)
20{ 34{
21 int i; 35 int i;
22 struct prom_args { 36 struct prom_args {
@@ -45,7 +59,7 @@ int call_prom(const char *service, int nargs, int nret, ...)
45 return (nret > 0)? args.args[nargs]: 0; 59 return (nret > 0)? args.args[nargs]: 0;
46} 60}
47 61
48int call_prom_ret(const char *service, int nargs, int nret, 62static int call_prom_ret(const char *service, int nargs, int nret,
49 unsigned int *rets, ...) 63 unsigned int *rets, ...)
50{ 64{
51 int i; 65 int i;
@@ -79,11 +93,6 @@ int call_prom_ret(const char *service, int nargs, int nret,
79 return (nret > 0)? args.args[nargs]: 0; 93 return (nret > 0)? args.args[nargs]: 0;
80} 94}
81 95
82int write(void *handle, void *ptr, int nb)
83{
84 return call_prom("write", 3, 1, handle, ptr, nb);
85}
86
87/* 96/*
88 * Older OF's require that when claiming a specific range of addresses, 97 * Older OF's require that when claiming a specific range of addresses,
89 * we claim the physical space in the /memory node and the virtual 98 * we claim the physical space in the /memory node and the virtual
@@ -142,7 +151,7 @@ static int check_of_version(void)
142 return 1; 151 return 1;
143} 152}
144 153
145void *claim(unsigned long virt, unsigned long size, unsigned long align) 154static void *claim(unsigned long virt, unsigned long size, unsigned long align)
146{ 155{
147 int ret; 156 int ret;
148 unsigned int result; 157 unsigned int result;
@@ -151,7 +160,7 @@ void *claim(unsigned long virt, unsigned long size, unsigned long align)
151 need_map = check_of_version(); 160 need_map = check_of_version();
152 if (align || !need_map) 161 if (align || !need_map)
153 return (void *) call_prom("claim", 3, 1, virt, size, align); 162 return (void *) call_prom("claim", 3, 1, virt, size, align);
154 163
155 ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, 164 ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
156 align, size, virt); 165 align, size, virt);
157 if (ret != 0 || result == -1) 166 if (ret != 0 || result == -1)
@@ -163,3 +172,112 @@ void *claim(unsigned long virt, unsigned long size, unsigned long align)
163 0x12, size, virt, virt); 172 0x12, size, virt, virt);
164 return (void *) virt; 173 return (void *) virt;
165} 174}
175
176static void *of_try_claim(u32 size)
177{
178 unsigned long addr = 0;
179 static u8 first_time = 1;
180
181 if (first_time) {
182 claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
183 first_time = 0;
184 }
185
186 for(; claim_base < RAM_END; claim_base += ONE_MB) {
187#ifdef DEBUG
188 printf(" trying: 0x%08lx\n\r", claim_base);
189#endif
190 addr = (unsigned long)claim(claim_base, size, 0);
191 if ((void *)addr != (void *)-1)
192 break;
193 }
194 if (addr == 0)
195 return NULL;
196 claim_base = PAGE_ALIGN(claim_base + size);
197 return (void *)addr;
198}
199
200static void of_image_hdr(const void *hdr)
201{
202 const Elf64_Ehdr *elf64 = hdr;
203
204 if (elf64->e_ident[EI_CLASS] == ELFCLASS64) {
205 /*
206 * Maintain a "magic" minimum address. This keeps some older
207 * firmware platforms running.
208 */
209 if (claim_base < PROG_START)
210 claim_base = PROG_START;
211 }
212}
213
214static void of_exit(void)
215{
216 call_prom("exit", 0, 0);
217}
218
219/*
220 * OF device tree routines
221 */
222static void *of_finddevice(const char *name)
223{
224 return (phandle) call_prom("finddevice", 1, 1, name);
225}
226
227static int of_getprop(const void *phandle, const char *name, void *buf,
228 const int buflen)
229{
230 return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
231}
232
233static int of_setprop(const void *phandle, const char *name, const void *buf,
234 const int buflen)
235{
236 return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
237}
238
239/*
240 * OF console routines
241 */
242static void *of_stdout_handle;
243
244static int of_console_open(void)
245{
246 void *devp;
247
248 if (((devp = finddevice("/chosen")) != NULL)
249 && (getprop(devp, "stdout", &of_stdout_handle,
250 sizeof(of_stdout_handle))
251 == sizeof(of_stdout_handle)))
252 return 0;
253
254 return -1;
255}
256
257static void of_console_write(char *buf, int len)
258{
259 call_prom("write", 3, 1, of_stdout_handle, buf, len);
260}
261
262int platform_init(void *promptr)
263{
264 platform_ops.fixups = NULL;
265 platform_ops.image_hdr = of_image_hdr;
266 platform_ops.malloc = of_try_claim;
267 platform_ops.free = NULL;
268 platform_ops.exit = of_exit;
269
270 dt_ops.finddevice = of_finddevice;
271 dt_ops.getprop = of_getprop;
272 dt_ops.setprop = of_setprop;
273 dt_ops.translate_addr = NULL;
274
275 console_ops.open = of_console_open;
276 console_ops.write = of_console_write;
277 console_ops.edit_cmdline = NULL;
278 console_ops.close = NULL;
279 console_ops.data = NULL;
280
281 prom = (int (*)(void *))promptr;
282 return 0;
283}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
new file mode 100644
index 000000000000..135eb4bb03b4
--- /dev/null
+++ b/arch/powerpc/boot/ops.h
@@ -0,0 +1,100 @@
1/*
2 * Global definition of all the bootwrapper operations.
3 *
4 * Author: Mark A. Greer <mgreer@mvista.com>
5 *
6 * 2006 (c) MontaVista Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11#ifndef _PPC_BOOT_OPS_H_
12#define _PPC_BOOT_OPS_H_
13
14#include "types.h"
15
16#define COMMAND_LINE_SIZE 512
17#define MAX_PATH_LEN 256
18#define MAX_PROP_LEN 256 /* What should this be? */
19
20/* Platform specific operations */
21struct platform_ops {
22 void (*fixups)(void);
23 void (*image_hdr)(const void *);
24 void * (*malloc)(u32 size);
25 void (*free)(void *ptr, u32 size);
26 void (*exit)(void);
27};
28extern struct platform_ops platform_ops;
29
30/* Device Tree operations */
31struct dt_ops {
32 void * (*finddevice)(const char *name);
33 int (*getprop)(const void *node, const char *name, void *buf,
34 const int buflen);
35 int (*setprop)(const void *node, const char *name,
36 const void *buf, const int buflen);
37 u64 (*translate_addr)(const char *path, const u32 *in_addr,
38 const u32 addr_len);
39 unsigned long (*ft_addr)(void);
40};
41extern struct dt_ops dt_ops;
42
43/* Console operations */
44struct console_ops {
45 int (*open)(void);
46 void (*write)(char *buf, int len);
47 void (*edit_cmdline)(char *buf, int len);
48 void (*close)(void);
49 void *data;
50};
51extern struct console_ops console_ops;
52
53/* Serial console operations */
54struct serial_console_data {
55 int (*open)(void);
56 void (*putc)(unsigned char c);
57 unsigned char (*getc)(void);
58 u8 (*tstc)(void);
59 void (*close)(void);
60};
61
62extern int platform_init(void *promptr);
63extern void simple_alloc_init(void);
64extern void ft_init(void *dt_blob);
65extern int serial_console_init(void);
66
67static inline void *finddevice(const char *name)
68{
69 return (dt_ops.finddevice) ? dt_ops.finddevice(name) : NULL;
70}
71
72static inline int getprop(void *devp, const char *name, void *buf, int buflen)
73{
74 return (dt_ops.getprop) ? dt_ops.getprop(devp, name, buf, buflen) : -1;
75}
76
77static inline int setprop(void *devp, const char *name, void *buf, int buflen)
78{
79 return (dt_ops.setprop) ? dt_ops.setprop(devp, name, buf, buflen) : -1;
80}
81
82static inline void *malloc(u32 size)
83{
84 return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
85}
86
87static inline void free(void *ptr, u32 size)
88{
89 if (platform_ops.free)
90 platform_ops.free(ptr, size);
91}
92
93static inline void exit(void)
94{
95 if (platform_ops.exit)
96 platform_ops.exit();
97 for(;;);
98}
99
100#endif /* _PPC_BOOT_OPS_H_ */
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
deleted file mode 100644
index a57b184c564f..000000000000
--- a/arch/powerpc/boot/prom.h
+++ /dev/null
@@ -1,41 +0,0 @@
1#ifndef _PPC_BOOT_PROM_H_
2#define _PPC_BOOT_PROM_H_
3
4typedef void *phandle;
5typedef void *ihandle;
6
7extern int (*prom) (void *);
8extern phandle chosen_handle;
9extern ihandle stdout;
10
11int call_prom(const char *service, int nargs, int nret, ...);
12int call_prom_ret(const char *service, int nargs, int nret,
13 unsigned int *rets, ...);
14
15extern int write(void *handle, void *ptr, int nb);
16extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
17
18static inline void exit(void)
19{
20 call_prom("exit", 0, 0);
21}
22
23static inline phandle finddevice(const char *name)
24{
25 return (phandle) call_prom("finddevice", 1, 1, name);
26}
27
28static inline int getprop(void *phandle, const char *name,
29 void *buf, int buflen)
30{
31 return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
32}
33
34
35static inline int setprop(void *phandle, const char *name,
36 void *buf, int buflen)
37{
38 return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
39}
40
41#endif /* _PPC_BOOT_PROM_H_ */
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index b5aa522f8b77..6d5f6382e1ce 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -10,7 +10,7 @@
10#include <stddef.h> 10#include <stddef.h>
11#include "string.h" 11#include "string.h"
12#include "stdio.h" 12#include "stdio.h"
13#include "prom.h" 13#include "ops.h"
14 14
15size_t strnlen(const char * s, size_t count) 15size_t strnlen(const char * s, size_t count)
16{ 16{
@@ -320,6 +320,6 @@ printf(const char *fmt, ...)
320 va_start(args, fmt); 320 va_start(args, fmt);
321 n = vsprintf(sprint_buf, fmt, args); 321 n = vsprintf(sprint_buf, fmt, args);
322 va_end(args); 322 va_end(args);
323 write(stdout, sprint_buf, n); 323 console_ops.write(sprint_buf, n);
324 return n; 324 return n;
325} 325}
diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h
index eb9e16c87aef..73b8a91bfb34 100644
--- a/arch/powerpc/boot/stdio.h
+++ b/arch/powerpc/boot/stdio.h
@@ -1,8 +1,16 @@
1#ifndef _PPC_BOOT_STDIO_H_ 1#ifndef _PPC_BOOT_STDIO_H_
2#define _PPC_BOOT_STDIO_H_ 2#define _PPC_BOOT_STDIO_H_
3 3
4#include <stdarg.h>
5
6#define ENOMEM 12 /* Out of Memory */
7#define EINVAL 22 /* Invalid argument */
8#define ENOSPC 28 /* No space left on device */
9
4extern int printf(const char *fmt, ...); 10extern int printf(const char *fmt, ...);
5 11
12#define fprintf(fmt, args...) printf(args)
13
6extern int sprintf(char *buf, const char *fmt, ...); 14extern int sprintf(char *buf, const char *fmt, ...);
7 15
8extern int vsprintf(char *buf, const char *fmt, va_list args); 16extern int vsprintf(char *buf, const char *fmt, va_list args);
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h
new file mode 100644
index 000000000000..79d26e708677
--- /dev/null
+++ b/arch/powerpc/boot/types.h
@@ -0,0 +1,23 @@
1#ifndef _TYPES_H_
2#define _TYPES_H_
3
4#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
5
6typedef unsigned char u8;
7typedef unsigned short u16;
8typedef unsigned int u32;
9typedef unsigned long long u64;
10
11#define min(x,y) ({ \
12 typeof(x) _x = (x); \
13 typeof(y) _y = (y); \
14 (void) (&_x == &_y); \
15 _x < _y ? _x : _y; })
16
17#define max(x,y) ({ \
18 typeof(x) _x = (x); \
19 typeof(y) _y = (y); \
20 (void) (&_x == &_y); \
21 _x > _y ? _x : _y; })
22
23#endif /* _TYPES_H_ */