summaryrefslogtreecommitdiffstats
path: root/arch/ppc/chrpboot
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
commit6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch)
tree0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /arch/ppc/chrpboot
parentecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff)
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine status unknown.
Diffstat (limited to 'arch/ppc/chrpboot')
-rw-r--r--arch/ppc/chrpboot/Makefile35
-rw-r--r--arch/ppc/chrpboot/addnote.c163
-rw-r--r--arch/ppc/chrpboot/main.c30
-rw-r--r--arch/ppc/chrpboot/start.c23
4 files changed, 223 insertions, 28 deletions
diff --git a/arch/ppc/chrpboot/Makefile b/arch/ppc/chrpboot/Makefile
index e988ce9de..48750982e 100644
--- a/arch/ppc/chrpboot/Makefile
+++ b/arch/ppc/chrpboot/Makefile
@@ -5,29 +5,24 @@
#
# Based on coffboot by Paul Mackerras
-.c.s:
- $(CC) $(CFLAGS) -S -o $*.s $<
-.s.o:
- $(AS) -o $*.o $<
+ifeq ($(CONFIG_PPC64BRIDGE),y)
+MSIZE=.64
+AFLAGS += -Wa,-mppc64bridge
+else
+MSIZE=
+endif
+
.c.o:
$(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $<
-.S.s:
- $(CPP) $(AFLAGS) -traditional -o $*.o $<
.S.o:
$(CC) $(AFLAGS) -traditional -c -o $*.o $<
CFLAGS = $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS
LD_ARGS = -Ttext 0x00400000
-OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o sysmap.o
+OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o
LIBS = $(TOPDIR)/lib/lib.a
-ifeq ($(CONFIG_PPC64),y)
-MSIZE=.64
-else
-MSIZE=
-endif
-
ifeq ($(CONFIG_ALL_PPC),y)
# yes, we want to build chrp stuff
CONFIG_CHRP = y
@@ -58,8 +53,8 @@ floppy: zImage
piggyback: piggyback.c
$(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c
-mknote: mknote.c
- $(HOSTCC) $(HOSTCFLAGS) -o mknote mknote.c
+addnote: addnote.c
+ $(HOSTCC) $(HOSTCFLAGS) -o addnote addnote.c
image.o: piggyback ../coffboot/vmlinux.gz
./piggyback image < ../coffboot/vmlinux.gz | $(AS) -o image.o
@@ -70,13 +65,13 @@ sysmap.o: piggyback ../../../System.map
initrd.o: ramdisk.image.gz piggyback
./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o
-zImage: $(OBJS) no_initrd.o mknote
+zImage: $(OBJS) no_initrd.o addnote
$(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS)
- ./mknote > note
- $(OBJCOPY) $@ $@ --add-section=.note=note -R .comment
+ ./addnote $@
-zImage.initrd: $(OBJS) initrd.o
+zImage.initrd: $(OBJS) initrd.o addnote
$(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS)
+ ./addnote $@
else
znetboot:
@@ -98,7 +93,7 @@ vmlinux.coff.initrd:
clean:
- rm -f piggyback note mknote $(OBJS) zImage
+ rm -f piggyback note addnote $(OBJS) zImage
fastdep:
$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
diff --git a/arch/ppc/chrpboot/addnote.c b/arch/ppc/chrpboot/addnote.c
new file mode 100644
index 000000000..5f0934f6e
--- /dev/null
+++ b/arch/ppc/chrpboot/addnote.c
@@ -0,0 +1,163 @@
+/*
+ * Program to hack in a PT_NOTE program header entry in an ELF file.
+ * This is needed for OF on RS/6000s to load an image correctly.
+ * Note that OF needs a program header entry for the note, not an
+ * ELF section.
+ *
+ * Copyright 2000 Paul Mackerras.
+ *
+ * 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.
+ *
+ * Usage: addnote zImage
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+char arch[] = "PowerPC";
+
+#define N_DESCR 6
+unsigned int descr[N_DESCR] = {
+ 0xffffffff, /* real-mode = true */
+ 0x00c00000, /* real-base, i.e. where we expect OF to be */
+ 0xffffffff, /* real-size */
+ 0xffffffff, /* virt-base */
+ 0xffffffff, /* virt-size */
+ 0x4000, /* load-base */
+};
+
+unsigned char buf[512];
+
+#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1]))
+#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2))
+
+#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \
+ buf[(off) + 1] = (v) & 0xff)
+#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \
+ PUT_16BE((off) + 2, (v)))
+
+/* Structure of an ELF file */
+#define E_IDENT 0 /* ELF header */
+#define E_PHOFF 28
+#define E_PHENTSIZE 42
+#define E_PHNUM 44
+#define E_HSIZE 52 /* size of ELF header */
+
+#define EI_MAGIC 0 /* offsets in E_IDENT area */
+#define EI_CLASS 4
+#define EI_DATA 5
+
+#define PH_TYPE 0 /* ELF program header */
+#define PH_OFFSET 4
+#define PH_FILESZ 16
+#define PH_HSIZE 32 /* size of program header */
+
+#define PT_NOTE 4 /* Program header type = note */
+
+#define ELFCLASS32 1
+#define ELFDATA2MSB 2
+
+unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
+
+main(int ac, char **av)
+{
+ int fd, n, i;
+ int ph, ps, np;
+ int nnote, ns;
+
+ if (ac != 2) {
+ fprintf(stderr, "Usage: %s elf-file\n", av[0]);
+ exit(1);
+ }
+ fd = open(av[1], O_RDWR);
+ if (fd < 0) {
+ perror(av[1]);
+ exit(1);
+ }
+
+ nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
+
+ n = read(fd, buf, sizeof(buf));
+ if (n < 0) {
+ perror("read");
+ exit(1);
+ }
+
+ if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
+ goto notelf;
+
+ if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
+ || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
+ fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
+ av[1]);
+ exit(1);
+ }
+
+ ph = GET_32BE(E_PHOFF);
+ ps = GET_16BE(E_PHENTSIZE);
+ np = GET_16BE(E_PHNUM);
+ if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
+ goto notelf;
+ if (ph + (np + 1) * ps + nnote > n)
+ goto nospace;
+
+ for (i = 0; i < np; ++i) {
+ if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
+ fprintf(stderr, "%s already has a note entry\n",
+ av[1]);
+ exit(0);
+ }
+ ph += ps;
+ }
+
+ /* XXX check that the area we want to use is all zeroes */
+ for (i = 0; i < ps + nnote; ++i)
+ if (buf[ph + i] != 0)
+ goto nospace;
+
+ /* fill in the program header entry */
+ ns = ph + ps;
+ PUT_32BE(ph + PH_TYPE, PT_NOTE);
+ PUT_32BE(ph + PH_OFFSET, ns);
+ PUT_32BE(ph + PH_FILESZ, nnote);
+
+ /* fill in the note area we point to */
+ /* XXX we should probably make this a proper section */
+ PUT_32BE(ns, strlen(arch) + 1);
+ PUT_32BE(ns + 4, N_DESCR * 4);
+ PUT_32BE(ns + 8, 0x1275);
+ strcpy(&buf[ns + 12], arch);
+ ns += 12 + strlen(arch) + 1;
+ for (i = 0; i < N_DESCR; ++i)
+ PUT_32BE(ns + i * 4, descr[i]);
+
+ /* Update the number of program headers */
+ PUT_16BE(E_PHNUM, np + 1);
+
+ /* write back */
+ lseek(fd, (long) 0, SEEK_SET);
+ i = write(fd, buf, n);
+ if (i < 0) {
+ perror("write");
+ exit(1);
+ }
+ if (i < n) {
+ fprintf(stderr, "%s: write truncated\n", av[1]);
+ exit(1);
+ }
+
+ exit(0);
+
+ notelf:
+ fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
+ exit(1);
+
+ nospace:
+ fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
+ av[0]);
+ exit(1);
+}
diff --git a/arch/ppc/chrpboot/main.c b/arch/ppc/chrpboot/main.c
index 91bf4d8c4..a080f5ac6 100644
--- a/arch/ppc/chrpboot/main.c
+++ b/arch/ppc/chrpboot/main.c
@@ -16,11 +16,11 @@ extern void *finddevice(const char *);
extern int getprop(void *, const char *, void *, int);
void gunzip(void *, int, unsigned char *, int *);
-#define get_16be(x) (*(unsigned short *)(x))
-#define get_32be(x) (*(unsigned *)(x))
-
#define RAM_START 0x00000000
-#define RAM_END (8<<20)
+#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
@@ -36,6 +36,7 @@ extern int initrd_len;
extern char sysmap_data[];
extern int sysmap_len;
+static char scratch[1024<<10]; /* 1MB of scratch space for gunzip */
chrpboot(int a1, int a2, void *prom)
{
@@ -48,13 +49,25 @@ chrpboot(int a1, int a2, void *prom)
printf("chrpboot starting: loaded at 0x%x\n\r", &_start);
- end_avail = (char *) RAM_END;
+ if (initrd_len) {
+ initrd_size = initrd_len;
+ 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%x (%x bytes)\n\r",
+ initrd_start, initrd_data, initrd_size);
+ memcpy((char *)initrd_start, initrd_data, initrd_size);
+ }
im = image_data;
len = image_len;
+ /* claim 4MB starting at PROG_START */
+ claim(PROG_START, (4<<20) - PROG_START, 0);
dst = (void *) PROG_START;
if (im[0] == 0x1f && im[1] == 0x8b) {
- avail_ram = (char *)RAM_FREE;
+ avail_ram = scratch;
+ end_avail = scratch + sizeof(scratch);
printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
gunzip(dst, 0x400000, im, &len);
printf("done %u bytes\n\r", len);
@@ -86,17 +99,18 @@ chrpboot(int a1, int a2, void *prom)
rec->data[1] = 1;
rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
+#if 0
rec->tag = BI_SYSMAP;
rec->data[0] = (unsigned long)sysmap_data;
rec->data[1] = sysmap_len;
rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
rec = (struct bi_record *)((unsigned long)rec + rec->size);
+#endif
rec->tag = BI_LAST;
rec->size = sizeof(struct bi_record);
rec = (struct bi_record *)((unsigned long)rec + rec->size);
}
- (*(void (*)())sa)(0, 0, prom, a1, a2);
+ (*(void (*)())sa)(a1, a2, prom);
printf("returned?\n\r");
diff --git a/arch/ppc/chrpboot/start.c b/arch/ppc/chrpboot/start.c
index 161d9a980..308f4fcd3 100644
--- a/arch/ppc/chrpboot/start.c
+++ b/arch/ppc/chrpboot/start.c
@@ -131,6 +131,29 @@ finddevice(const char *name)
return args.phandle;
}
+void *
+claim(unsigned int virt, unsigned int size, unsigned int align)
+{
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ unsigned int virt;
+ unsigned int size;
+ unsigned int align;
+ void *ret;
+ } args;
+
+ args.service = "claim";
+ args.nargs = 3;
+ args.nret = 1;
+ args.virt = virt;
+ args.size = size;
+ args.align = align;
+ (*prom)(&args);
+ return args.ret;
+}
+
int
getprop(void *phandle, const char *name, void *buf, int buflen)
{