diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
commit | 6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch) | |
tree | 0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /arch/ppc/chrpboot | |
parent | ecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (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/Makefile | 35 | ||||
-rw-r--r-- | arch/ppc/chrpboot/addnote.c | 163 | ||||
-rw-r--r-- | arch/ppc/chrpboot/main.c | 30 | ||||
-rw-r--r-- | arch/ppc/chrpboot/start.c | 23 |
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) { |