diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/boot/openfirmware |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/ppc/boot/openfirmware')
-rw-r--r-- | arch/ppc/boot/openfirmware/Makefile | 188 | ||||
-rw-r--r-- | arch/ppc/boot/openfirmware/chrpmain.c | 101 | ||||
-rw-r--r-- | arch/ppc/boot/openfirmware/coffmain.c | 101 | ||||
-rw-r--r-- | arch/ppc/boot/openfirmware/common.c | 162 | ||||
-rw-r--r-- | arch/ppc/boot/openfirmware/dummy.c | 4 | ||||
-rw-r--r-- | arch/ppc/boot/openfirmware/misc.S | 67 | ||||
-rw-r--r-- | arch/ppc/boot/openfirmware/newworldmain.c | 94 | ||||
-rw-r--r-- | arch/ppc/boot/openfirmware/start.c | 172 |
8 files changed, 889 insertions, 0 deletions
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile new file mode 100644 index 000000000000..4eacbd8c772a --- /dev/null +++ b/arch/ppc/boot/openfirmware/Makefile | |||
@@ -0,0 +1,188 @@ | |||
1 | # Makefile for making bootable images on various OpenFirmware machines. | ||
2 | # | ||
3 | # Paul Mackerras January 1997 | ||
4 | # XCOFF bootable images for PowerMacs | ||
5 | # Geert Uytterhoeven September 1997 | ||
6 | # ELF bootable iamges for CHRP machines. | ||
7 | # Tom Rini January 2001 | ||
8 | # Cleaned up, moved into arch/ppc/boot/pmac | ||
9 | # Tom Rini July/August 2002 | ||
10 | # Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the | ||
11 | # rules. | ||
12 | |||
13 | zImage.initrd znetboot.initrd: del-ramdisk-sec := -R .ramdisk | ||
14 | zImage.initrd znetboot.initrd: initrd := .initrd | ||
15 | |||
16 | |||
17 | boot := arch/ppc/boot | ||
18 | common := $(boot)/common | ||
19 | utils := $(boot)/utils | ||
20 | bootlib := $(boot)/lib | ||
21 | of1275 := $(boot)/of1275 | ||
22 | images := $(boot)/images | ||
23 | |||
24 | OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment | ||
25 | COFF_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00500000 \ | ||
26 | -Bstatic | ||
27 | CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000 | ||
28 | NEWWORLD_LD_ARGS:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x01000000 | ||
29 | |||
30 | COMMONOBJS := start.o misc.o common.o | ||
31 | COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o | ||
32 | CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o | ||
33 | NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o | ||
34 | |||
35 | targets := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) dummy.o | ||
36 | COFFOBJS := $(addprefix $(obj)/, $(COFFOBJS)) | ||
37 | CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS)) | ||
38 | NEWWORLDOBJS := $(addprefix $(obj)/, $(NEWWORLDOBJS)) | ||
39 | |||
40 | LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a | ||
41 | |||
42 | HACKCOFF := $(utils)/hack-coff | ||
43 | |||
44 | ifdef CONFIG_SMP | ||
45 | END := .smp | ||
46 | endif | ||
47 | ifdef CONFIG_PPC64BRIDGE | ||
48 | END += .64 | ||
49 | endif | ||
50 | |||
51 | |||
52 | $(images)/ramdisk.image.gz: | ||
53 | @echo ' MISSING $@' | ||
54 | @echo ' RAM disk image must be provided separately' | ||
55 | @/bin/false | ||
56 | |||
57 | objcpxmon-$(CONFIG_XMON) := --add-section=.sysmap=System.map \ | ||
58 | --set-section-flags=.sysmap=contents,alloc,load,readonly,data | ||
59 | quiet_cmd_genimage = GEN $@ | ||
60 | cmd_genimage = $(OBJCOPY) -R .comment \ | ||
61 | --add-section=.image=$(images)/vmlinux.gz \ | ||
62 | --set-section-flags=.image=contents,alloc,load,readonly,data \ | ||
63 | $(objcpxmon-y) $< $@ | ||
64 | |||
65 | targets += image.o | ||
66 | $(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE | ||
67 | $(call if_changed,genimage) | ||
68 | |||
69 | # Place the ramdisk in the initrd image. | ||
70 | quiet_cmd_genimage-initrd = GEN $@ | ||
71 | cmd_genimage-initrd = $(OBJCOPY) $< $@ \ | ||
72 | --add-section=.ramdisk=$(images)/ramdisk.image.gz \ | ||
73 | --set-section-flags=.ramdisk=contents,alloc,load,readonly,data | ||
74 | targets += image.initrd.o | ||
75 | $(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE | ||
76 | $(call if_changed,genimage-initrd) | ||
77 | |||
78 | # Create the note section for New-World PowerMacs. | ||
79 | quiet_cmd_mknote = MKNOTE $@ | ||
80 | cmd_mknote = $(utils)/mknote > $@ | ||
81 | targets += note | ||
82 | $(obj)/note: $(utils)/mknote FORCE | ||
83 | $(call if_changed,mknote) | ||
84 | |||
85 | |||
86 | $(obj)/coffcrt0.o: EXTRA_AFLAGS := -traditional -DXCOFF | ||
87 | $(obj)/crt0.o: EXTRA_AFLAGS := -traditional | ||
88 | targets += coffcrt0.o crt0.o | ||
89 | $(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE | ||
90 | $(call if_changed_dep,as_o_S) | ||
91 | |||
92 | quiet_cmd_gencoffb = COFF $@ | ||
93 | cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) $< $(LIBS) && \ | ||
94 | $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) | ||
95 | targets += coffboot | ||
96 | $(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(srctree)/$(boot)/ld.script FORCE | ||
97 | $(call if_changed,gencoffb) | ||
98 | targets += coffboot.initrd | ||
99 | $(obj)/coffboot.initrd: $(obj)/image.initrd.o $(COFFOBJS) $(LIBS) \ | ||
100 | $(srctree)/$(boot)/ld.script FORCE | ||
101 | $(call if_changed,gencoffb) | ||
102 | |||
103 | |||
104 | quiet_cmd_gen-coff = COFF $@ | ||
105 | cmd_gen-coff = $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ && \ | ||
106 | $(HACKCOFF) $@ && \ | ||
107 | ln -sf $(notdir $@) $(images)/zImage$(initrd).pmac | ||
108 | |||
109 | $(images)/vmlinux.coff: $(obj)/coffboot | ||
110 | $(call cmd,gen-coff) | ||
111 | |||
112 | $(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd | ||
113 | $(call cmd,gen-coff) | ||
114 | |||
115 | quiet_cmd_gen-elf-pmac = ELF $@ | ||
116 | cmd_gen-elf-pmac = $(LD) $(NEWWORLD_LD_ARGS) -o $@ \ | ||
117 | $(NEWWORLDOBJS) $(LIBS) $< && \ | ||
118 | $(OBJCOPY) $@ $@ --add-section=.note=$(obj)/note \ | ||
119 | -R .comment $(del-ramdisk-sec) | ||
120 | |||
121 | $(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) \ | ||
122 | $(obj)/note $(srctree)/$(boot)/ld.script | ||
123 | $(call cmd,gen-elf-pmac) | ||
124 | $(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \ | ||
125 | $(LIBS) $(obj)/note \ | ||
126 | $(srctree)/$(boot)/ld.script | ||
127 | $(call cmd,gen-elf-pmac) | ||
128 | |||
129 | quiet_cmd_gen-chrp = CHRP $@ | ||
130 | cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \ | ||
131 | $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) | ||
132 | |||
133 | $(images)/zImage.chrp: $(obj)/image.o $(CHRPOBJS) $(LIBS) \ | ||
134 | $(srctree)/$(boot)/ld.script | ||
135 | $(call cmd,gen-chrp) | ||
136 | $(images)/zImage.initrd.chrp: $(obj)/image.initrd.o $(CHRPOBJS) $(LIBS) \ | ||
137 | $(srctree)/$(boot)/ld.script | ||
138 | $(call cmd,gen-chrp) | ||
139 | |||
140 | quiet_cmd_addnote = ADDNOTE $@ | ||
141 | cmd_addnote = cat $< > $@ && $(utils)/addnote $@ | ||
142 | $(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \ | ||
143 | %-rs6k: % | ||
144 | $(call cmd,addnote) | ||
145 | |||
146 | quiet_cmd_gen-miboot = GEN $@ | ||
147 | cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_ARGS) \ | ||
148 | --add-section=$1=$(word 2, $^) $< $@ | ||
149 | $(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz | ||
150 | $(call cmd,gen-miboot,image) | ||
151 | |||
152 | $(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz | ||
153 | $(call cmd,gen-miboot,initrd) | ||
154 | |||
155 | # The targets used on the make command-line | ||
156 | |||
157 | .PHONY: zImage zImage.initrd | ||
158 | zImage: $(images)/vmlinux.coff \ | ||
159 | $(images)/vmlinux.elf-pmac \ | ||
160 | $(images)/zImage.chrp \ | ||
161 | $(images)/zImage.chrp-rs6k \ | ||
162 | $(images)/miboot.image | ||
163 | @echo ' kernel: $@ is ready ($<)' | ||
164 | zImage.initrd: $(images)/vmlinux.initrd.coff \ | ||
165 | $(images)/vmlinux.initrd.elf-pmac \ | ||
166 | $(images)/zImage.initrd.chrp \ | ||
167 | $(images)/zImage.initrd.chrp-rs6k \ | ||
168 | $(images)/miboot.initrd.image | ||
169 | @echo ' kernel: $@ is ready ($<)' | ||
170 | |||
171 | TFTPIMAGE := /tftpboot/zImage | ||
172 | |||
173 | .PHONY: znetboot znetboot.initrd | ||
174 | znetboot: $(images)/vmlinux.coff \ | ||
175 | $(images)/vmlinux.elf-pmac \ | ||
176 | $(images)/zImage.chrp | ||
177 | cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END) | ||
178 | cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END).elf | ||
179 | cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END) | ||
180 | @echo ' kernel: $@ is ready ($<)' | ||
181 | znetboot.initrd:$(images)/vmlinux.initrd.coff \ | ||
182 | $(images)/vmlinux.initrd.elf-pmac \ | ||
183 | $(images)/zImage.initrd.chrp | ||
184 | cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END) | ||
185 | cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf | ||
186 | cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END) | ||
187 | @echo ' kernel: $@ is ready ($<)' | ||
188 | |||
diff --git a/arch/ppc/boot/openfirmware/chrpmain.c b/arch/ppc/boot/openfirmware/chrpmain.c new file mode 100644 index 000000000000..6fb4f738728c --- /dev/null +++ b/arch/ppc/boot/openfirmware/chrpmain.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
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. | ||
8 | */ | ||
9 | #include <linux/string.h> | ||
10 | #include "nonstdio.h" | ||
11 | #include "of1275.h" | ||
12 | #include <asm/processor.h> | ||
13 | #include <asm/page.h> | ||
14 | |||
15 | /* Passed from the linker */ | ||
16 | extern char __image_begin, __image_end; | ||
17 | extern char __ramdisk_begin, __ramdisk_end; | ||
18 | extern char _start, _end; | ||
19 | |||
20 | extern unsigned int heap_max; | ||
21 | extern void flush_cache(void *, unsigned long); | ||
22 | extern void gunzip(void *, int, unsigned char *, int *); | ||
23 | extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, | ||
24 | unsigned int progend); | ||
25 | |||
26 | char *avail_ram; | ||
27 | char *begin_avail, *end_avail; | ||
28 | char *avail_high; | ||
29 | |||
30 | #define RAM_START 0x00000000 | ||
31 | #define RAM_END (64<<20) | ||
32 | |||
33 | #define BOOT_START ((unsigned long)_start) | ||
34 | #define BOOT_END ((unsigned long)(_end + 0xFFF) & ~0xFFF) | ||
35 | |||
36 | #define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF) | ||
37 | #define PROG_START 0x00010000 | ||
38 | #define PROG_SIZE 0x007f0000 /* 8MB */ | ||
39 | |||
40 | #define SCRATCH_SIZE (128 << 10) | ||
41 | |||
42 | static char scratch[SCRATCH_SIZE]; /* 1MB of scratch space for gunzip */ | ||
43 | |||
44 | typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int); | ||
45 | |||
46 | void | ||
47 | boot(int a1, int a2, void *prom) | ||
48 | { | ||
49 | unsigned sa, len; | ||
50 | void *dst; | ||
51 | unsigned char *im; | ||
52 | unsigned int initrd_size, initrd_start; | ||
53 | |||
54 | printf("chrpboot starting: loaded at 0x%p\n\r", &_start); | ||
55 | |||
56 | initrd_size = &__ramdisk_end - &__ramdisk_begin; | ||
57 | if (initrd_size) { | ||
58 | initrd_start = (RAM_END - initrd_size) & ~0xFFF; | ||
59 | a1 = initrd_start; | ||
60 | a2 = initrd_size; | ||
61 | claim(initrd_start, RAM_END - initrd_start, 0); | ||
62 | printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", | ||
63 | initrd_start, &__ramdisk_begin, initrd_size); | ||
64 | memcpy((char *)initrd_start, &__ramdisk_begin, initrd_size); | ||
65 | } else { | ||
66 | initrd_start = 0; | ||
67 | initrd_size = 0; | ||
68 | a2 = 0xdeadbeef; | ||
69 | } | ||
70 | |||
71 | im = &__image_begin; | ||
72 | len = &__image_end - &__image_begin; | ||
73 | /* claim 4MB starting at PROG_START */ | ||
74 | claim(PROG_START, PROG_SIZE - PROG_START, 0); | ||
75 | dst = (void *) PROG_START; | ||
76 | if (im[0] == 0x1f && im[1] == 0x8b) { | ||
77 | avail_ram = scratch; | ||
78 | begin_avail = avail_high = avail_ram; | ||
79 | end_avail = scratch + sizeof(scratch); | ||
80 | printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); | ||
81 | gunzip(dst, 0x400000, im, &len); | ||
82 | printf("done %u bytes\n\r", len); | ||
83 | printf("%u bytes of heap consumed, max in use %u\n\r", | ||
84 | avail_high - begin_avail, heap_max); | ||
85 | } else { | ||
86 | memmove(dst, im, len); | ||
87 | } | ||
88 | |||
89 | flush_cache(dst, len); | ||
90 | make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp, | ||
91 | (PROG_START + PROG_SIZE)); | ||
92 | |||
93 | sa = PROG_START; | ||
94 | printf("start address = 0x%x\n\r", sa); | ||
95 | |||
96 | (*(kernel_start_t)sa)(a1, a2, prom, initrd_start, initrd_size); | ||
97 | |||
98 | printf("returned?\n\r"); | ||
99 | |||
100 | pause(); | ||
101 | } | ||
diff --git a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c new file mode 100644 index 000000000000..04ba9d57e110 --- /dev/null +++ b/arch/ppc/boot/openfirmware/coffmain.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
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. | ||
8 | */ | ||
9 | #include <linux/string.h> | ||
10 | #include <asm/processor.h> | ||
11 | #include <asm/page.h> | ||
12 | |||
13 | #include "nonstdio.h" | ||
14 | #include "of1275.h" | ||
15 | |||
16 | /* Passed from the linker */ | ||
17 | extern char __image_begin, __image_end; | ||
18 | extern char __ramdisk_begin[], __ramdisk_end; | ||
19 | extern char _start, _end; | ||
20 | |||
21 | extern char image_data[], initrd_data[]; | ||
22 | extern int initrd_len, image_len; | ||
23 | extern unsigned int heap_max; | ||
24 | extern void flush_cache(void *start, unsigned int len); | ||
25 | extern void gunzip(void *, int, unsigned char *, int *); | ||
26 | extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, | ||
27 | unsigned int progend); | ||
28 | extern void setup_bats(unsigned long start); | ||
29 | |||
30 | char *avail_ram; | ||
31 | char *begin_avail, *end_avail; | ||
32 | char *avail_high; | ||
33 | |||
34 | #define SCRATCH_SIZE (128 << 10) | ||
35 | |||
36 | static char heap[SCRATCH_SIZE]; | ||
37 | |||
38 | static unsigned long ram_start = 0; | ||
39 | static unsigned long ram_end = 0x1000000; | ||
40 | |||
41 | static unsigned long prog_start = 0x900000; | ||
42 | static unsigned long prog_size = 0x700000; | ||
43 | |||
44 | typedef void (*kernel_start_t)(int, int, void *); | ||
45 | |||
46 | void boot(int a1, int a2, void *prom) | ||
47 | { | ||
48 | unsigned sa, len; | ||
49 | void *dst; | ||
50 | unsigned char *im; | ||
51 | unsigned initrd_start, initrd_size; | ||
52 | |||
53 | printf("coffboot starting: loaded at 0x%p\n", &_start); | ||
54 | setup_bats(ram_start); | ||
55 | |||
56 | initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin); | ||
57 | if (initrd_size) { | ||
58 | initrd_start = (ram_end - initrd_size) & ~0xFFF; | ||
59 | a1 = initrd_start; | ||
60 | a2 = initrd_size; | ||
61 | claim(initrd_start, ram_end - initrd_start, 0); | ||
62 | printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", | ||
63 | initrd_start, (char *)(&__ramdisk_begin), initrd_size); | ||
64 | memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size); | ||
65 | prog_size = initrd_start - prog_start; | ||
66 | } else | ||
67 | a2 = 0xdeadbeef; | ||
68 | |||
69 | im = (char *)(&__image_begin); | ||
70 | len = (char *)(&__image_end) - (char *)(&__image_begin); | ||
71 | /* claim 4MB starting at PROG_START */ | ||
72 | claim(prog_start, prog_size, 0); | ||
73 | map(prog_start, prog_start, prog_size); | ||
74 | dst = (void *) prog_start; | ||
75 | if (im[0] == 0x1f && im[1] == 0x8b) { | ||
76 | /* set up scratch space */ | ||
77 | begin_avail = avail_high = avail_ram = heap; | ||
78 | end_avail = heap + sizeof(heap); | ||
79 | printf("heap at 0x%p\n", avail_ram); | ||
80 | printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); | ||
81 | gunzip(dst, prog_size, im, &len); | ||
82 | printf("done %u bytes\n", len); | ||
83 | printf("%u bytes of heap consumed, max in use %u\n", | ||
84 | avail_high - begin_avail, heap_max); | ||
85 | } else { | ||
86 | memmove(dst, im, len); | ||
87 | } | ||
88 | |||
89 | flush_cache(dst, len); | ||
90 | make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac, | ||
91 | (prog_start + prog_size)); | ||
92 | |||
93 | sa = (unsigned long)prog_start; | ||
94 | printf("start address = 0x%x\n", sa); | ||
95 | |||
96 | (*(kernel_start_t)sa)(a1, a2, prom); | ||
97 | |||
98 | printf("returned?\n"); | ||
99 | |||
100 | pause(); | ||
101 | } | ||
diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c new file mode 100644 index 000000000000..9e6952781f1f --- /dev/null +++ b/arch/ppc/boot/openfirmware/common.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
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. | ||
8 | */ | ||
9 | |||
10 | #include "nonstdio.h" | ||
11 | #include "of1275.h" | ||
12 | #include <linux/string.h> | ||
13 | #include <linux/zlib.h> | ||
14 | #include <asm/bootinfo.h> | ||
15 | #include <asm/page.h> | ||
16 | |||
17 | /* Information from the linker */ | ||
18 | extern char __sysmap_begin, __sysmap_end; | ||
19 | |||
20 | extern int strcmp(const char *s1, const char *s2); | ||
21 | extern char *avail_ram, *avail_high; | ||
22 | extern char *end_avail; | ||
23 | |||
24 | unsigned int heap_use, heap_max; | ||
25 | |||
26 | struct memchunk { | ||
27 | unsigned int size; | ||
28 | struct memchunk *next; | ||
29 | }; | ||
30 | |||
31 | static struct memchunk *freechunks; | ||
32 | |||
33 | static void *zalloc(unsigned size) | ||
34 | { | ||
35 | void *p; | ||
36 | struct memchunk **mpp, *mp; | ||
37 | |||
38 | size = (size + 7) & -8; | ||
39 | heap_use += size; | ||
40 | if (heap_use > heap_max) | ||
41 | heap_max = heap_use; | ||
42 | for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { | ||
43 | if (mp->size == size) { | ||
44 | *mpp = mp->next; | ||
45 | return mp; | ||
46 | } | ||
47 | } | ||
48 | p = avail_ram; | ||
49 | avail_ram += size; | ||
50 | if (avail_ram > avail_high) | ||
51 | avail_high = avail_ram; | ||
52 | if (avail_ram > end_avail) { | ||
53 | printf("oops... out of memory\n\r"); | ||
54 | pause(); | ||
55 | } | ||
56 | return p; | ||
57 | } | ||
58 | |||
59 | #define HEAD_CRC 2 | ||
60 | #define EXTRA_FIELD 4 | ||
61 | #define ORIG_NAME 8 | ||
62 | #define COMMENT 0x10 | ||
63 | #define RESERVED 0xe0 | ||
64 | |||
65 | void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) | ||
66 | { | ||
67 | z_stream s; | ||
68 | int r, i, flags; | ||
69 | |||
70 | /* skip header */ | ||
71 | i = 10; | ||
72 | flags = src[3]; | ||
73 | if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { | ||
74 | printf("bad gzipped data\n\r"); | ||
75 | exit(); | ||
76 | } | ||
77 | if ((flags & EXTRA_FIELD) != 0) | ||
78 | i = 12 + src[10] + (src[11] << 8); | ||
79 | if ((flags & ORIG_NAME) != 0) | ||
80 | while (src[i++] != 0) | ||
81 | ; | ||
82 | if ((flags & COMMENT) != 0) | ||
83 | while (src[i++] != 0) | ||
84 | ; | ||
85 | if ((flags & HEAD_CRC) != 0) | ||
86 | i += 2; | ||
87 | if (i >= *lenp) { | ||
88 | printf("gunzip: ran out of data in header\n\r"); | ||
89 | exit(); | ||
90 | } | ||
91 | |||
92 | /* Initialize ourself. */ | ||
93 | s.workspace = zalloc(zlib_inflate_workspacesize()); | ||
94 | r = zlib_inflateInit2(&s, -MAX_WBITS); | ||
95 | if (r != Z_OK) { | ||
96 | printf("zlib_inflateInit2 returned %d\n\r", r); | ||
97 | exit(); | ||
98 | } | ||
99 | s.next_in = src + i; | ||
100 | s.avail_in = *lenp - i; | ||
101 | s.next_out = dst; | ||
102 | s.avail_out = dstlen; | ||
103 | r = zlib_inflate(&s, Z_FINISH); | ||
104 | if (r != Z_OK && r != Z_STREAM_END) { | ||
105 | printf("inflate returned %d msg: %s\n\r", r, s.msg); | ||
106 | exit(); | ||
107 | } | ||
108 | *lenp = s.next_out - (unsigned char *) dst; | ||
109 | zlib_inflateEnd(&s); | ||
110 | } | ||
111 | |||
112 | /* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID, | ||
113 | * a machine type for BI_MACHTYPE, and the location where the end of the | ||
114 | * bootloader is (PROG_START + PROG_SIZE) | ||
115 | */ | ||
116 | void make_bi_recs(unsigned long addr, char *name, unsigned int mach, | ||
117 | unsigned long progend) | ||
118 | { | ||
119 | unsigned long sysmap_size; | ||
120 | struct bi_record *rec; | ||
121 | |||
122 | /* Figure out the size of a possible System.map we're going to | ||
123 | * pass along. | ||
124 | * */ | ||
125 | sysmap_size = (unsigned long)(&__sysmap_end) - | ||
126 | (unsigned long)(&__sysmap_begin); | ||
127 | |||
128 | /* leave a 1MB gap then align to the next 1MB boundary */ | ||
129 | addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); | ||
130 | /* oldworld machine seem very unhappy about this. -- Tom */ | ||
131 | if (addr >= progend) | ||
132 | claim(addr, 0x1000, 0); | ||
133 | |||
134 | rec = (struct bi_record *)addr; | ||
135 | rec->tag = BI_FIRST; | ||
136 | rec->size = sizeof(struct bi_record); | ||
137 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | ||
138 | |||
139 | rec->tag = BI_BOOTLOADER_ID; | ||
140 | sprintf( (char *)rec->data, name); | ||
141 | rec->size = sizeof(struct bi_record) + strlen(name) + 1; | ||
142 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | ||
143 | |||
144 | rec->tag = BI_MACHTYPE; | ||
145 | rec->data[0] = mach; | ||
146 | rec->data[1] = 1; | ||
147 | rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); | ||
148 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | ||
149 | |||
150 | if (sysmap_size) { | ||
151 | rec->tag = BI_SYSMAP; | ||
152 | rec->data[0] = (unsigned long)(&__sysmap_begin); | ||
153 | rec->data[1] = sysmap_size; | ||
154 | rec->size = sizeof(struct bi_record) + 2 * | ||
155 | sizeof(unsigned long); | ||
156 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | ||
157 | } | ||
158 | |||
159 | rec->tag = BI_LAST; | ||
160 | rec->size = sizeof(struct bi_record); | ||
161 | rec = (struct bi_record *)((unsigned long)rec + rec->size); | ||
162 | } | ||
diff --git a/arch/ppc/boot/openfirmware/dummy.c b/arch/ppc/boot/openfirmware/dummy.c new file mode 100644 index 000000000000..31dbf45bf99c --- /dev/null +++ b/arch/ppc/boot/openfirmware/dummy.c | |||
@@ -0,0 +1,4 @@ | |||
1 | int main(void) | ||
2 | { | ||
3 | return 0; | ||
4 | } | ||
diff --git a/arch/ppc/boot/openfirmware/misc.S b/arch/ppc/boot/openfirmware/misc.S new file mode 100644 index 000000000000..ab9e897cadd0 --- /dev/null +++ b/arch/ppc/boot/openfirmware/misc.S | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
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. | ||
8 | */ | ||
9 | .text | ||
10 | |||
11 | /* | ||
12 | * Use the BAT2 & 3 registers to map the 1st 16MB of RAM to | ||
13 | * the address given as the 1st argument. | ||
14 | */ | ||
15 | .globl setup_bats | ||
16 | setup_bats: | ||
17 | mfpvr 5 | ||
18 | rlwinm 5,5,16,16,31 /* r3 = 1 for 601, 4 for 604 */ | ||
19 | cmpwi 0,5,1 | ||
20 | li 0,0 | ||
21 | bne 4f | ||
22 | mtibatl 3,0 /* invalidate BAT first */ | ||
23 | ori 3,3,4 /* set up BAT registers for 601 */ | ||
24 | li 4,0x7f | ||
25 | mtibatu 2,3 | ||
26 | mtibatl 2,4 | ||
27 | oris 3,3,0x80 | ||
28 | oris 4,4,0x80 | ||
29 | mtibatu 3,3 | ||
30 | mtibatl 3,4 | ||
31 | b 5f | ||
32 | 4: mtdbatu 3,0 /* invalidate BATs first */ | ||
33 | mtibatu 3,0 | ||
34 | ori 3,3,0xff /* set up BAT registers for 604 */ | ||
35 | li 4,2 | ||
36 | mtdbatl 2,4 | ||
37 | mtdbatu 2,3 | ||
38 | mtibatl 2,4 | ||
39 | mtibatu 2,3 | ||
40 | oris 3,3,0x80 | ||
41 | oris 4,4,0x80 | ||
42 | mtdbatl 3,4 | ||
43 | mtdbatu 3,3 | ||
44 | mtibatl 3,4 | ||
45 | mtibatu 3,3 | ||
46 | 5: sync | ||
47 | isync | ||
48 | blr | ||
49 | |||
50 | /* | ||
51 | * Flush the dcache and invalidate the icache for a range of addresses. | ||
52 | * | ||
53 | * flush_cache(addr, len) | ||
54 | */ | ||
55 | .global flush_cache | ||
56 | flush_cache: | ||
57 | addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */ | ||
58 | rlwinm. 4,4,27,5,31 | ||
59 | mtctr 4 | ||
60 | beqlr | ||
61 | 1: dcbf 0,3 | ||
62 | icbi 0,3 | ||
63 | addi 3,3,0x20 | ||
64 | bdnz 1b | ||
65 | sync | ||
66 | isync | ||
67 | blr | ||
diff --git a/arch/ppc/boot/openfirmware/newworldmain.c b/arch/ppc/boot/openfirmware/newworldmain.c new file mode 100644 index 000000000000..fa8a8f9313f9 --- /dev/null +++ b/arch/ppc/boot/openfirmware/newworldmain.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
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. | ||
8 | */ | ||
9 | #include <linux/string.h> | ||
10 | #include "nonstdio.h" | ||
11 | #include "of1275.h" | ||
12 | #include <asm/processor.h> | ||
13 | #include <asm/page.h> | ||
14 | |||
15 | /* Passed from the linker */ | ||
16 | extern char __image_begin, __image_end; | ||
17 | extern char __ramdisk_begin[], __ramdisk_end; | ||
18 | extern char _start, _end; | ||
19 | |||
20 | extern unsigned int heap_max; | ||
21 | extern void flush_cache(void *start, unsigned int len); | ||
22 | extern void gunzip(void *, int, unsigned char *, int *); | ||
23 | extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, | ||
24 | unsigned int progend); | ||
25 | |||
26 | char *avail_ram; | ||
27 | char *begin_avail, *end_avail; | ||
28 | char *avail_high; | ||
29 | |||
30 | |||
31 | #define RAM_END (16 << 20) | ||
32 | |||
33 | #define PROG_START 0x00010000 | ||
34 | #define PROG_SIZE 0x007f0000 | ||
35 | |||
36 | #define SCRATCH_SIZE (128 << 10) | ||
37 | |||
38 | typedef void (*kernel_start_t)(int, int, void *); | ||
39 | |||
40 | void boot(int a1, int a2, void *prom) | ||
41 | { | ||
42 | unsigned sa, len; | ||
43 | void *dst; | ||
44 | unsigned char *im; | ||
45 | unsigned initrd_start, initrd_size; | ||
46 | |||
47 | printf("chrpboot starting: loaded at 0x%p\n", &_start); | ||
48 | |||
49 | initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin); | ||
50 | if (initrd_size) { | ||
51 | initrd_start = (RAM_END - initrd_size) & ~0xFFF; | ||
52 | a1 = initrd_start; | ||
53 | a2 = initrd_size; | ||
54 | claim(initrd_start, RAM_END - initrd_start, 0); | ||
55 | printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", | ||
56 | initrd_start, (char *)(&__ramdisk_begin), initrd_size); | ||
57 | memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size); | ||
58 | } else | ||
59 | a2 = 0xdeadbeef; | ||
60 | |||
61 | im = (char *)(&__image_begin); | ||
62 | len = (char *)(&__image_end) - (char *)(&__image_begin); | ||
63 | /* claim 3MB starting at PROG_START */ | ||
64 | claim(PROG_START, PROG_SIZE, 0); | ||
65 | dst = (void *) PROG_START; | ||
66 | if (im[0] == 0x1f && im[1] == 0x8b) { | ||
67 | /* claim some memory for scratch space */ | ||
68 | avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10); | ||
69 | begin_avail = avail_high = avail_ram; | ||
70 | end_avail = avail_ram + SCRATCH_SIZE; | ||
71 | printf("heap at 0x%p\n", avail_ram); | ||
72 | printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); | ||
73 | gunzip(dst, PROG_SIZE, im, &len); | ||
74 | printf("done %u bytes\n", len); | ||
75 | printf("%u bytes of heap consumed, max in use %u\n", | ||
76 | avail_high - begin_avail, heap_max); | ||
77 | release(begin_avail, SCRATCH_SIZE); | ||
78 | } else { | ||
79 | memmove(dst, im, len); | ||
80 | } | ||
81 | |||
82 | flush_cache(dst, len); | ||
83 | make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac, | ||
84 | (PROG_START + PROG_SIZE)); | ||
85 | |||
86 | sa = (unsigned long)PROG_START; | ||
87 | printf("start address = 0x%x\n", sa); | ||
88 | |||
89 | (*(kernel_start_t)sa)(a1, a2, prom); | ||
90 | |||
91 | printf("returned?\n"); | ||
92 | |||
93 | pause(); | ||
94 | } | ||
diff --git a/arch/ppc/boot/openfirmware/start.c b/arch/ppc/boot/openfirmware/start.c new file mode 100644 index 000000000000..1617a26956bf --- /dev/null +++ b/arch/ppc/boot/openfirmware/start.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
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. | ||
8 | */ | ||
9 | #include <stdarg.h> | ||
10 | #include "of1275.h" | ||
11 | |||
12 | extern int strlen(const char *s); | ||
13 | extern void boot(int a1, int a2, void *prom); | ||
14 | |||
15 | phandle stdin; | ||
16 | phandle stdout; | ||
17 | phandle stderr; | ||
18 | |||
19 | void printk(char *fmt, ...); | ||
20 | |||
21 | void | ||
22 | start(int a1, int a2, void *promptr) | ||
23 | { | ||
24 | ofinit(promptr); | ||
25 | if (ofstdio(&stdin, &stdout, &stderr)) | ||
26 | exit(); | ||
27 | |||
28 | boot(a1, a2, promptr); | ||
29 | for (;;) | ||
30 | exit(); | ||
31 | } | ||
32 | |||
33 | int writestring(void *f, char *ptr, int nb) | ||
34 | { | ||
35 | int w = 0, i; | ||
36 | char *ret = "\r"; | ||
37 | |||
38 | for (i = 0; i < nb; ++i) { | ||
39 | if (ptr[i] == '\n') { | ||
40 | if (i > w) { | ||
41 | write(f, ptr + w, i - w); | ||
42 | w = i; | ||
43 | } | ||
44 | write(f, ret, 1); | ||
45 | } | ||
46 | } | ||
47 | if (w < nb) | ||
48 | write(f, ptr + w, nb - w); | ||
49 | return nb; | ||
50 | } | ||
51 | |||
52 | int | ||
53 | putc(int c, void *f) | ||
54 | { | ||
55 | char ch = c; | ||
56 | |||
57 | return writestring(f, &ch, 1) == 1? c: -1; | ||
58 | } | ||
59 | |||
60 | int | ||
61 | putchar(int c) | ||
62 | { | ||
63 | return putc(c, stdout); | ||
64 | } | ||
65 | |||
66 | int | ||
67 | fputs(char *str, void *f) | ||
68 | { | ||
69 | int n = strlen(str); | ||
70 | |||
71 | return writestring(f, str, n) == n? 0: -1; | ||
72 | } | ||
73 | |||
74 | int | ||
75 | readchar(void) | ||
76 | { | ||
77 | char ch; | ||
78 | |||
79 | for (;;) { | ||
80 | switch (read(stdin, &ch, 1)) { | ||
81 | case 1: | ||
82 | return ch; | ||
83 | case -1: | ||
84 | printk("read(stdin) returned -1\n"); | ||
85 | return -1; | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static char line[256]; | ||
91 | static char *lineptr; | ||
92 | static int lineleft; | ||
93 | |||
94 | int | ||
95 | getchar(void) | ||
96 | { | ||
97 | int c; | ||
98 | |||
99 | if (lineleft == 0) { | ||
100 | lineptr = line; | ||
101 | for (;;) { | ||
102 | c = readchar(); | ||
103 | if (c == -1 || c == 4) | ||
104 | break; | ||
105 | if (c == '\r' || c == '\n') { | ||
106 | *lineptr++ = '\n'; | ||
107 | putchar('\n'); | ||
108 | break; | ||
109 | } | ||
110 | switch (c) { | ||
111 | case 0177: | ||
112 | case '\b': | ||
113 | if (lineptr > line) { | ||
114 | putchar('\b'); | ||
115 | putchar(' '); | ||
116 | putchar('\b'); | ||
117 | --lineptr; | ||
118 | } | ||
119 | break; | ||
120 | case 'U' & 0x1F: | ||
121 | while (lineptr > line) { | ||
122 | putchar('\b'); | ||
123 | putchar(' '); | ||
124 | putchar('\b'); | ||
125 | --lineptr; | ||
126 | } | ||
127 | break; | ||
128 | default: | ||
129 | if (lineptr >= &line[sizeof(line) - 1]) | ||
130 | putchar('\a'); | ||
131 | else { | ||
132 | putchar(c); | ||
133 | *lineptr++ = c; | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | lineleft = lineptr - line; | ||
138 | lineptr = line; | ||
139 | } | ||
140 | if (lineleft == 0) | ||
141 | return -1; | ||
142 | --lineleft; | ||
143 | return *lineptr++; | ||
144 | } | ||
145 | |||
146 | extern int vsprintf(char *buf, const char *fmt, va_list args); | ||
147 | static char sprint_buf[1024]; | ||
148 | |||
149 | void | ||
150 | printk(char *fmt, ...) | ||
151 | { | ||
152 | va_list args; | ||
153 | int n; | ||
154 | |||
155 | va_start(args, fmt); | ||
156 | n = vsprintf(sprint_buf, fmt, args); | ||
157 | va_end(args); | ||
158 | writestring(stdout, sprint_buf, n); | ||
159 | } | ||
160 | |||
161 | int | ||
162 | printf(char *fmt, ...) | ||
163 | { | ||
164 | va_list args; | ||
165 | int n; | ||
166 | |||
167 | va_start(args, fmt); | ||
168 | n = vsprintf(sprint_buf, fmt, args); | ||
169 | va_end(args); | ||
170 | writestring(stdout, sprint_buf, n); | ||
171 | return n; | ||
172 | } | ||