summaryrefslogtreecommitdiff
path: root/arch/ppc/boot/openfirmware
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/boot/openfirmware')
-rw-r--r--arch/ppc/boot/openfirmware/Makefile188
-rw-r--r--arch/ppc/boot/openfirmware/chrpmain.c101
-rw-r--r--arch/ppc/boot/openfirmware/coffmain.c101
-rw-r--r--arch/ppc/boot/openfirmware/common.c162
-rw-r--r--arch/ppc/boot/openfirmware/dummy.c4
-rw-r--r--arch/ppc/boot/openfirmware/misc.S67
-rw-r--r--arch/ppc/boot/openfirmware/newworldmain.c94
-rw-r--r--arch/ppc/boot/openfirmware/start.c172
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 @@
+# Makefile for making bootable images on various OpenFirmware machines.
+#
+# Paul Mackerras January 1997
+# XCOFF bootable images for PowerMacs
+# Geert Uytterhoeven September 1997
+# ELF bootable iamges for CHRP machines.
+# Tom Rini January 2001
+# Cleaned up, moved into arch/ppc/boot/pmac
+# Tom Rini July/August 2002
+# Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the
+# rules.
+
+zImage.initrd znetboot.initrd: del-ramdisk-sec := -R .ramdisk
+zImage.initrd znetboot.initrd: initrd := .initrd
+
+
+boot := arch/ppc/boot
+common := $(boot)/common
+utils := $(boot)/utils
+bootlib := $(boot)/lib
+of1275 := $(boot)/of1275
+images := $(boot)/images
+
+OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
+COFF_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00500000 \
+ -Bstatic
+CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000
+NEWWORLD_LD_ARGS:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x01000000
+
+COMMONOBJS := start.o misc.o common.o
+COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o
+CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o
+NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o
+
+targets := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) dummy.o
+COFFOBJS := $(addprefix $(obj)/, $(COFFOBJS))
+CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS))
+NEWWORLDOBJS := $(addprefix $(obj)/, $(NEWWORLDOBJS))
+
+LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a
+
+HACKCOFF := $(utils)/hack-coff
+
+ifdef CONFIG_SMP
+END := .smp
+endif
+ifdef CONFIG_PPC64BRIDGE
+END += .64
+endif
+
+
+$(images)/ramdisk.image.gz:
+ @echo ' MISSING $@'
+ @echo ' RAM disk image must be provided separately'
+ @/bin/false
+
+objcpxmon-$(CONFIG_XMON) := --add-section=.sysmap=System.map \
+ --set-section-flags=.sysmap=contents,alloc,load,readonly,data
+quiet_cmd_genimage = GEN $@
+ cmd_genimage = $(OBJCOPY) -R .comment \
+ --add-section=.image=$(images)/vmlinux.gz \
+ --set-section-flags=.image=contents,alloc,load,readonly,data \
+ $(objcpxmon-y) $< $@
+
+targets += image.o
+$(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE
+ $(call if_changed,genimage)
+
+# Place the ramdisk in the initrd image.
+quiet_cmd_genimage-initrd = GEN $@
+ cmd_genimage-initrd = $(OBJCOPY) $< $@ \
+ --add-section=.ramdisk=$(images)/ramdisk.image.gz \
+ --set-section-flags=.ramdisk=contents,alloc,load,readonly,data
+targets += image.initrd.o
+$(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE
+ $(call if_changed,genimage-initrd)
+
+# Create the note section for New-World PowerMacs.
+quiet_cmd_mknote = MKNOTE $@
+ cmd_mknote = $(utils)/mknote > $@
+targets += note
+$(obj)/note: $(utils)/mknote FORCE
+ $(call if_changed,mknote)
+
+
+$(obj)/coffcrt0.o: EXTRA_AFLAGS := -traditional -DXCOFF
+$(obj)/crt0.o: EXTRA_AFLAGS := -traditional
+targets += coffcrt0.o crt0.o
+$(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE
+ $(call if_changed_dep,as_o_S)
+
+quiet_cmd_gencoffb = COFF $@
+ cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) $< $(LIBS) && \
+ $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
+targets += coffboot
+$(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(srctree)/$(boot)/ld.script FORCE
+ $(call if_changed,gencoffb)
+targets += coffboot.initrd
+$(obj)/coffboot.initrd: $(obj)/image.initrd.o $(COFFOBJS) $(LIBS) \
+ $(srctree)/$(boot)/ld.script FORCE
+ $(call if_changed,gencoffb)
+
+
+quiet_cmd_gen-coff = COFF $@
+ cmd_gen-coff = $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ && \
+ $(HACKCOFF) $@ && \
+ ln -sf $(notdir $@) $(images)/zImage$(initrd).pmac
+
+$(images)/vmlinux.coff: $(obj)/coffboot
+ $(call cmd,gen-coff)
+
+$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd
+ $(call cmd,gen-coff)
+
+quiet_cmd_gen-elf-pmac = ELF $@
+ cmd_gen-elf-pmac = $(LD) $(NEWWORLD_LD_ARGS) -o $@ \
+ $(NEWWORLDOBJS) $(LIBS) $< && \
+ $(OBJCOPY) $@ $@ --add-section=.note=$(obj)/note \
+ -R .comment $(del-ramdisk-sec)
+
+$(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) \
+ $(obj)/note $(srctree)/$(boot)/ld.script
+ $(call cmd,gen-elf-pmac)
+$(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \
+ $(LIBS) $(obj)/note \
+ $(srctree)/$(boot)/ld.script
+ $(call cmd,gen-elf-pmac)
+
+quiet_cmd_gen-chrp = CHRP $@
+ cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \
+ $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
+
+$(images)/zImage.chrp: $(obj)/image.o $(CHRPOBJS) $(LIBS) \
+ $(srctree)/$(boot)/ld.script
+ $(call cmd,gen-chrp)
+$(images)/zImage.initrd.chrp: $(obj)/image.initrd.o $(CHRPOBJS) $(LIBS) \
+ $(srctree)/$(boot)/ld.script
+ $(call cmd,gen-chrp)
+
+quiet_cmd_addnote = ADDNOTE $@
+ cmd_addnote = cat $< > $@ && $(utils)/addnote $@
+$(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \
+ %-rs6k: %
+ $(call cmd,addnote)
+
+quiet_cmd_gen-miboot = GEN $@
+ cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_ARGS) \
+ --add-section=$1=$(word 2, $^) $< $@
+$(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz
+ $(call cmd,gen-miboot,image)
+
+$(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz
+ $(call cmd,gen-miboot,initrd)
+
+# The targets used on the make command-line
+
+.PHONY: zImage zImage.initrd
+zImage: $(images)/vmlinux.coff \
+ $(images)/vmlinux.elf-pmac \
+ $(images)/zImage.chrp \
+ $(images)/zImage.chrp-rs6k \
+ $(images)/miboot.image
+ @echo ' kernel: $@ is ready ($<)'
+zImage.initrd: $(images)/vmlinux.initrd.coff \
+ $(images)/vmlinux.initrd.elf-pmac \
+ $(images)/zImage.initrd.chrp \
+ $(images)/zImage.initrd.chrp-rs6k \
+ $(images)/miboot.initrd.image
+ @echo ' kernel: $@ is ready ($<)'
+
+TFTPIMAGE := /tftpboot/zImage
+
+.PHONY: znetboot znetboot.initrd
+znetboot: $(images)/vmlinux.coff \
+ $(images)/vmlinux.elf-pmac \
+ $(images)/zImage.chrp
+ cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END)
+ cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END).elf
+ cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END)
+ @echo ' kernel: $@ is ready ($<)'
+znetboot.initrd:$(images)/vmlinux.initrd.coff \
+ $(images)/vmlinux.initrd.elf-pmac \
+ $(images)/zImage.initrd.chrp
+ cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END)
+ cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf
+ cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
+ @echo ' kernel: $@ is ready ($<)'
+
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 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include "nonstdio.h"
+#include "of1275.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+
+/* Passed from the linker */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin, __ramdisk_end;
+extern char _start, _end;
+
+extern unsigned int heap_max;
+extern void flush_cache(void *, unsigned long);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
+ unsigned int progend);
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+
+#define RAM_START 0x00000000
+#define RAM_END (64<<20)
+
+#define BOOT_START ((unsigned long)_start)
+#define BOOT_END ((unsigned long)(_end + 0xFFF) & ~0xFFF)
+
+#define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF)
+#define PROG_START 0x00010000
+#define PROG_SIZE 0x007f0000 /* 8MB */
+
+#define SCRATCH_SIZE (128 << 10)
+
+static char scratch[SCRATCH_SIZE]; /* 1MB of scratch space for gunzip */
+
+typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int);
+
+void
+boot(int a1, int a2, void *prom)
+{
+ unsigned sa, len;
+ void *dst;
+ unsigned char *im;
+ unsigned int initrd_size, initrd_start;
+
+ printf("chrpboot starting: loaded at 0x%p\n\r", &_start);
+
+ initrd_size = &__ramdisk_end - &__ramdisk_begin;
+ if (initrd_size) {
+ initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+ a1 = initrd_start;
+ a2 = initrd_size;
+ claim(initrd_start, RAM_END - initrd_start, 0);
+ printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
+ initrd_start, &__ramdisk_begin, initrd_size);
+ memcpy((char *)initrd_start, &__ramdisk_begin, initrd_size);
+ } else {
+ initrd_start = 0;
+ initrd_size = 0;
+ a2 = 0xdeadbeef;
+ }
+
+ im = &__image_begin;
+ len = &__image_end - &__image_begin;
+ /* claim 4MB starting at PROG_START */
+ claim(PROG_START, PROG_SIZE - PROG_START, 0);
+ dst = (void *) PROG_START;
+ if (im[0] == 0x1f && im[1] == 0x8b) {
+ avail_ram = scratch;
+ begin_avail = avail_high = avail_ram;
+ end_avail = scratch + sizeof(scratch);
+ printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
+ gunzip(dst, 0x400000, im, &len);
+ printf("done %u bytes\n\r", len);
+ printf("%u bytes of heap consumed, max in use %u\n\r",
+ avail_high - begin_avail, heap_max);
+ } else {
+ memmove(dst, im, len);
+ }
+
+ flush_cache(dst, len);
+ make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp,
+ (PROG_START + PROG_SIZE));
+
+ sa = PROG_START;
+ printf("start address = 0x%x\n\r", sa);
+
+ (*(kernel_start_t)sa)(a1, a2, prom, initrd_start, initrd_size);
+
+ printf("returned?\n\r");
+
+ pause();
+}
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 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+#include "nonstdio.h"
+#include "of1275.h"
+
+/* Passed from the linker */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin[], __ramdisk_end;
+extern char _start, _end;
+
+extern char image_data[], initrd_data[];
+extern int initrd_len, image_len;
+extern unsigned int heap_max;
+extern void flush_cache(void *start, unsigned int len);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
+ unsigned int progend);
+extern void setup_bats(unsigned long start);
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+
+#define SCRATCH_SIZE (128 << 10)
+
+static char heap[SCRATCH_SIZE];
+
+static unsigned long ram_start = 0;
+static unsigned long ram_end = 0x1000000;
+
+static unsigned long prog_start = 0x900000;
+static unsigned long prog_size = 0x700000;
+
+typedef void (*kernel_start_t)(int, int, void *);
+
+void boot(int a1, int a2, void *prom)
+{
+ unsigned sa, len;
+ void *dst;
+ unsigned char *im;
+ unsigned initrd_start, initrd_size;
+
+ printf("coffboot starting: loaded at 0x%p\n", &_start);
+ setup_bats(ram_start);
+
+ initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin);
+ if (initrd_size) {
+ initrd_start = (ram_end - initrd_size) & ~0xFFF;
+ a1 = initrd_start;
+ a2 = initrd_size;
+ claim(initrd_start, ram_end - initrd_start, 0);
+ printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
+ initrd_start, (char *)(&__ramdisk_begin), initrd_size);
+ memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size);
+ prog_size = initrd_start - prog_start;
+ } else
+ a2 = 0xdeadbeef;
+
+ im = (char *)(&__image_begin);
+ len = (char *)(&__image_end) - (char *)(&__image_begin);
+ /* claim 4MB starting at PROG_START */
+ claim(prog_start, prog_size, 0);
+ map(prog_start, prog_start, prog_size);
+ dst = (void *) prog_start;
+ if (im[0] == 0x1f && im[1] == 0x8b) {
+ /* set up scratch space */
+ begin_avail = avail_high = avail_ram = heap;
+ end_avail = heap + sizeof(heap);
+ printf("heap at 0x%p\n", avail_ram);
+ printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
+ gunzip(dst, prog_size, im, &len);
+ printf("done %u bytes\n", len);
+ printf("%u bytes of heap consumed, max in use %u\n",
+ avail_high - begin_avail, heap_max);
+ } else {
+ memmove(dst, im, len);
+ }
+
+ flush_cache(dst, len);
+ make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac,
+ (prog_start + prog_size));
+
+ sa = (unsigned long)prog_start;
+ printf("start address = 0x%x\n", sa);
+
+ (*(kernel_start_t)sa)(a1, a2, prom);
+
+ printf("returned?\n");
+
+ pause();
+}
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 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "nonstdio.h"
+#include "of1275.h"
+#include <linux/string.h>
+#include <linux/zlib.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+/* Information from the linker */
+extern char __sysmap_begin, __sysmap_end;
+
+extern int strcmp(const char *s1, const char *s2);
+extern char *avail_ram, *avail_high;
+extern char *end_avail;
+
+unsigned int heap_use, heap_max;
+
+struct memchunk {
+ unsigned int size;
+ struct memchunk *next;
+};
+
+static struct memchunk *freechunks;
+
+static void *zalloc(unsigned size)
+{
+ void *p;
+ struct memchunk **mpp, *mp;
+
+ size = (size + 7) & -8;
+ heap_use += size;
+ if (heap_use > heap_max)
+ heap_max = heap_use;
+ for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+ if (mp->size == size) {
+ *mpp = mp->next;
+ return mp;
+ }
+ }
+ p = avail_ram;
+ avail_ram += size;
+ if (avail_ram > avail_high)
+ avail_high = avail_ram;
+ if (avail_ram > end_avail) {
+ printf("oops... out of memory\n\r");
+ pause();
+ }
+ return p;
+}
+
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
+ printf("bad gzipped data\n\r");
+ exit();
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ printf("gunzip: ran out of data in header\n\r");
+ exit();
+ }
+
+ /* Initialize ourself. */
+ s.workspace = zalloc(zlib_inflate_workspacesize());
+ r = zlib_inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ printf("zlib_inflateInit2 returned %d\n\r", r);
+ exit();
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = zlib_inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ printf("inflate returned %d msg: %s\n\r", r, s.msg);
+ exit();
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ zlib_inflateEnd(&s);
+}
+
+/* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID,
+ * a machine type for BI_MACHTYPE, and the location where the end of the
+ * bootloader is (PROG_START + PROG_SIZE)
+ */
+void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
+ unsigned long progend)
+{
+ unsigned long sysmap_size;
+ struct bi_record *rec;
+
+ /* Figure out the size of a possible System.map we're going to
+ * pass along.
+ * */
+ sysmap_size = (unsigned long)(&__sysmap_end) -
+ (unsigned long)(&__sysmap_begin);
+
+ /* leave a 1MB gap then align to the next 1MB boundary */
+ addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
+ /* oldworld machine seem very unhappy about this. -- Tom */
+ if (addr >= progend)
+ claim(addr, 0x1000, 0);
+
+ rec = (struct bi_record *)addr;
+ rec->tag = BI_FIRST;
+ rec->size = sizeof(struct bi_record);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ rec->tag = BI_BOOTLOADER_ID;
+ sprintf( (char *)rec->data, name);
+ rec->size = sizeof(struct bi_record) + strlen(name) + 1;
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ rec->tag = BI_MACHTYPE;
+ rec->data[0] = mach;
+ rec->data[1] = 1;
+ rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ if (sysmap_size) {
+ rec->tag = BI_SYSMAP;
+ rec->data[0] = (unsigned long)(&__sysmap_begin);
+ rec->data[1] = sysmap_size;
+ rec->size = sizeof(struct bi_record) + 2 *
+ sizeof(unsigned long);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+ }
+
+ rec->tag = BI_LAST;
+ rec->size = sizeof(struct bi_record);
+ rec = (struct bi_record *)((unsigned long)rec + rec->size);
+}
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 @@
+int main(void)
+{
+ return 0;
+}
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 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+ .text
+
+/*
+ * Use the BAT2 & 3 registers to map the 1st 16MB of RAM to
+ * the address given as the 1st argument.
+ */
+ .globl setup_bats
+setup_bats:
+ mfpvr 5
+ rlwinm 5,5,16,16,31 /* r3 = 1 for 601, 4 for 604 */
+ cmpwi 0,5,1
+ li 0,0
+ bne 4f
+ mtibatl 3,0 /* invalidate BAT first */
+ ori 3,3,4 /* set up BAT registers for 601 */
+ li 4,0x7f
+ mtibatu 2,3
+ mtibatl 2,4
+ oris 3,3,0x80
+ oris 4,4,0x80
+ mtibatu 3,3
+ mtibatl 3,4
+ b 5f
+4: mtdbatu 3,0 /* invalidate BATs first */
+ mtibatu 3,0
+ ori 3,3,0xff /* set up BAT registers for 604 */
+ li 4,2
+ mtdbatl 2,4
+ mtdbatu 2,3
+ mtibatl 2,4
+ mtibatu 2,3
+ oris 3,3,0x80
+ oris 4,4,0x80
+ mtdbatl 3,4
+ mtdbatu 3,3
+ mtibatl 3,4
+ mtibatu 3,3
+5: sync
+ isync
+ blr
+
+/*
+ * Flush the dcache and invalidate the icache for a range of addresses.
+ *
+ * flush_cache(addr, len)
+ */
+ .global flush_cache
+flush_cache:
+ addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */
+ rlwinm. 4,4,27,5,31
+ mtctr 4
+ beqlr
+1: dcbf 0,3
+ icbi 0,3
+ addi 3,3,0x20
+ bdnz 1b
+ sync
+ isync
+ 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 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include "nonstdio.h"
+#include "of1275.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+
+/* Passed from the linker */
+extern char __image_begin, __image_end;
+extern char __ramdisk_begin[], __ramdisk_end;
+extern char _start, _end;
+
+extern unsigned int heap_max;
+extern void flush_cache(void *start, unsigned int len);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
+ unsigned int progend);
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+
+
+#define RAM_END (16 << 20)
+
+#define PROG_START 0x00010000
+#define PROG_SIZE 0x007f0000
+
+#define SCRATCH_SIZE (128 << 10)
+
+typedef void (*kernel_start_t)(int, int, void *);
+
+void boot(int a1, int a2, void *prom)
+{
+ unsigned sa, len;
+ void *dst;
+ unsigned char *im;
+ unsigned initrd_start, initrd_size;
+
+ printf("chrpboot starting: loaded at 0x%p\n", &_start);
+
+ initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin);
+ if (initrd_size) {
+ initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+ a1 = initrd_start;
+ a2 = initrd_size;
+ claim(initrd_start, RAM_END - initrd_start, 0);
+ printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
+ initrd_start, (char *)(&__ramdisk_begin), initrd_size);
+ memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size);
+ } else
+ a2 = 0xdeadbeef;
+
+ im = (char *)(&__image_begin);
+ len = (char *)(&__image_end) - (char *)(&__image_begin);
+ /* claim 3MB starting at PROG_START */
+ claim(PROG_START, PROG_SIZE, 0);
+ dst = (void *) PROG_START;
+ if (im[0] == 0x1f && im[1] == 0x8b) {
+ /* claim some memory for scratch space */
+ avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10);
+ begin_avail = avail_high = avail_ram;
+ end_avail = avail_ram + SCRATCH_SIZE;
+ printf("heap at 0x%p\n", avail_ram);
+ printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
+ gunzip(dst, PROG_SIZE, im, &len);
+ printf("done %u bytes\n", len);
+ printf("%u bytes of heap consumed, max in use %u\n",
+ avail_high - begin_avail, heap_max);
+ release(begin_avail, SCRATCH_SIZE);
+ } else {
+ memmove(dst, im, len);
+ }
+
+ flush_cache(dst, len);
+ make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac,
+ (PROG_START + PROG_SIZE));
+
+ sa = (unsigned long)PROG_START;
+ printf("start address = 0x%x\n", sa);
+
+ (*(kernel_start_t)sa)(a1, a2, prom);
+
+ printf("returned?\n");
+
+ pause();
+}
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 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdarg.h>
+#include "of1275.h"
+
+extern int strlen(const char *s);
+extern void boot(int a1, int a2, void *prom);
+
+phandle stdin;
+phandle stdout;
+phandle stderr;
+
+void printk(char *fmt, ...);
+
+void
+start(int a1, int a2, void *promptr)
+{
+ ofinit(promptr);
+ if (ofstdio(&stdin, &stdout, &stderr))
+ exit();
+
+ boot(a1, a2, promptr);
+ for (;;)
+ exit();
+}
+
+int writestring(void *f, char *ptr, int nb)
+{
+ int w = 0, i;
+ char *ret = "\r";
+
+ for (i = 0; i < nb; ++i) {
+ if (ptr[i] == '\n') {
+ if (i > w) {
+ write(f, ptr + w, i - w);
+ w = i;
+ }
+ write(f, ret, 1);
+ }
+ }
+ if (w < nb)
+ write(f, ptr + w, nb - w);
+ return nb;
+}
+
+int
+putc(int c, void *f)
+{
+ char ch = c;
+
+ return writestring(f, &ch, 1) == 1? c: -1;
+}
+
+int
+putchar(int c)
+{
+ return putc(c, stdout);
+}
+
+int
+fputs(char *str, void *f)
+{
+ int n = strlen(str);
+
+ return writestring(f, str, n) == n? 0: -1;
+}
+
+int
+readchar(void)
+{
+ char ch;
+
+ for (;;) {
+ switch (read(stdin, &ch, 1)) {
+ case 1:
+ return ch;
+ case -1:
+ printk("read(stdin) returned -1\n");
+ return -1;
+ }
+ }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+int
+getchar(void)
+{
+ int c;
+
+ if (lineleft == 0) {
+ lineptr = line;
+ for (;;) {
+ c = readchar();
+ if (c == -1 || c == 4)
+ break;
+ if (c == '\r' || c == '\n') {
+ *lineptr++ = '\n';
+ putchar('\n');
+ break;
+ }
+ switch (c) {
+ case 0177:
+ case '\b':
+ if (lineptr > line) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ --lineptr;
+ }
+ break;
+ case 'U' & 0x1F:
+ while (lineptr > line) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ --lineptr;
+ }
+ break;
+ default:
+ if (lineptr >= &line[sizeof(line) - 1])
+ putchar('\a');
+ else {
+ putchar(c);
+ *lineptr++ = c;
+ }
+ }
+ }
+ lineleft = lineptr - line;
+ lineptr = line;
+ }
+ if (lineleft == 0)
+ return -1;
+ --lineleft;
+ return *lineptr++;
+}
+
+extern int vsprintf(char *buf, const char *fmt, va_list args);
+static char sprint_buf[1024];
+
+void
+printk(char *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vsprintf(sprint_buf, fmt, args);
+ va_end(args);
+ writestring(stdout, sprint_buf, n);
+}
+
+int
+printf(char *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vsprintf(sprint_buf, fmt, args);
+ va_end(args);
+ writestring(stdout, sprint_buf, n);
+ return n;
+}