aboutsummaryrefslogtreecommitdiff
path: root/tip22
diff options
context:
space:
mode:
authorGuido Guenther <agx@sigxcpu.org>2006-11-18 23:48:07 +0100
committerGuido Guenther <agx@bogon.sigxcpu.org>2006-11-18 23:48:07 +0100
commitd1e063beb43e595680c65e3804d1f8ddff53373b (patch)
treef7256dfe1b807920270ec5113df6f6e4abf1ed0f /tip22
Imported Debian version 0.3.8.80.3.8.8
Diffstat (limited to 'tip22')
-rw-r--r--tip22/.cvsignore6
-rw-r--r--tip22/Makefile73
-rw-r--r--tip22/README32
-rw-r--r--tip22/kernel/parse_rd_cmd_line-2.4-2002-05-09.diff88
-rw-r--r--tip22/kernel/parse_rd_cmd_line-2.6-2004-11-17.diff172
-rw-r--r--tip22/ld.kernel.script.in11
-rw-r--r--tip22/ld.ramdisk.script.in11
-rw-r--r--tip22/ld.script.in78
-rw-r--r--tip22/tftpload.c353
-rw-r--r--tip22/tip2251
-rwxr-xr-xtip22/tip3251
11 files changed, 926 insertions, 0 deletions
diff --git a/tip22/.cvsignore b/tip22/.cvsignore
new file mode 100644
index 0000000..c5aacb9
--- /dev/null
+++ b/tip22/.cvsignore
@@ -0,0 +1,6 @@
+ld.kernel.script.IP22
+ld.kernel.script.IP32
+ld.ramdisk.script.IP22
+ld.ramdisk.script.IP32
+ld.script.IP22
+ld.script.IP32
diff --git a/tip22/Makefile b/tip22/Makefile
new file mode 100644
index 0000000..2efe8ae
--- /dev/null
+++ b/tip22/Makefile
@@ -0,0 +1,73 @@
+#
+# Copyright 2002-2004 Guido Guenther <agx@sigxcpu.org>
+#
+
+ARCLIBDIR = ../arclib
+ARCLIB = $(ARCLIBDIR)/libarc.a
+
+COMMONDIR = ../common
+PRINT_LOADADDR = $(COMMONDIR)/print_loadaddr
+PRINT_OUTPUTFORMAT = $(COMMONDIR)/print_outputformat
+
+CFLAGS += -O2 -I$(COMMONDIR) -I$(ARCLIBDIR) -Wall -mno-abicalls -G 0 \
+ -fno-pic -DSUBARCH=${SUBARCH}
+
+ASFLAGS = -O2 -mno-abicalls -G 0 -fno-pic
+
+LIBDIR ?= /usr/lib/tip22
+BINDIR ?= /usr/sbin
+
+LIBS=${ARCLIB}
+BINS=tip22 tip32
+LD_SCRIPTS = ld.kernel.script.$(SUBARCH) ld.ramdisk.script.$(SUBARCH) ld.script.$(SUBARCH)
+OBJECTS = tftpload.$(SUBARCH).o
+TARGETS = $(OBJECTS) $(LD_SCRIPTS)
+
+# uncomment for debugging
+#CFLAGS+=-DDEBUG
+
+
+all: ${LIBS} ${BINS}
+ @$(MAKE) SUBARCH=IP32 archall
+ @$(MAKE) SUBARCH=IP22 archall
+
+archall: $(TARGETS)
+
+
+$(ARCLIB):
+ @$(MAKE) -C $(ARCLIBDIR)
+
+$(PRINT_LOADADDR):
+ @$(MAKE) -C $(COMMONDIR) SUBARCH=$(SUBARCH)
+
+
+%.$(SUBARCH).o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.script.$(SUBARCH): %.script.in $(PRINT_LOADADDR) $(PRINT_OUTPUTFORMAT)
+ LOADADDR=$$($(PRINT_LOADADDR) $(SUBARCH)); \
+ OUTPUTFORMAT=$$($(PRINT_OUTPUTFORMAT) $(SUBARCH)); \
+ sed -e "s/@@LOADADDR@@/$$LOADADDR/" \
+ -e "s/@@OUTPUTFORMAT@@/$$OUTPUTFORMAT/" <$< >$@
+
+clean:
+ @$(MAKE) SUBARCH=IP32 archclean
+ @$(MAKE) SUBARCH=IP22 archclean
+ rm -f tags *~
+
+archclean:
+ @$(MAKE) -C $(ARCLIBDIR) clean
+ @$(MAKE) -C $(COMMONDIR) clean
+ rm -f $(TARGETS)
+
+install: all
+ install -d ${PREFIX}/${BINDIR}
+ install -m 755 ${BINS} ${PREFIX}/${BINDIR}
+ @$(MAKE) SUBARCH=IP32 archinstall
+ @$(MAKE) SUBARCH=IP22 archinstall
+
+archinstall:
+ $(foreach tg,$(TARGETS),install -m 644 $(tg) ${PREFIX}/${LIBDIR};)
+
+
+.PHONY: all archall clean archclean install archinstall
diff --git a/tip22/README b/tip22/README
new file mode 100644
index 0000000..becc313
--- /dev/null
+++ b/tip22/README
@@ -0,0 +1,32 @@
+How to create the boot image:
+-----------------------------------
+
+tip22 <vmlinux> <initrd> <outputfile>
+tip32 <vmlinux> <initrd> <outputfile>
+
+- vmlinux is an ELF Linux kernel. For versions before 2.6.9 you need to
+ apply an extra patch for correct commandline parsing, see
+ /usr/share/doc/tip22/examples.
+- initrd is the gzip compressed initial ramdisk you want add
+- outputfile is the bootimage. It is in ECOFF format for ip22 and in
+ ELF format for ip32. You can for example tfpboot this image on an SGI
+ Indy using the bootp(): command in the prom.
+
+it basically works like this:
+-----------------------------
+- tftpload.o is a relocatable object created during package build time
+- the tip22 script converts the ramdisk and vmlinux to relocatable
+ objects using linker scripts including symbols that mark the begin
+ and the end of kernel and ramdisk
+- those are linked together into the output file using yet another
+ linker script
+- when executed by the prom the embedded loader:
+ - memcopies the kernel to its loadaddress
+ - memcopies the initrd after the kernel to a page boundary
+ - parses the command line and everything within an append="..."
+ statement is passed on to the kernel, e.g.
+ 'bootp(): append="console=ttyS0"'
+ - jumps into the kernel passing the start address and size of the
+ initrd on the command line
+
+ -- Thu, 15 May 2002 23:07:18 +0200 Guido Guenther <agx@sigxcpu.org>
diff --git a/tip22/kernel/parse_rd_cmd_line-2.4-2002-05-09.diff b/tip22/kernel/parse_rd_cmd_line-2.4-2002-05-09.diff
new file mode 100644
index 0000000..c1bd785
--- /dev/null
+++ b/tip22/kernel/parse_rd_cmd_line-2.4-2002-05-09.diff
@@ -0,0 +1,88 @@
+Index: arch/mips/kernel/setup.c
+===================================================================
+RCS file: /cvs/linux/arch/mips/kernel/setup.c,v
+retrieving revision 1.96.2.12
+diff -u -u -r1.96.2.12 setup.c
+--- arch/mips/kernel/setup.c 2002/02/15 21:05:48 1.96.2.12
++++ arch/mips/kernel/setup.c 2002/05/09 17:17:59
+@@ -650,6 +650,38 @@
+ }
+ }
+
++static inline void parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
++{
++ char c = ' ', *to = command_line, *from = saved_command_line;
++ int len = 0;
++ unsigned long rd_size = 0;
++
++ for (;;) {
++ /*
++ * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
++ * "rd_size=0xNN" it's size
++ */
++ if (c == ' ' && !memcmp(from, "rd_start=", 9)) {
++ if (to != command_line)
++ to--;
++ (*rd_start) = memparse(from + 9, &from);
++ }
++ if (c == ' ' && !memcmp(from, "rd_size=", 8)) {
++ if (to != command_line)
++ to--;
++ rd_size = memparse(from + 8, &from);
++ }
++ c = *(from++);
++ if (!c)
++ break;
++ if (CL_SIZE <= ++len)
++ break;
++ *(to++) = c;
++ }
++ *to = '\0';
++ (*rd_end) = (*rd_start) + rd_size;
++}
++
+ void __init setup_arch(char **cmdline_p)
+ {
+ void atlas_setup(void);
+@@ -674,10 +706,7 @@
+
+ unsigned long bootmap_size;
+ unsigned long start_pfn, max_pfn, max_low_pfn, first_usable_pfn;
+-#ifdef CONFIG_BLK_DEV_INITRD
+- unsigned long tmp;
+- unsigned long* initrd_header;
+-#endif
++ unsigned long end = &_end;
+
+ int i;
+
+@@ -828,22 +857,18 @@
+ #define MAXMEM_PFN PFN_DOWN(MAXMEM)
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+- tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
+- if (tmp < (unsigned long)&_end)
+- tmp += PAGE_SIZE;
+- initrd_header = (unsigned long *)tmp;
+- if (initrd_header[0] == 0x494E5244) {
+- initrd_start = (unsigned long)&initrd_header[2];
+- initrd_end = initrd_start + initrd_header[1];
++ parse_rd_cmdline(&initrd_start, &initrd_end);
++ if(initrd_start && initrd_end)
++ end = initrd_end;
++ else {
++ initrd_start = initrd_end = 0;
+ }
+- start_pfn = PFN_UP(__pa((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
+-#else
++#endif /* CONFIG_BLK_DEV_INITRD */
+ /*
+ * Partially used pages are not usable - thus
+ * we are rounding upwards.
+ */
+- start_pfn = PFN_UP(__pa(&_end));
+-#endif /* CONFIG_BLK_DEV_INITRD */
++ start_pfn = PFN_UP(__pa(end));
+
+ /* Find the highest page frame number we have available. */
+ max_pfn = 0;
diff --git a/tip22/kernel/parse_rd_cmd_line-2.6-2004-11-17.diff b/tip22/kernel/parse_rd_cmd_line-2.6-2004-11-17.diff
new file mode 100644
index 0000000..504dd66
--- /dev/null
+++ b/tip22/kernel/parse_rd_cmd_line-2.6-2004-11-17.diff
@@ -0,0 +1,172 @@
+Index: arch/mips/kernel/setup.c
+===================================================================
+RCS file: /home/cvs/linux/arch/mips/kernel/setup.c,v
+retrieving revision 1.171
+diff -u -p -r1.171 setup.c
+--- arch/mips/kernel/setup.c 28 Jun 2004 21:04:12 -0000 1.171
++++ arch/mips/kernel/setup.c 19 Nov 2004 00:45:23 -0000
+@@ -194,6 +194,68 @@ static inline void parse_cmdline_early(v
+ }
+ }
+
++static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
++{
++ /*
++ * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
++ * "rd_size=0xNN" it's size
++ */
++ unsigned long start = 0;
++ unsigned long size = 0;
++ unsigned long end;
++ char cmd_line[CL_SIZE];
++ char *start_str;
++ char *size_str;
++ char *tmp;
++
++ strcpy(cmd_line, command_line);
++ *command_line = 0;
++ tmp = cmd_line;
++ /* Ignore "rd_start=" strings in other parameters. */
++ start_str = strstr(cmd_line, "rd_start=");
++ if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
++ start_str = strstr(start_str, " rd_start=");
++ while (start_str) {
++ if (start_str != cmd_line)
++ strncat(command_line, tmp, start_str - tmp);
++ start = memparse(start_str + 9, &start_str);
++ tmp = start_str + 1;
++ start_str = strstr(start_str, " rd_start=");
++ }
++ if (*tmp)
++ strcat(command_line, tmp);
++
++ strcpy(cmd_line, command_line);
++ *command_line = 0;
++ tmp = cmd_line;
++ /* Ignore "rd_size" strings in other parameters. */
++ size_str = strstr(cmd_line, "rd_size=");
++ if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
++ size_str = strstr(size_str, " rd_size=");
++ while (size_str) {
++ if (size_str != cmd_line)
++ strncat(command_line, tmp, size_str - tmp);
++ size = memparse(size_str + 8, &size_str);
++ tmp = size_str + 1;
++ size_str = strstr(size_str, " rd_size=");
++ }
++ if (*tmp)
++ strcat(command_line, tmp);
++
++#ifdef CONFIG_MIPS64
++ /* HACK: Guess if the sign extension was forgotten */
++ if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
++ start |= 0xffffffff00000000;
++#endif
++
++ end = start + size;
++ if (start && end) {
++ *rd_start = start;
++ *rd_end = end;
++ return 1;
++ }
++ return 0;
++}
+
+ #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+ #define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+@@ -205,30 +267,45 @@ static inline void parse_cmdline_early(v
+ static inline void bootmem_init(void)
+ {
+ unsigned long start_pfn;
++ unsigned long reserved_end = (unsigned long)&_end;
+ #ifndef CONFIG_SGI_IP27
+- unsigned long bootmap_size, max_low_pfn, first_usable_pfn;
++ unsigned long first_usable_pfn;
++ unsigned long bootmap_size;
+ int i;
+ #endif
+ #ifdef CONFIG_BLK_DEV_INITRD
+- unsigned long tmp;
+- unsigned long *initrd_header;
++ int initrd_reserve_bootmem = 0;
+
+- tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
+- if (tmp < (unsigned long)&_end)
+- tmp += PAGE_SIZE;
+- initrd_header = (unsigned long *)tmp;
+- if (initrd_header[0] == 0x494E5244) {
+- initrd_start = (unsigned long)&initrd_header[2];
+- initrd_end = initrd_start + initrd_header[1];
++ /* Board specific code should have set up initrd_start and initrd_end */
++ ROOT_DEV = Root_RAM0;
++ if (&__rd_start != &__rd_end) {
++ initrd_start = (unsigned long)&__rd_start;
++ initrd_end = (unsigned long)&__rd_end;
++ } else if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
++ reserved_end = max(reserved_end, initrd_end);
++ initrd_reserve_bootmem = 1;
++ } else {
++ unsigned long tmp;
++ unsigned long *initrd_header;
++
++ tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
++ if (tmp < reserved_end)
++ tmp += PAGE_SIZE;
++ initrd_header = (unsigned long *)tmp;
++ if (initrd_header[0] == 0x494E5244) {
++ initrd_start = (unsigned long)&initrd_header[2];
++ initrd_end = initrd_start + initrd_header[1];
++ reserved_end = max(reserved_end, initrd_end);
++ initrd_reserve_bootmem = 1;
++ }
+ }
+- start_pfn = PFN_UP(CPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
+-#else
++#endif /* CONFIG_BLK_DEV_INITRD */
++
+ /*
+ * Partially used pages are not usable - thus
+ * we are rounding upwards.
+ */
+- start_pfn = PFN_UP(CPHYSADDR(&_end));
+-#endif /* CONFIG_BLK_DEV_INITRD */
++ start_pfn = PFN_UP(CPHYSADDR(reserved_end));
+
+ #ifndef CONFIG_SGI_IP27
+ /* Find the highest page frame number we have available. */
+@@ -341,21 +418,14 @@ static inline void bootmem_init(void)
+
+ /* Reserve the bootmap memory. */
+ reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
+-#endif
++#endif /* CONFIG_SGI_IP27 */
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+- /* Board specific code should have set up initrd_start and initrd_end */
+- ROOT_DEV = Root_RAM0;
+- if (&__rd_start != &__rd_end) {
+- initrd_start = (unsigned long)&__rd_start;
+- initrd_end = (unsigned long)&__rd_end;
+- }
+ initrd_below_start_ok = 1;
+ if (initrd_start) {
+ unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
+ printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
+- (void *)initrd_start,
+- initrd_size);
++ (void *)initrd_start, initrd_size);
+
+ if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+ printk("initrd extends beyond end of memory "
+@@ -363,7 +433,11 @@ static inline void bootmem_init(void)
+ sizeof(long) * 2, CPHYSADDR(initrd_end),
+ sizeof(long) * 2, PFN_PHYS(max_low_pfn));
+ initrd_start = initrd_end = 0;
++ initrd_reserve_bootmem = 0;
+ }
++
++ if (initrd_reserve_bootmem)
++ reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
+ }
+ #endif /* CONFIG_BLK_DEV_INITRD */
+ }
diff --git a/tip22/ld.kernel.script.in b/tip22/ld.kernel.script.in
new file mode 100644
index 0000000..df01e37
--- /dev/null
+++ b/tip22/ld.kernel.script.in
@@ -0,0 +1,11 @@
+OUTPUT_FORMAT("@@OUTPUTFORMAT@@")
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+ .data :
+ {
+ __kernel_start = .;
+ *(.data)
+ __kernel_end = .;
+ }
+}
diff --git a/tip22/ld.ramdisk.script.in b/tip22/ld.ramdisk.script.in
new file mode 100644
index 0000000..38f11d2
--- /dev/null
+++ b/tip22/ld.ramdisk.script.in
@@ -0,0 +1,11 @@
+OUTPUT_FORMAT("@@OUTPUTFORMAT@@")
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+ .data :
+ {
+ __rd_start = .;
+ *(.data)
+ __rd_end = .;
+ }
+}
diff --git a/tip22/ld.script.in b/tip22/ld.script.in
new file mode 100644
index 0000000..4f5597c
--- /dev/null
+++ b/tip22/ld.script.in
@@ -0,0 +1,78 @@
+OUTPUT_FORMAT("@@OUTPUTFORMAT@@")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ /* XXX: place the loader after the kernel */
+ . = @@LOADADDR@@;
+
+ /* read-only */
+ _text = .; /* Text and read-only data */
+ .text : {
+ _ftext = .;
+ *(.text .text.*)
+ *(.rodata*)
+ } =0
+
+ _etext = .; /* End of text section */
+ PROVIDE (etext = .);
+
+ . = ALIGN(16);
+
+ /* writeable */
+ .data : {
+ _fdata = .;
+ *(.data .data.*)
+ } =0
+
+ _gp = ALIGN(16) + 0x7ff0;
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __bss_start = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ _fbss = .;
+ *(.dynbss)
+ *(.bss .bss.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections. */
+ . = ALIGN(32 / 8);
+ }
+ . = ALIGN(32 / 8);
+ __bss_stop = .;
+ _end = .;
+ PROVIDE (end = .);
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.text.exit)
+ *(.data.exit)
+ *(.exitcall.exit)
+ *(.stab)
+ *(.stabstr)
+ *(.pdr)
+ *(.note)
+ *(.reginfo)
+ *(.options)
+ *(.MIPS.options)
+ *(.debug*)
+ *(.line)
+ *(.mdebug*)
+ *(.comment*)
+ *(.gptab*)
+ *(.note)
+ }
+}
diff --git a/tip22/tftpload.c b/tip22/tftpload.c
new file mode 100644
index 0000000..c0bf0a2
--- /dev/null
+++ b/tip22/tftpload.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2002-04 Guido Guenther <agx@sigxcpu.org>
+ *
+ * based on arcboot/ext2load/loader.c
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <types.h>
+
+#include <arc.h>
+#include <elf.h>
+
+#include <sys/types.h>
+
+#include <version.h>
+#include <subarch.h>
+
+#define KSEG0ADDR(addr) (((addr) & 0x1fffffff) | 0x80000000)
+
+#define ANSI_CLEAR "\033[2J"
+
+typedef enum { False = 0, True } Boolean;
+
+extern void* __kernel_start;
+extern void* __kernel_end;
+extern void* __rd_start;
+extern void* __rd_end;
+
+static void Wait(const char *prompt)
+{
+ int ch;
+
+ if (prompt != NULL)
+ puts(prompt);
+
+ do {
+ ch = getchar();
+ } while ((ch != EOF) && (((char) ch) != ' '));
+}
+
+
+static void Fatal(const CHAR * message, ...)
+{
+ va_list ap;
+
+ if (message != NULL) {
+ printf("FATAL ERROR: ");
+ va_start(ap, message);
+ vprintf(message, ap);
+ va_end(ap);
+ }
+
+ Wait("\n\r--- Press <spacebar> to enter ARC interactive mode ---");
+ ArcEnterInteractiveMode();
+}
+
+
+static void InitMalloc(void)
+{
+ MEMORYDESCRIPTOR *current = NULL;
+ ULONG stack = (ULONG) & current;
+#ifdef DEBUG
+ printf("stack starts at: 0x%lx\n\r", stack);
+#endif
+
+ current = ArcGetMemoryDescriptor(current);
+ if(! current ) {
+ Fatal("Can't find any valid memory descriptors!\n\r");
+ }
+ while (current != NULL) {
+ /*
+ * The spec says we should have an adjacent FreeContiguous
+ * memory area that includes our stack. It would be much
+ * easier to just look for that and give it to malloc, but
+ * the Indy only shows FreeMemory areas, no FreeContiguous.
+ * Oh well.
+ */
+ if (current->Type == FreeMemory) {
+ ULONG start = KSEG0ADDR(current->BasePage * PAGE_SIZE);
+ ULONG end =
+ start + (current->PageCount * PAGE_SIZE);
+#if DEBUG
+ printf("Free Memory(%u) segment found at (0x%lx,0x%lx).\n\r",
+ current->Type, start, end);
+#endif
+
+ /* Leave some space for our stack */
+ if ((stack >= start) && (stack < end))
+ end =
+ (stack -
+ (STACK_PAGES *
+ PAGE_SIZE)) & ~(PAGE_SIZE - 1);
+ /* Don't use memory from reserved region */
+ if ((start >= kernel_load[SUBARCH].base )
+ && (start < (kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved )))
+ start = kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved;
+ if ((end > kernel_load[SUBARCH].base)
+ && (end <= (kernel_load[SUBARCH].base
+ + kernel_load[SUBARCH].reserved )))
+ end = kernel_load[SUBARCH].base;
+ if (end > start) {
+#ifdef DEBUG
+ printf("Adding %lu bytes at 0x%lx to the list of available memory\n\r",
+ end-start, start);
+#endif
+ arclib_malloc_add(start, end - start);
+ }
+ }
+ current = ArcGetMemoryDescriptor(current);
+ }
+}
+
+/* convert an offset in the kernel image to an address in the loaded tftpboot image */
+static void* offset2addr(unsigned long offset)
+{
+ void* address = (void*)((ULONG)&(__kernel_start) + offset);
+ return address;
+}
+
+/* copy program segments to the locations the kernel expects */
+static ULONG CopyProgramSegments32(Elf32_Ehdr * header)
+{
+ int idx;
+ Boolean loaded = False;
+ Elf32_Phdr *segment, *segments;
+ size_t size = header->e_phentsize * header->e_phnum;
+ ULONG kernel_end=0L;
+
+ if (size <= 0)
+ Fatal("No program segments\n\r");
+
+ segments = malloc(size);
+ if (segments == NULL)
+ Fatal("Cannot allocate memory for segment headers\n\r");
+
+ segments = (Elf32_Phdr*)offset2addr(header->e_phoff);
+
+ segment = segments;
+ for (idx = 0; idx < header->e_phnum; idx++) {
+ if (segment->p_type == PT_LOAD) {
+ printf
+ ("Loading program segment %u at 0x%x, size = 0x%x\n\r",
+ idx + 1, KSEG0ADDR(segment->p_vaddr), segment->p_filesz);
+
+ memcpy((void *)segment->p_vaddr, offset2addr(segment->p_offset), segment->p_filesz);
+ /* determine the highest address used by the kernel's memory image */
+ if( kernel_end < segment->p_vaddr + segment->p_memsz ) {
+ kernel_end = segment->p_vaddr + segment->p_memsz;
+ }
+
+ size = segment->p_memsz - segment->p_filesz;
+ if (size > 0) {
+ printf
+ ("Zeroing memory at 0x%x, size = 0x%x\n\r",
+ (KSEG0ADDR(segment->p_vaddr +
+ segment->p_filesz)), size);
+ memset((void *)
+ (KSEG0ADDR(segment->
+ p_vaddr + segment->p_filesz)), 0, size);
+ }
+ loaded = True;
+ }
+ segment =
+ (Elf32_Phdr *) (((char *) segment) +
+ header->e_phentsize);
+ }
+
+ if (!loaded)
+ Fatal("No loadable program segments found\n\r");
+
+ free(segments);
+ return kernel_end;
+}
+
+static ULONG CopyProgramSegments64(Elf64_Ehdr * header)
+{
+ int idx;
+ Boolean loaded = False;
+ Elf64_Phdr *segment, *segments;
+ size_t size = header->e_phentsize * header->e_phnum;
+ ULONG kernel_end=0L;
+
+ if (size <= 0)
+ Fatal("No program segments\n\r");
+
+ segments = malloc(size);
+ if (segments == NULL)
+ Fatal("Cannot allocate memory for segment headers\n\r");
+
+ segments = (Elf64_Phdr*)offset2addr(header->e_phoff);
+
+ segment = segments;
+ for (idx = 0; idx < header->e_phnum; idx++) {
+ if (segment->p_type == PT_LOAD) {
+ printf("Loading program segment %u at 0x%x, size = 0x%llx\n\r",
+ idx + 1, KSEG0ADDR(segment->p_vaddr), segment->p_filesz);
+
+ memcpy((void *)(long)(segment->p_vaddr), offset2addr(segment->p_offset), segment->p_filesz);
+ /* determine the highest address used by the kernel's memory image */
+ if( kernel_end < segment->p_vaddr + segment->p_memsz ) {
+ kernel_end = segment->p_vaddr + segment->p_memsz;
+ }
+
+ size = segment->p_memsz - segment->p_filesz;
+ if (size > 0) {
+ printf
+ ("Zeroing memory at 0x%x, size = 0x%x\n\r",
+ (KSEG0ADDR(segment->p_vaddr +
+ segment->p_filesz)), size);
+ memset((void *)
+ (KSEG0ADDR(segment->
+ p_vaddr + segment->p_filesz)), 0, size);
+ }
+ loaded = True;
+ }
+ segment =
+ (Elf64_Phdr *) (((char *) segment) +
+ header->e_phentsize);
+ }
+
+ if (!loaded)
+ Fatal("No loadable program segments found\n\r");
+
+ free(segments);
+ return kernel_end;
+}
+
+static ULONG CopyKernel(ULONG* kernel_end)
+{
+ Elf32_Ehdr *header = (Elf32_Ehdr*)offset2addr(0L);
+ Elf64_Ehdr *header64 = (Elf64_Ehdr*)header;
+
+ if (memcmp(&(header->e_ident[EI_MAG0]), ELFMAG, SELFMAG) != 0)
+ Fatal("Not an ELF file\n\r");
+
+ if (header->e_ident[EI_CLASS] == ELFCLASS32) {
+ if (header->e_ident[EI_DATA] != ELFDATA2MSB)
+ Fatal("Not a big-endian file\n\r");
+ if (header->e_ident[EI_VERSION] != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+ if (header->e_type != ET_EXEC)
+ Fatal("Not an executable file\n\r");
+ if (header->e_machine != EM_MIPS)
+ Fatal("Unsupported machine type\n\r");
+ if (header->e_version != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+
+ (*kernel_end) = CopyProgramSegments32(header);
+
+ printf("Starting kernel; entry point = 0x%lx\n\r",
+ ((ULONG) KSEG0ADDR(header->e_entry)));
+ return KSEG0ADDR(header->e_entry);
+ } else if (header->e_ident[EI_CLASS] == ELFCLASS64) {
+ if (header64->e_ident[EI_DATA] != ELFDATA2MSB)
+ Fatal("Not a big-endian file\n\r");
+ if (header64->e_ident[EI_VERSION] != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+ if (header64->e_type != ET_EXEC)
+ Fatal("Not an executable file\n\r");
+ if (header64->e_machine != EM_MIPS)
+ Fatal("Unsupported machine type\n\r");
+ if (header64->e_version != EV_CURRENT)
+ Fatal("Wrong ELF version\n\r");
+
+ (*kernel_end) = CopyProgramSegments64(header64);
+
+ printf("Starting kernel; entry point = 0x%lx\n\r",
+ ((ULONG) KSEG0ADDR(header64->e_entry)));
+ return KSEG0ADDR(header64->e_entry);
+ } else
+ Fatal("Neither an ELF32 nor an ELF64 kernel\n\r");
+
+ return 0L;
+}
+
+static void copyRamdisk(void* rd_vaddr, void* rd_start, ULONG rd_size)
+{
+ memcpy(rd_vaddr, rd_start, rd_size);
+ printf("Copied initrd from 0x%p to 0x%p (0x%lx bytes)\n\r",
+ rd_start, rd_vaddr, rd_size);
+}
+
+void _start(LONG argc, CHAR * argv[], CHAR * envp[])
+{
+ char* nargv[3];
+ int nargc,i;
+ char argv_rd[128]; /* passed to the kernel on its commandline */
+ ULONG kernel_end = 0L;
+ ULONG rd_size= ((char*)&__rd_end) - ((char*)&__rd_start);
+ char* rd_vaddr=NULL;
+ void (*kernel_entry)(int argc, CHAR * argv[], CHAR * envp[]);
+
+ /* Print identification */
+#if (SUBARCH == IP22)
+ printf(ANSI_CLEAR "\n\rtip22: IP22 Linux tftpboot loader " __ARCSBOOT_VERSION__ "\n\r");
+#elif (SUBARCH == IP32)
+ printf(ANSI_CLEAR "\n\rtip32: IP32 Linux tftpboot loader " __ARCSBOOT_VERSION__ "\n\r");
+#endif
+
+ InitMalloc();
+
+ /* copy the kernel to its load address */
+#ifdef DEBUG
+ printf("Embedded kernel image starts 0x%p, ends 0x%p\n\r",
+ &__kernel_start, &__kernel_end);
+ printf("Embedded ramdisk image starts 0x%p, ends 0x%p\n\r",
+ &__rd_start, &__rd_end);
+#endif
+ kernel_entry = (void (*)(int, CHAR *[], CHAR *[]))CopyKernel(&kernel_end);
+
+ /* align to page boundary */
+ rd_vaddr = (char*)(((kernel_end + PAGE_SIZE) / PAGE_SIZE ) * PAGE_SIZE);
+ copyRamdisk( rd_vaddr, (char*)&__rd_start, rd_size);
+
+ /* tell the kernel about the ramdisk */
+ sprintf(argv_rd, "rd_start=0x%p rd_size=0x%lx", rd_vaddr, rd_size);
+
+ nargv[0] = argv[0];
+ nargv[1] = argv_rd;
+ nargc=2;
+ for(i=1; i < argc; i++) {
+ if( !memcmp(argv[i],"append=",7) )
+ break;
+ }
+ if( i < argc ) { /* we're asked to pass s.th. to the kernel */
+ nargv[2] = argv[i]+7;
+ nargc++;
+ }
+
+#ifdef DEBUG
+ printf("Arguments passed to kernel:\n\r");
+ for(i = 0; i < nargc; i++ )
+ printf("%u: %s\n\r", i, nargv[i]);
+ Wait("\n\r--- Debug: press <spacebar> to boot kernel ---");
+#endif
+ /* Finally jump into the kernel */
+ ArcFlushAllCaches();
+ if( kernel_entry )
+ (*kernel_entry)(nargc ,nargv, envp);
+ else
+ printf("Invalid kernel entry NULL\n\r");
+
+ /* Not likely to get back here in a functional state,
+ * but what the heck */
+ Wait("\n\r--- Press <spacebar> to restart ---");
+ ArcRestart();
+}
diff --git a/tip22/tip22 b/tip22/tip22
new file mode 100644
index 0000000..86a5eb9
--- /dev/null
+++ b/tip22/tip22
@@ -0,0 +1,51 @@
+#! /bin/sh -e
+#
+# Merges kernel and ramdisk into one ECOFF bootimage
+
+SUBARCH=IP22
+
+LIBDIR=/usr/lib/tip22
+TIP22=$LIBDIR/tftpload.$SUBARCH.o
+ARCLIB=$LIBDIR/libarc.a
+LD_KERNEL=$LIBDIR/ld.kernel.script.$SUBARCH
+LD_RAMDISK=$LIBDIR/ld.ramdisk.script.$SUBARCH
+LD_SCRIPT=$LIBDIR/ld.script.$SUBARCH
+LDFLAGS="-N"
+LD=/usr/bin/ld
+MKTEMP=/bin/mktemp
+
+usage() {
+ echo "`basename $0` vmlinux initrd outfile"
+ exit 1
+}
+
+if [ "$#" != "3" ]; then
+ usage
+fi
+
+if ! file $2 | grep 'gzip compressed data' > /dev/null 2>&1; then
+ echo "$2 is no gzip compressed ramdisk".
+ usage
+fi
+
+if ! file $1 | grep 'ELF .* MIPS' > /dev/null 2>&1; then
+ echo "$1 is no ELF kernel".
+ usage
+fi
+
+if [ ! -x $MKTEMP ]; then
+ echo "Need mktemp."
+ exit 1
+fi
+
+if ! TMPDIR=`mktemp -d`; then
+ echo "mktemp failed."
+ exit 1
+fi
+
+echo -n "Merging kernel \"$1\" and ramdisk \"$2\" into bootimage \"$3\"..."
+${LD} -T $LD_KERNEL -b binary -o $TMPDIR/kernel.o $1
+${LD} -T $LD_RAMDISK -b binary -o $TMPDIR/ramdisk.o $2
+${LD} -T $LD_SCRIPT ${LDFLAGS} -o $3 ${TIP22} ${ARCLIB} $TMPDIR/kernel.o $TMPDIR/ramdisk.o
+rm -rf $TMPDIR
+echo "done."
diff --git a/tip22/tip32 b/tip22/tip32
new file mode 100755
index 0000000..0e91bb2
--- /dev/null
+++ b/tip22/tip32
@@ -0,0 +1,51 @@
+#! /bin/sh -e
+#
+# Merges kernel and ramdisk into one ELF bootimage
+
+SUBARCH=IP32
+
+LIBDIR=/usr/lib/tip22
+TIP22=$LIBDIR/tftpload.$SUBARCH.o
+ARCLIB=$LIBDIR/libarc.a
+LD_KERNEL=$LIBDIR/ld.kernel.script.$SUBARCH
+LD_RAMDISK=$LIBDIR/ld.ramdisk.script.$SUBARCH
+LD_SCRIPT=$LIBDIR/ld.script.$SUBARCH
+LDFLAGS="-n"
+LD=/usr/bin/ld
+MKTEMP=/bin/mktemp
+
+usage() {
+ echo "`basename $0` vmlinux initrd outfile"
+ exit 1
+}
+
+if [ "$#" != "3" ]; then
+ usage
+fi
+
+if ! file $2 | grep 'gzip compressed data' > /dev/null 2>&1; then
+ echo "$2 is no gzip compressed ramdisk".
+ usage
+fi
+
+if ! file $1 | grep 'ELF .* MIPS' > /dev/null 2>&1; then
+ echo "$1 is no ELF kernel".
+ usage
+fi
+
+if [ ! -x $MKTEMP ]; then
+ echo "Need mktemp."
+ exit 1
+fi
+
+if ! TMPDIR=`mktemp -d`; then
+ echo "mktemp failed."
+ exit 1
+fi
+
+echo -n "Merging kernel \"$1\" and ramdisk \"$2\" into bootimage \"$3\"..."
+${LD} -T $LD_KERNEL -b binary -o $TMPDIR/kernel.o $1
+${LD} -T $LD_RAMDISK -b binary -o $TMPDIR/ramdisk.o $2
+${LD} -T $LD_SCRIPT ${LDFLAGS} -o $3 ${TIP22} ${ARCLIB} $TMPDIR/kernel.o $TMPDIR/ramdisk.o
+rm -rf $TMPDIR
+echo "done."