diff --git a/Makefile b/Makefile index ce58a7e..e1597af 100644 --- a/Makefile +++ b/Makefile @@ -35,10 +35,12 @@ AR=$(CROSS_COMPILE)ar LD=$(CROSS_COMPILE)ld OBJCOPY=$(CROSS_COMPILE)objcopy +MACHDIR=mach/$(TARGET) + # command to prepare a binary RAW=${OBJCOPY} --strip-unneeded --alt-machine-code ${MACHCODE} -INCLUDE=-Iinclude/ -Imach/${TARGET} +INCLUDE=-Iinclude/ -Imach/${TARGET} -Iinclude/mach/${TARGET} CFLAGS=$(INCLUDE) -fno-builtin -fomit-frame-pointer -fno-pic -mno-abicalls \ -Wall @@ -48,12 +50,18 @@ ASFLAGS=-xassembler-with-cpp -traditional-cpp LDFLAGS=--omagic -nostartfiles -nostdlib --discard-all --strip-all \ -Ttext ${TEXTADDR} --entry _start -OBJECTS=start.o main.o printf.o promlib.o elf_loader.o +OBJECTS=main.o printf.o elf_loader.o + +LINKOBJ=${OBJECTS} $(MACHDIR)/promlib.o $(MACHDIR)/start.o #$(MACHDIR)/platform.o + + +THISFLAGS='LDFLAGS=$(LDFLAGS)' 'ASFLAGS=$(ASFLAGS)' \ + 'CROSS_COMPILE=$(CROSS_COMPILE)' 'CFLAGS=$(CFLAGS)' 'CC=$(CC)' all: ${OBJECTS} ${PROG} -${PROG}: ${OBJECTS} - ${CC} ${LDFLAGS} ${OBJECTS} -o ${PROG}.elf +${PROG}: sub ${OBJECTS} + ${CC} ${LDFLAGS} ${LINKOBJ} -o ${PROG}.elf ${RAW} ${PROG}.elf ${PROG}.bin .c.o: @@ -61,8 +69,20 @@ ${PROG}: ${OBJECTS} .S.o: ${CC} ${CFLAGS} ${ASFLAGS} -c $< - -clean: - -rm *.o - -rm ${PROG}.elf - -rm ${PROG}.bin + +sub: + @for i in $(MACHDIR); do \ + echo "Making all in $$i..."; \ + (cd $$i; $(MAKE) $(MFLAGS) $(THISFLAGS) all); done + (cd second/; $(MAKE) $(MFLAGS)) + +subclean: + @for i in $(MACHDIR); do \ + echo "Cleaning all in $$i..."; \ + (cd $$i; $(MAKE) $(MFLAGS) clean); done + (cd second/; $(MAKE) $(MFLAGS) clean) + +clean: subclean + -rm -f *.o + -rm -f ${PROG}.elf + -rm -f ${PROG}.bin diff --git a/README b/README index e351758..fe58682 100644 --- a/README +++ b/README @@ -37,6 +37,8 @@ When the router boots, it will load CILO; CILO then will prompt you to select the file you want to boot. Enter the file name you wish to boot, and away you go! +Of course, it makes sense to put your kernel on your flash device as well. + 5. What hardware is supported? At this time, the Cisco 3600 Series of routers (3620 and 3640 at least) are very well supported. As well, preliminary support is underway for the diff --git a/elf_loader.c b/elf_loader.c index 7ff8858..83c8ce5 100644 --- a/elf_loader.c +++ b/elf_loader.c @@ -2,6 +2,9 @@ #include #include +/* platform-specific defines */ +#include + void read(void *ptr, uint32_t size, uint32_t count, uint32_t base, uint32_t offset); @@ -19,12 +22,8 @@ void load_elf32_section(uint32_t base, uint32_t address, { uint8_t *elf_loc = (uint8_t *)address; - printf("read(%08x, %08x, 1, %08x, %08x);\n", - address, length, base, file_offset); - read(elf_loc, length, 1, base, file_offset); - printf("Read %d bytes into memory at location %#8x.\n", length, address); } /** @@ -40,8 +39,6 @@ void load_elf32_uninitialized_memory(uint32_t address, uint32_t length) for (i = 0; i < length; i++) { p[i] = 0; } - printf("Created uninitialized data section of %d bytes at %#8x.\n", i, - address); } /** @@ -147,11 +144,11 @@ int load_elf32_file(uint32_t base, uint32_t loader_addr) if (phdr.type != ELF_PT_LOAD) continue; uint32_t leftover = phdr.memsz - phdr.filesz; - load_elf32_section(base, mem_sz + hdr.entry + phdr.paddr, + load_elf32_section(base, mem_sz + phdr.paddr, phdr.offset, phdr.filesz); if (leftover > 0) { - load_elf32_uninitialized_memory(mem_sz + hdr.entry + phdr.paddr + + load_elf32_uninitialized_memory(mem_sz + phdr.paddr + phdr.filesz, leftover); } } @@ -161,66 +158,13 @@ int load_elf32_file(uint32_t base, uint32_t loader_addr) printf("Loaded %d bytes at %08x.\n", mem_sz, load_offset); - /* struct elf32_section_header shdr; */ - - /* read in section headers, load sections */ -#if 0 - uint32_t sh_offset = hdr.shoff; - for (i = 0; i < hdr.shnum; i++) { - printf("reading: base: %08x, sh_offset: %08x\n", base, sh_offset); - read(&shdr, sizeof(struct elf32_section_header), 1, base, sh_offset); - - printf("\n\nJust read section header %d\n", i); - - printf("\tName: %u\n", shdr.name); - printf("\tType: %#8x: %s\n", shdr.type, sh_type_to_string(shdr.type)); - printf("\tFlags: %#8x\n", shdr.flags); - printf("\t\t%c%c%c\n", ELF_SHF_ALLOCD(shdr.flags) ? 'A' : '-', - ELF_SHF_WRITABLE(shdr.flags) ? 'w' : '-', - ELF_SHF_EXECUTABLE(shdr.flags) ? 'x' : '-'); - printf("\tAddress: %#8x\n", shdr.addr); - printf("\tOffset: %u bytes\n", shdr.offset); - printf("\tSize: %u bytes\n", shdr.size); - printf("\tLink: %#8x\n", shdr.link); - printf("\tAdditional Info: %#8x\n", shdr.info); - printf("\tAddress Alignment: %#8x\n", shdr.addralign); - printf("\tPer-Entry Size: %u bytes\n\n", shdr.entsize); - - if (!ELF_SHF_ALLOCD(shdr.flags)) { - sh_offset += sizeof(struct elf32_section_header); - continue; - } - - printf("Param: base: %08x addr: %08x offset: %08x size: %08x\n", - base, shdr.addr, shdr.offset, shdr.size); - - /* load section */ - switch (shdr.type) { - case ELF_SHT_NULL: /* no data to be loaded */ - break; - case ELF_SHT_NOBITS: - /* zero out this data */ - load_elf32_uninitialized_memory(shdr.addr + mem_sz, - shdr.size); - break; - case ELF_SHT_PROGBITS: - /* program bits and such */ - load_elf32_section(base, shdr.addr + mem_sz, shdr.offset, - shdr.size); - break; - default: - printf("WARNING: Section type %08x cannot be loaded by " - "CiscoLoad.\n", shdr.type); - } - - sh_offset += sizeof(struct elf32_section_header); - } -#endif - printf("Kicking into Linux.\n"); + +#ifdef DEBUG printf("bootcpy: %08x, kdataoffset: %08x, kdatalength: %08x\n", loader_addr, load_offset, mem_sz); printf("kentrypt: %08x, kloadoffset: %08x\n", hdr.entry, hdr.entry); +#endif /* Jump to the copy routine */ asm (".set noreorder\n" diff --git a/elftool/Makefile b/elftool/Makefile index 798e137..01ca676 100644 --- a/elftool/Makefile +++ b/elftool/Makefile @@ -12,5 +12,5 @@ elftool: $(OBJECTS) gcc $(CFLAGS) -c $< clean: - rm *.o - rm $(PROG) + -rm -f *.o + -rm -f $(PROG) diff --git a/include/mach/c3600/platform.h b/include/mach/c3600/platform.h new file mode 100644 index 0000000..478cacd --- /dev/null +++ b/include/mach/c3600/platform.h @@ -0,0 +1,8 @@ +#ifndef _INCLUDE_MACH_C3600_PLATFORM_H +#define _INCLUDE_MACH_C3600_PLATFORM_H + +#define FLASH_BASE 0x30000000 +#define KERNEL_ENTRY_POINT 0x80008000 +#define MEMORY_BASE 0x80000000 + +#endif /* _INCLUDE_MACH_C3600_PLATFORM_H */ diff --git a/include/string.h b/include/string.h index 33bc707..7531f4c 100644 --- a/include/string.h +++ b/include/string.h @@ -88,4 +88,20 @@ inline int memcpy(void *dst, const void *src, int n) return i; } +/** + * strchr + */ +inline const char *strchr(const char *s, int c) +{ + const char *ptr = s; + + while (*ptr != '\0') { + if (*(ptr++) == (char)c) { + return ptr; + } + } + + return NULL; +} + #endif /* _STRING_H */ diff --git a/mach/README b/mach/README new file mode 100644 index 0000000..9b37222 --- /dev/null +++ b/mach/README @@ -0,0 +1,2 @@ +The mach/ directory contains platform-specific defines for CiscoLoad. + diff --git a/mach/c3600/Makefile b/mach/c3600/Makefile new file mode 100644 index 0000000..c66b221 --- /dev/null +++ b/mach/c3600/Makefile @@ -0,0 +1,18 @@ +ifndef CROSS_COMPILE +CROSS_COMPILE=mips-elf- +endif + +OBJECTS=start.o promlib.o + +INCLUDE=-I../../include + +all: ${OBJECTS} + +.c.o: + $(CC) ${CFLAGS} ${INCLUDE} -c $< + +.S.o: + $(CC) ${CFLAGS} ${INCLUDE} ${ASFLAGS} -c $< + +clean: + -rm -f *.o diff --git a/mach/c3600/platform.c b/mach/c3600/platform.c new file mode 100644 index 0000000..e69de29 diff --git a/promlib.c b/mach/c3600/promlib.c similarity index 100% rename from promlib.c rename to mach/c3600/promlib.c diff --git a/start.S b/mach/c3600/start.S similarity index 100% rename from start.S rename to mach/c3600/start.S diff --git a/main.c b/main.c index 837b41f..f99b756 100644 --- a/main.c +++ b/main.c @@ -2,18 +2,15 @@ * (c) 2008 Philippe Vachon * Licensed under the GNU General Public License v2 */ -#include #include #include #include #include #include +#include -/** - * Todo: Add these to platform-specific header - */ -#define FLASH_BASE 0x30000000 -#define KERNEL_ENTRY_POINT 0x80008000 +/* platform-specific defines */ +#include #define FS_FILE_MAGIC 0xbad00b1e @@ -133,7 +130,10 @@ void start_bootloader() { int r = 0; int f; - char buf[48]; + char buf[129]; + char *cmd_line = (char *)MEMORY_BASE; + + buf[128] = '\0'; /* determine amount of RAM present */ c_putc('I'); @@ -164,8 +164,19 @@ void start_bootloader() printf("Available files:\n"); flash_directory(FLASH_BASE); + +enter_filename: printf("\nEnter filename to boot:\n> "); - c_gets(buf, 48); + c_gets(buf, 128); + + /* determine if a command line string has been appended to kernel name */ + const char *cmd_line_append; + if ((cmd_line_append = strchr(buf, ' ')) != NULL) { + strcpy(cmd_line, cmd_line_append); + } else { + cmd_line[0] = '\0'; + } + printf("\n\nAttempting to load file %s\n", buf); uint32_t kernel_off = find_file(buf, FLASH_BASE); @@ -182,12 +193,14 @@ void start_bootloader() } else { printf("Booting \"%s\" from flash at 0x%08x\n", buf, FLASH_BASE + kernel_off); + printf("DEBUG: cmd_line: %s\n", cmd_line); if (load_elf32_file(FLASH_BASE + kernel_off, FLASH_BASE + loader_off) < 0) { printf("Fatal error while loading kernel. Aborting.\n"); } } + goto enter_filename; /* return to ROMMON */ } diff --git a/second/kcopy.S b/second/kcopy.S index d49481d..c153891 100644 --- a/second/kcopy.S +++ b/second/kcopy.S @@ -25,7 +25,21 @@ LEAF(_start) bnez a1, 1b # continue copying addi a1, -4 # subtract from remaining bytes to copy - nop + nop + + /* put the stack pointer up at top of memory */ + li a0, 4 + syscall + nop + + li sp, 0x80000000 + add sp, sp, v0 + + move a0, v0 + li a1, 0x80000000 + li a3, 0 + li v0, 0 + jr a2 # jump to kernel entry point nop