diff --git a/Makefile b/Makefile index 74cb99d..b14859d 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,8 @@ TEXTADDR=0x80008000 ifndef CROSS_COMPILE CROSS_COMPILE=mips-elf- endif +CFLAGS=-DDEBUG -mno-abicalls +LDFLAGS=-Ttext ${TEXTADDR} # Configuration for the Cisco 3660 Routers # TARGET=c3600 @@ -15,15 +17,16 @@ endif # endif # Configuration for the Cisco 1700 Series Routers -# TARGET=c1700 -# MACHINE=0x33 -# TEXTADDR=0x80008000 -# ifndef CROSS_COMPILE -# CROSS_COMPILE=powerpc-elf- -# endif +#TARGET=c1700 +#MACHCODE=0x33 +#TEXTADDR=0x80008000 +#ifndef CROSS_COMPILE +#CROSS_COMPILE=powerpc-elf- +#endif +#LDFLAGS=-Ttext=${TEXTADDR} # additional CFLAGS -CFLAGS= +CFLAGS+= # don't modify anything below here # =================================================================== @@ -42,13 +45,13 @@ RAW=${OBJCOPY} --strip-unneeded --alt-machine-code ${MACHCODE} INCLUDE=-Iinclude/ -Imach/${TARGET} -Iinclude/mach/${TARGET} -CFLAGS+=-fno-builtin -fomit-frame-pointer -fno-pic -mno-abicalls \ +CFLAGS+=-fno-builtin -fomit-frame-pointer -fno-pic \ -Wall ASFLAGS=-D__ASSEMBLY__-xassembler-with-cpp -traditional-cpp -LDFLAGS=--omagic -nostartfiles -nostdlib --discard-all --strip-all \ - -Ttext ${TEXTADDR} --entry _start +LDFLAGS+=--omagic -nostartfiles -nostdlib --discard-all --strip-all \ + --entry _start OBJECTS=string.o main.o ciloio.o printf.o elf_loader.o @@ -75,13 +78,11 @@ 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 diff --git a/README b/README index fe58682..10abc3b 100644 --- a/README +++ b/README @@ -22,23 +22,18 @@ target architecture is mips-elf and not mips-unknown-linux-gnu), just go to the root directory of the source distribution and type make. Everything should build from there. -Next, build the second stage bootloader by going to the second/ directory -and typing make. - -Copy the ciscoload.bin and ciscoload.two files to the router's flash along -with your kernel and set the router boot image to be ciscoload.bin. +Copy the ciscoload.bin file to the router's flash along with your kernel and +set the router boot image to be ciscoload.bin. 4. How do I use CILO? Assuming you have one of the supported routers, it is really quite easy. -In short, you must build CiscoLoad, build the stage-two loader and copy -them to your device's flash, typically using IOS. +In short, you must build CiscoLoad and a kernel then copy them to your +device's flash, typically using IOS. 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/elf2mzip/elf2img.c b/elf2mzip/elf2img.c index a7873d7..03806be 100644 --- a/elf2mzip/elf2img.c +++ b/elf2mzip/elf2img.c @@ -19,10 +19,11 @@ void usage(const char *s) { - printf("usage: %s [-m] [elffile] [outfile]\n", s); + printf("usage: %s [-m] [elffile] [outfile] [descrfile]\n", s); printf("\t-m Generates an MZIP image\n"); printf("\t[elffile] Input ELF file\n"); printf("\t[outfile] Output image\n"); + printf("\t[descrfile] file containing textual description of image\n"); printf("The parameters of the format to be converted to are determined " "based\non the structure of the input ELF file.\n\n"); } @@ -64,14 +65,15 @@ int main(const int argc, const char *argv[]) struct elf32_phdr *phdr; int i; char swap = 0; - const char *file_in = argv[argc - 2]; - const char *file_out = argv[argc - 1]; + const char *file_in = argv[argc - 3]; + const char *file_out = argv[argc - 2]; + const char *file_desc = argv[argc - 1]; char mzip = 0; printf("elf2img - Cisco Router Image Generation Utility.\n"); printf("(c) 2009 Philippe Vachon \n\n"); - if (argc < 2) { + if (argc < 3) { printf("Insufficient arguments.\n"); USAGE; return -1; @@ -240,14 +242,44 @@ int main(const int argc, const char *argv[]) mz.hdr_crc_header = swap ? SWAP_16(crc) : crc; mzip_print_header(&mz); + + /* read in the description file */ + FILE *fp_desc = fopen(file_desc, "r"); + if (!fp_desc) { + printf("Unable to open description file.\n"); + USAGE; + goto quit; + } + + fseek(fp_desc, 0, SEEK_END); + uint32_t desc_len = ftell(fp_desc); + + char *desc_buf = (char *)malloc(desc_len); + if (desc_buf == NULL) { + printf("Error while allocating memory for description buffer.\n"); + goto quit; + } + + rewind(fp_desc); + fread(desc_buf, desc_len, 1, fp_desc); + + fclose(fp_desc); + + printf("Descriptor:\n%s", desc_buf); /* write out the MZIP file */ mzip_write_header(fp_out, &mz); mzip_write_codeseg(fp_out, zip_buf, seg_size); + fseek(fp_out, 0, SEEK_END); + + fwrite(desc_buf, desc_len, 1, fp_out); + +quit: if (zip_buf) free(zip_buf); free(phdr); + free(desc_buf); fclose(fp_in); fclose(fp_out); return 0; diff --git a/elf_loader.c b/elf_loader.c index d0c33f5..37d001f 100644 --- a/elf_loader.c +++ b/elf_loader.c @@ -63,10 +63,9 @@ void load_elf32_uninitialized_memory(uint32_t address, uint32_t length) * @param loader_addr address of the loader binary in memory * @return */ -int load_elf32_file(struct file *fp) +int load_elf32_file(struct file *fp, char *cmd_line) { struct elf32_header hdr; - uint32_t mem_sz = 0; /* read in header entries */ @@ -110,21 +109,6 @@ int load_elf32_file(struct file *fp) uint32_t offset = 0xffffffff; cilo_seek(fp, hdr.phoff, SEEK_SET); - /* read in program header(s), determine total memory size of image */ - /* TODO: figure out if there's a better way to determine this */ - for (i = 0; i < hdr.phnum; i++) { - cilo_read(&phdr, sizeof(struct elf32_phdr), 1, fp); - - if (phdr.type != ELF_PT_LOAD) continue; - - mem_sz += phdr.memsz; - - if (phdr.paddr < offset) offset = phdr.paddr; - } - -#ifdef DEBUG - printf("mem_sz = %08x\n", mem_sz); -#endif /* read the PT_LOAD segments into memory at paddr + mem_sz */ cilo_seek(fp, hdr.phoff, SEEK_SET); @@ -134,35 +118,32 @@ int load_elf32_file(struct file *fp) /* skip unloadable segments */ if (phdr.type != ELF_PT_LOAD) continue; - /* uint32_t leftover = phdr.memsz - phdr.filesz; */ - load_elf32_section(fp, mem_sz + phdr.paddr, + load_elf32_section(fp, phdr.paddr, phdr.offset, phdr.filesz); -/* if (leftover > 0) { - load_elf32_uninitialized_memory(mem_sz + phdr.paddr + - phdr.filesz, leftover); - } */ + mem_sz += phdr.memsz; + + if (phdr.memsz - phdr.filesz > 0) { + load_elf32_uninitialized_memory(phdr.paddr + + phdr.filesz, phdr.memsz - phdr.filesz); + } cilo_seek(fp, hdr.phoff + sizeof(struct elf32_phdr) * (i + 1), SEEK_SET); } /* assume the entry point is the smallest address we're loading */ - uint32_t load_offset = mem_sz + offset; - - printf("Loaded %d bytes at %08x.\n", mem_sz, load_offset); + printf("Loaded %d bytes.\n", mem_sz); printf("Kicking into Linux.\n"); #ifdef DEBUG - printf("load_offset = 0x%08x\n", load_offset); printf("hdr.entry = 0x%08x\n", hdr.entry); printf("mem_sz = 0x%08x\n", mem_sz); - printf("offset = 0x%08x\n", offset); #endif - /* Jump to the copy routine */ - stage_two(load_offset, hdr.entry, mem_sz, offset); + ((void (*)(uint32_t mem_sz, char *cmd_line))(hdr.entry)) + (c_memsz(), cmd_line); return -1; /* something failed, badly */ } diff --git a/include/elf_loader.h b/include/elf_loader.h index 12eed42..fd6fedb 100644 --- a/include/elf_loader.h +++ b/include/elf_loader.h @@ -7,6 +7,6 @@ void load_elf32_section(struct file *fp, uint32_t address, uint32_t file_offset, uint32_t length); void load_elf32_uninitialized_memory(uint32_t address, uint32_t length); -int load_elf32_file(struct file *fp); +int load_elf32_file(struct file *fp, char *cmd_line); #endif /* _ELF_LOADER_H */ diff --git a/include/mach/c3600/platform.h b/include/mach/c3600/platform.h index af0b338..1f9eb0f 100644 --- a/include/mach/c3600/platform.h +++ b/include/mach/c3600/platform.h @@ -10,8 +10,5 @@ void platform_init(); uint32_t check_flash(); void flash_directory(); -uint32_t locate_stage_two(); -void stage_two(uint32_t kern_off, uint32_t kern_entry, uint32_t kern_size, - uint32_t kern_loadpt); #endif /* _INCLUDE_MACH_C3600_PLATFORM_H */ diff --git a/mach/c3600/platform.c b/mach/c3600/platform.c index 5ebb2e0..85dcf3c 100644 --- a/mach/c3600/platform.c +++ b/mach/c3600/platform.c @@ -42,28 +42,3 @@ void flash_directory() f = (struct fs_ent *)(FLASH_BASE + offset); } } - -/** - * Locate the stage two loader for CiscoLoad for this particular platform - * returns 0 if not found, 1 if found - */ -uint32_t locate_stage_two() -{ - return platio_find_file("ciscoload.two"); -} - -/** - * Kick into the stage two loader. - */ -void stage_two(uint32_t kern_off, uint32_t kern_entry, uint32_t kern_size, - uint32_t kern_loadpt) -{ - uint32_t s2addr = ((uint32_t)find_file("ciscoload.two", FLASH_BASE)) + - sizeof(struct fs_ent); - - - ((void (*)(uint32_t data_offset, uint32_t data_length, uint32_t entry_pt, - uint32_t load_offset)) (s2addr)) - (kern_off, kern_size, kern_entry, kern_loadpt); - -} diff --git a/main.c b/main.c index 3a2933b..e2f43db 100644 --- a/main.c +++ b/main.c @@ -71,13 +71,6 @@ void start_bootloader() c_putc('O'); platform_init(); - /* locate the stage two loader */ - if (!locate_stage_two()) { - printf("\nError: Unable to find valid stage two loader. " - "Aborting load.\n"); - return; - } - printf("\nCiscoLoader (CILO) - Linux bootloader for Cisco Routers\n"); printf("Available RAM: %d kB\n", r); @@ -121,7 +114,7 @@ enter_filename: printf("DEBUG: cmd_line: %s\n", cmd_line); #endif printf("Booting %s.\n", kernel); - if (load_elf32_file(&kernel_file) + if (load_elf32_file(&kernel_file, cmd_line) < 0) { printf("Fatal error while loading kernel. Aborting.\n");