diff --git a/Makefile b/Makefile index e1597af..e1ef689 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ RAW=${OBJCOPY} --strip-unneeded --alt-machine-code ${MACHCODE} INCLUDE=-Iinclude/ -Imach/${TARGET} -Iinclude/mach/${TARGET} -CFLAGS=$(INCLUDE) -fno-builtin -fomit-frame-pointer -fno-pic -mno-abicalls \ +CFLAGS=-fno-builtin -fomit-frame-pointer -fno-pic -mno-abicalls \ -Wall ASFLAGS=-xassembler-with-cpp -traditional-cpp @@ -50,9 +50,10 @@ ASFLAGS=-xassembler-with-cpp -traditional-cpp LDFLAGS=--omagic -nostartfiles -nostdlib --discard-all --strip-all \ -Ttext ${TEXTADDR} --entry _start -OBJECTS=main.o printf.o elf_loader.o +OBJECTS=string.o main.o ciloio.o printf.o elf_loader.o -LINKOBJ=${OBJECTS} $(MACHDIR)/promlib.o $(MACHDIR)/start.o #$(MACHDIR)/platform.o +LINKOBJ=${OBJECTS} $(MACHDIR)/promlib.o $(MACHDIR)/start.o $(MACHDIR)/platio.o\ + $(MACHDIR)/platform.o THISFLAGS='LDFLAGS=$(LDFLAGS)' 'ASFLAGS=$(ASFLAGS)' \ @@ -65,10 +66,10 @@ ${PROG}: sub ${OBJECTS} ${RAW} ${PROG}.elf ${PROG}.bin .c.o: - ${CC} ${CFLAGS} -c $< + ${CC} ${CFLAGS} $(INCLUDE) -c $< .S.o: - ${CC} ${CFLAGS} ${ASFLAGS} -c $< + ${CC} ${CFLAGS} $(INCLUDE) ${ASFLAGS} -c $< sub: @for i in $(MACHDIR); do \ diff --git a/ciloio.c b/ciloio.c new file mode 100644 index 0000000..f11c703 --- /dev/null +++ b/ciloio.c @@ -0,0 +1,48 @@ +/* (C) 2008 Philippe Vachon + * Licensed under the GNU General Public License v2 + */ + +#include +#include + +/* Platform-specific file I/O operations */ +#include + +struct file cilo_open(const char *filename) +{ + struct file fp; + if (!platio_find_file(filename)) { + fp.code = -1; + return fp; + } + + platio_file_open(&fp, filename); + + return fp; +} + +int32_t cilo_read(void *pbuf, uint32_t size, uint32_t nmemb, struct file *fp) +{ + return platio_read(pbuf, size, nmemb, fp); +} + +int32_t cilo_seek(struct file *fp, uint32_t offset, uint8_t whence) +{ + switch (whence) { + case SEEK_SET: + if (offset > fp->file_len) fp->file_pos = fp->file_len; + else fp->file_pos = offset; + break; + case SEEK_CUR: + if (offset + fp->file_pos > fp->file_len) fp->file_pos = fp->file_len; + else fp->file_pos += offset; + break; + case SEEK_END: + /* unimplemented */ + break; + default: + return 0; + } + + return 0; +} diff --git a/elf_loader.c b/elf_loader.c index 7a1f7f4..e10455a 100644 --- a/elf_loader.c +++ b/elf_loader.c @@ -1,14 +1,19 @@ +/** + * CILO Elf Loader + * (c) 2008 Philippe Vachoon + * + * Licensed under the GNU General Public License v2. See COPYING + * in the distribution source directory for more information. + */ #include #include #include +#include /* platform-specific defines */ #include -void read(void *ptr, uint32_t size, uint32_t count, uint32_t base, - uint32_t offset); - /** * load a single ELF section into memory at address. Assumes ELF data is * contiguous in memory. @@ -17,12 +22,12 @@ void read(void *ptr, uint32_t size, uint32_t count, uint32_t base, * @param file_offset offset (in bytes) in the ELF file where the section is * @param length Length of the section (in bytes) */ -void load_elf32_section(uint32_t base, uint32_t address, +void load_elf32_section(struct file *fp, uint32_t address, uint32_t file_offset, uint32_t length) { uint8_t *elf_loc = (uint8_t *)address; - - read(elf_loc, length, 1, base, file_offset); + cilo_seek(fp, file_offset, SEEK_SET); + cilo_read(elf_loc, length, 1, fp); } @@ -41,27 +46,6 @@ void load_elf32_uninitialized_memory(uint32_t address, uint32_t length) } } -/** - * Read data into a given pointer - * @param ptr Pointer to write data out to - * @param size Size of the data to be read - * @param count number of elements to read - * @param base base address to start read from - * @param offset offset from base to read from - */ -void read(void *ptr, uint32_t size, uint32_t count, uint32_t base, - uint32_t offset) -{ - uint8_t *data = (uint8_t *)ptr; - uint8_t *src = (uint8_t *)(base + offset); - int i; - - for (i = 0; i < size * count; i++) { - data[i] = src[i]; - } - -} - /** * Load an ELF file into memory from the given base. Loads at * offset + image_size so that a later memcpy routine can be used to copy @@ -70,14 +54,14 @@ void read(void *ptr, uint32_t size, uint32_t count, uint32_t base, * @param loader_addr address of the loader binary in memory * @return */ -int load_elf32_file(uint32_t base, uint32_t loader_addr) +int load_elf32_file(struct file *fp) { struct elf32_header hdr; uint32_t mem_sz = 0; /* read in header entries */ - read(&hdr, sizeof(struct elf32_header), 1, base, 0); + cilo_read(&hdr, sizeof(struct elf32_header), 1, fp); /* check the file magic */ if (hdr.ident[0] != ELF_MAGIC_1 || hdr.ident[1] != ELF_MAGIC_2 || @@ -121,36 +105,39 @@ int load_elf32_file(uint32_t base, uint32_t loader_addr) int i; struct elf32_phdr phdr; - uint32_t ph_offset = hdr.phoff; + 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++) { - read(&phdr, sizeof(struct elf32_phdr), 1, base, ph_offset); + cilo_read(&phdr, sizeof(struct elf32_phdr), 1, fp); mem_sz += phdr.memsz; - - /*increment program header offset */ - ph_offset += sizeof(struct elf32_phdr); } + printf("Total in-memory image size: %d\n", mem_sz); + /* read the PT_LOAD segments into memory at paddr + mem_sz */ - ph_offset = hdr.phoff; + cilo_seek(fp, hdr.phoff, SEEK_SET); for (i = 0; i < hdr.phnum; i++) { - read(&phdr, sizeof(struct elf32_phdr), 1, base, ph_offset); + cilo_read(&phdr, sizeof(struct elf32_phdr), 1, fp); /* skip unloadable segments */ if (phdr.type != ELF_PT_LOAD) continue; uint32_t leftover = phdr.memsz - phdr.filesz; - load_elf32_section(base, mem_sz + phdr.paddr, + printf("Loading section at %08x\n", phdr.paddr); + load_elf32_section(fp, mem_sz + phdr.paddr, phdr.offset, phdr.filesz); if (leftover > 0) { load_elf32_uninitialized_memory(mem_sz + phdr.paddr + phdr.filesz, leftover); } + + cilo_seek(fp, hdr.phoff + sizeof(struct elf32_phdr) * (i + 1), + SEEK_SET); } /* assume the entry point is the smallest address we're loading */ @@ -167,24 +154,10 @@ int load_elf32_file(uint32_t base, uint32_t loader_addr) #endif /* Jump to the copy routine */ -/* asm (".set noreorder\n" - "move $k0, %[bootcpy]\n" - "move $a0, %[kdataoffset]\n" - "move $a1, %[kdatalength]\n" - "move $a2, %[kentrypt]\n" - "move $a3, %[kloadoffset]\n" - "jr $k0\n" - " nop\n" - : - : [bootcpy] "r"(loader_addr), [kdataoffset] "r"(load_offset), - [kdatalength] "r"(mem_sz), [kentrypt]"r"(hdr.entry), - [kloadoffset] "r"(hdr.entry) - : "k0", "a0", "a1", "a2", "a3" - ); */ - - ((void (*)(uint32_t data_offset, uint32_t data_length, uint32_t entry_pt, + stage_two(load_offset, hdr.entry, mem_sz); +/* ((void (*)(uint32_t data_offset, uint32_t data_length, uint32_t entry_pt, uint32_t load_offset)) (loader_addr)) - (load_offset, mem_sz, hdr.entry, hdr.entry); + (load_offset, mem_sz, hdr.entry, hdr.entry); */ return -1; /* something failed, badly */ } diff --git a/elftool/elftool.c b/elftool/elftool.c index b6f824a..ffabd24 100644 --- a/elftool/elftool.c +++ b/elftool/elftool.c @@ -104,6 +104,9 @@ const char *machine_id_to_string(uint16_t machine) case 0x1e: return "Cisco 3620/40 Router (MIPS, IDT R4700, Big Endian)"; break; + case 0x24: + return "Cisco 12000 Series Router (MIPS/PowerPC, Big Endian)"; + break; case 0x2b: return "Cisco 2600 Series Router (PowerPC, MPC860, Big Endian)"; break; diff --git a/include/ciloio.h b/include/ciloio.h new file mode 100644 index 0000000..9fa6395 --- /dev/null +++ b/include/ciloio.h @@ -0,0 +1,27 @@ +#ifndef _INCLUDE_CILOIO_H +#define _INCLUDE_CILOIO_H + +#include + +struct file { + uint8_t dev; /* device ID number */ + uint32_t file_len; /* length of the file */ + uint32_t file_pos; /* position in the file */ + char filename[128]; + + int8_t code; /* error code */ + + void *private; /* private data for the platform specific flash handler */ +}; + +#define SEEK_SET 9 +#define SEEK_CUR 1 +#define SEEK_END 2 + +struct file cilo_open(const char *filename); +int32_t cilo_read(void *pbuf, uint32_t size, uint32_t nmemb, + struct file *fp); +int32_t cilo_seek(struct file *fp, uint32_t offset, uint8_t whence); +struct fs_ent *find_file(const char *filename, uint32_t base); + +#endif /* _INCLUDE_CILOIO_H */ diff --git a/include/elf_loader.h b/include/elf_loader.h index 85e651c..12eed42 100644 --- a/include/elf_loader.h +++ b/include/elf_loader.h @@ -2,10 +2,11 @@ #define _ELF_LOADER_H #include +#include -void load_elf32_section(uint32_t base, uint32_t address, uint32_t file_offset, - uint32_t length); +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(uint32_t base, uint32_t loader_addr); +int load_elf32_file(struct file *fp); #endif /* _ELF_LOADER_H */ diff --git a/include/mach/c3600/platform.h b/include/mach/c3600/platform.h index 478cacd..ce47efe 100644 --- a/include/mach/c3600/platform.h +++ b/include/mach/c3600/platform.h @@ -1,8 +1,16 @@ #ifndef _INCLUDE_MACH_C3600_PLATFORM_H #define _INCLUDE_MACH_C3600_PLATFORM_H +#include + #define FLASH_BASE 0x30000000 #define KERNEL_ENTRY_POINT 0x80008000 #define MEMORY_BASE 0x80000000 +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); + #endif /* _INCLUDE_MACH_C3600_PLATFORM_H */ diff --git a/include/mach/c3600/platio.h b/include/mach/c3600/platio.h new file mode 100644 index 0000000..a82c11d --- /dev/null +++ b/include/mach/c3600/platio.h @@ -0,0 +1,24 @@ +#ifndef _INCLUDE_MACH_C3600_PLATIO +#define _INCLUDE_MACH_C3600_PLATIO + +#include +#include + +/* a flash filesystem entry for the C3600 */ +struct fs_ent { + uint32_t magic; + uint32_t length; + /* todo: figure out exactly what these two fields contain */ + uint32_t crc32; + uint32_t date; + char filename[48]; +}; + +void platio_file_open(struct file *fp, const char *filename); +uint32_t platio_read(void *pbuf, uint32_t size, uint32_t nmemb, + struct file *fp); +uint8_t platio_find_file(const char *filename); + +#define FS_FILE_MAGIC 0xbad00b1e + +#endif /* _INCLUDE_MACH_C3600_PLATIO */ diff --git a/include/string.h b/include/string.h index c3b94fb..0546c90 100644 --- a/include/string.h +++ b/include/string.h @@ -1,109 +1,20 @@ #ifndef _STRING_H #define _STRING_H -#define NULL 0 +#include -inline int strcmp(const char *s1, const char *s2) -{ - while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0') { - s1++; - s2++; - } +int strcmp(const char *s1, const char *s2); - if (*s1 != *s2) return -1; +int strncmp(const char *s1, const char *s2, uint32_t n); - return 0; -} +char *strcpy(char *dest, const char *src); -inline int strncmp(const char *s1, const char *s2, uint32_t n) -{ - int i; - for (i = 0; i < n; i++) { - if (s1[i] != s2[i]) return -1; - if (s1[i] == s2[i] && s1[i] == '\0') break; - } +char *strncpy(char *dest, const char *src, uint32_t n); - return 0; -} +uint32_t strlen(char *s); -inline char *strcpy(char *dest, const char *src) -{ - if (!dest || !src) { - return NULL; - } +int memcpy(void *dst, const void *src, int n); - while (*src != '\0') { - *dest++ = *src++; - } - *dest = '\0'; - - return dest; -} - -inline char *strncpy(char *dest, const char *src, uint32_t n) -{ - int i; - int t = 0; - if (!dest || !src || n == 0) { - return NULL; - } - - for (i = 0; i < n; i++) { - if (!t) dest[i] = src[i]; - else dest[i] = '\0'; - - if (dest[i] == '\0') t = 1; - } - - return dest; -} - -inline uint32_t strlen(char *s) -{ - int i = 0; - - while (*s != '\0') { - i++; s++; - } - - return i; -} - -/** - * Copy n bytes from src to dst - * @param dst destination buffer - * @param src source buffer - * @param n number of bytes to copy - * @return number of bytes copied or value < 0 on error - */ -inline int memcpy(void *dst, const void *src, int n) -{ - int i = 0; - if (!dst || !src) return -1; - - for (i = 0; i < n; i++) { - ((char *)dst)[i] = ((char *)src)[i]; - } - - return i; -} - -/** - * strchr - */ -inline const char *strchr(const char *s, int c) -{ - const char *ptr = s; - - if (*ptr == (char)c) return ptr; - - while (*ptr != '\0') { - if (*(++ptr) == (char)c) { - return ptr; - } - } - - return NULL; -} +const char *strchr(const char *s, int c); #endif /* _STRING_H */ diff --git a/include/types.h b/include/types.h index 49fe143..1d244be 100644 --- a/include/types.h +++ b/include/types.h @@ -2,6 +2,7 @@ #define _TYPES_H /* define some convenience types */ +#define NULL 0 typedef unsigned char uint8_t; typedef char int8_t; diff --git a/mach/c3600/Makefile b/mach/c3600/Makefile index c66b221..aa73d3d 100644 --- a/mach/c3600/Makefile +++ b/mach/c3600/Makefile @@ -2,7 +2,7 @@ ifndef CROSS_COMPILE CROSS_COMPILE=mips-elf- endif -OBJECTS=start.o promlib.o +OBJECTS=start.o promlib.o platform.o platio.o INCLUDE=-I../../include diff --git a/mach/c3600/platform.c b/mach/c3600/platform.c index e69de29..f15dad0 100644 --- a/mach/c3600/platform.c +++ b/mach/c3600/platform.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +/** + * perform hardware-specifc initialization for this platform + */ +void platform_init() +{ +} + +/** + * Perform a sanity check on flash + * @returns 0 if no flash found, number of flash devices found otherwise + */ +uint32_t check_flash() +{ + uint32_t *ptr = (uint32_t *)FLASH_BASE; + + if (*ptr != FS_FILE_MAGIC) { + return 0; + } + + return 1; + /* TODO: add support for PCMCIA flash */ +} + +/** + * print a directory listing of the 'main' flash device in the system + */ + +void flash_directory() +{ + struct fs_ent *f = (struct fs_ent *)FLASH_BASE; + uint32_t offset = 0; + + /* Iterate over the files; f->magic is 0 if an invalid file is found. */ + while (f->magic == FS_FILE_MAGIC) { + printf("%s\n", f->filename); + offset += sizeof(struct fs_ent) + f->length; + 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 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_entry); + +} diff --git a/mach/c3600/platio.c b/mach/c3600/platio.c new file mode 100644 index 0000000..d5c7772 --- /dev/null +++ b/mach/c3600/platio.c @@ -0,0 +1,98 @@ +/* Platform specific operations for I/O for the cisco 3600 Series + * (C) 2008 Philippe Vachon + * + * Licensed under the GNU General Public License v2. + */ +#include +#include +#include +#include + +#include + +/* find file in filesystem starting at base */ +struct fs_ent *find_file(const char *filename, uint32_t base) +{ + /* Actual file offset */ + uint32_t offset = 0; + + struct fs_ent *f = (struct fs_ent *)(base + offset); + + /* iterate over files in flash */ + while (f->magic == FS_FILE_MAGIC) { + if (!strncmp(f->filename, filename, 48)) { + return f; + } + + offset += sizeof(struct fs_ent) + f->length; + f = (struct fs_ent *)(base + offset); + } + + return NULL; +} + +/** + * Find a file within the platform-supported I/O devices + * @param filename the file + * @returns 0 on failure, device ID number on success + */ +uint8_t platio_find_file(const char *filename) +{ + if (find_file(filename, FLASH_BASE)) { + return 1; + } + /* todo: add support for PCMCIA devices */ + + return 0; +} + +/** + * Open a file. + * @param fp File structure to hold file information + * @param filename name of the file + */ +void platio_file_open(struct file *fp, const char *filename) +{ + struct fs_ent *ent = find_file(filename, FLASH_BASE); + + if (ent == NULL) { + fp->code = 0; + fp->private = NULL; + return; + } + + fp->dev = 1; /* TODO: add support for PCMCIA flash */ + + fp->private = (void *)ent; + + fp->file_len = ent->length; + fp->file_pos = 0; + + /* copy the filename */ + strncpy(fp->filename, ent->filename, 48); + + fp->code = 1; + +} + +/** + * Read data from a given file + * @param pbuf Buffer to read data into + * @param size size of entity to be read + * @param nmemb number of members to read + * @param fp file information structure to read from. + * @returns number of bytes read (should = size * nmemb for C3600) + */ +uint32_t platio_read(void *pbuf, uint32_t size, uint32_t nmemb, struct file *fp) +{ + /* calculate the effective offset of the data we want to read: */ + char *from = (char *)((uint32_t)(fp->private) + sizeof(struct fs_ent) + + fp->file_pos); + + memcpy(pbuf, from, size * nmemb); + + fp->file_pos += size * nmemb; + + return nmemb * size; + +} diff --git a/main.c b/main.c index 61ea57f..432b21c 100644 --- a/main.c +++ b/main.c @@ -6,16 +6,16 @@ #include #include #include -#include +#include #include /* platform-specific defines */ #include -#define FS_FILE_MAGIC 0xbad00b1e +#include /** - * Dump 0x10 bytes of RAM in canonical hexadecimal form + * Dump 0x10 bytes of memory in canonical hexadecimal form * @param addr Starting address to dump from */ void hex_dump(uint32_t addr) @@ -38,91 +38,6 @@ void hex_dump(uint32_t addr) } -struct fs_ent { - uint32_t magic; - uint32_t length; - /* guesses -- one of these is probably a CRC16 + flags */ - uint32_t crc32; /* ? */ - uint32_t date; /* ? */ - char filename[48]; -}; - -/** - * Check the sanity of flash -- just look for the filesystem magic number - * in the first 4 bytes of flash - * @param base base address of flash - * @returns 0 on failure, 1 on success - */ -int check_flash(uint32_t base) -{ - uint32_t *ptr = (uint32_t *)base; - - if (*ptr != FS_FILE_MAGIC) { - return 0; - } - - return 1; -} - - -/** - * Find file in flash. - * @param filename Name of the kernel ELF file to be loaded. - * @param base Base address of flash - * @returns offset of the file within the flash memory space. - */ -uint32_t find_file(const char *filename, uint32_t base) -{ - /* Actual file offset */ - uint32_t offset = 0; - - uint32_t file_offset = 0; - - struct fs_ent *f = (struct fs_ent *)(base + offset); - - /* iterate over files in flash */ - while (f->magic == FS_FILE_MAGIC) { - if (!strncmp(f->filename, filename, 48)) { - file_offset = offset + sizeof(struct fs_ent); - break; - } - - offset += sizeof(struct fs_ent) + f->length; - f = (struct fs_ent *)(base + offset); - } - - return file_offset; -} - -/** - * Print a directory listing of all files in flash - * @param base Base address of flash - */ -void flash_directory(uint32_t base) -{ - struct fs_ent *f = (struct fs_ent *)base; - uint32_t offset = 0; - - /* Iterate over the files; f->magic is 0 if an invalid file is - * found. - */ - while (f->magic == FS_FILE_MAGIC) { - printf("%s\n", f->filename); - offset += sizeof(struct fs_ent) + f->length; - f = (struct fs_ent *)(base + offset); - } -} - -/** - * Locate the stage two loader. - * @param base Flash base. - * @return address of stage two loader - */ -uint32_t locate_stage_two(uint32_t base) -{ - return find_file("ciscoload.two", base); -} - /** * Entry Point for CiscoLoad */ @@ -133,6 +48,7 @@ void start_bootloader() char buf[129]; char *cmd_line = (char *)MEMORY_BASE; char kernel[49]; + const char *cmd_line_append; buf[128] = '\0'; kernel[48] = '\0'; @@ -145,7 +61,7 @@ void start_bootloader() /* check flash filesystem sanity */ c_putc('L'); - f = check_flash(FLASH_BASE); + f = check_flash(); if (!f) { printf("\nError: Unable to find any valid flash! Aborting load.\n"); @@ -153,9 +69,10 @@ void start_bootloader() } c_putc('O'); + platform_init(); /* locate the stage two loader */ - if (!locate_stage_two(FLASH_BASE)) { + if (!locate_stage_two()) { printf("\nError: Unable to find valid stage two loader. " "Aborting load.\n"); return; @@ -165,14 +82,13 @@ void start_bootloader() printf("Available RAM: %d kB\n", r); printf("Available files:\n"); - flash_directory(FLASH_BASE); + flash_directory(); enter_filename: printf("\nEnter filename to boot:\n> "); 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, (char *)(cmd_line_append + 1)); /* extract the kernel file name now */ @@ -186,22 +102,16 @@ enter_filename: printf("\n\nAttempting to load file %s\n", kernel); - uint32_t kernel_off = find_file(kernel, FLASH_BASE); - uint32_t loader_off = find_file("ciscoload.two", FLASH_BASE); + struct file kernel_file = cilo_open(kernel); - if (loader_off == 0) { - printf("Unable to find the second stage loader. Please copy the " - "second\nstage loader to the flash filesystem (ciscoload.two)."); - return; - } - - if (kernel_off == 0) { + if (kernel_file.code == 0) { printf("Unable to find \"%s\" on the flash filesystem.\n", kernel); } else { - printf("Booting \"%s\" from flash at 0x%08x\n", kernel, - FLASH_BASE + kernel_off); +#ifdef DEBUG printf("DEBUG: cmd_line: %s\n", cmd_line); - if (load_elf32_file(FLASH_BASE + kernel_off, FLASH_BASE + loader_off) +#endif + printf("Booting %s.\n"); + if (load_elf32_file(&kernel_file) < 0) { printf("Fatal error while loading kernel. Aborting.\n"); diff --git a/string.c b/string.c new file mode 100644 index 0000000..64a9384 --- /dev/null +++ b/string.c @@ -0,0 +1,106 @@ +#include +#include + +int strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0') { + s1++; + s2++; + } + + if (*s1 != *s2) return -1; + + return 0; +} + +int strncmp(const char *s1, const char *s2, uint32_t n) +{ + int i; + for (i = 0; i < n; i++) { + if (s1[i] != s2[i]) return -1; + if (s1[i] == s2[i] && s1[i] == '\0') break; + } + + return 0; +} + +char *strcpy(char *dest, const char *src) +{ + if (!dest || !src) { + return NULL; + } + + while (*src != '\0') { + *dest++ = *src++; + } + *dest = '\0'; + + return dest; +} + +char *strncpy(char *dest, const char *src, uint32_t n) +{ + int i; + int t = 0; + if (!dest || !src || n == 0) { + return NULL; + } + + for (i = 0; i < n; i++) { + if (!t) dest[i] = src[i]; + else dest[i] = '\0'; + + if (dest[i] == '\0') t = 1; + } + + return dest; +} + +uint32_t strlen(char *s) +{ + int i = 0; + + while (*s != '\0') { + i++; s++; + } + + return i; +} + +/** + * Copy n bytes from src to dst + * @param dst destination buffer + * @param src source buffer + * @param n number of bytes to copy + * @return number of bytes copied or value < 0 on error + */ +int memcpy(void *dst, const void *src, int n) +{ + int i = 0; + if (!dst || !src) return -1; + + for (i = 0; i < n; i++) { + ((char *)dst)[i] = ((char *)src)[i]; + } + + return i; +} + +/** + * strchr + */ +const char *strchr(const char *s, int c) +{ + const char *ptr = s; + + if (*ptr == (char)c) return ptr; + + while (*ptr != '\0') { + if (*(++ptr) == (char)c) { + return ptr; + } + } + + return NULL; +} +