commit 685824f56ed8ff99c3da11dbe7026c045e8eb2e7 Author: Sean Cross Date: Thu Jun 12 12:48:10 2014 +0800 fernly: Initial commit This is an initial commit of the code. It just does prints "Hello, world!" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86fef77 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/build +*.swp +*.swo diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dff3547 --- /dev/null +++ b/Makefile @@ -0,0 +1,40 @@ +include mkenv.mk +include magic.mk + +CFLAGS = -mtune=arm7tdmi -mcpu=arm7tdmi -mfloat-abi=soft -Wall \ + -O0 -ggdb -Iinclude + +LDFLAGS = --nostdlib -T fernvale.ld +LIBS = + +SRC_C = \ + main.c \ + vectors.c \ + serial.c + +SRC_S = \ + start.S + +OBJ = $(addprefix $(BUILD)/, $(SRC_S:.S=.o) $(SRC_C:.c=.o)) + +all: $(BUILD)/firmware.bin +clean: + $(RM) -rf $(BUILD) + +HEADER_BUILD = $(BUILD)/genhdr +$(BUILD)/firmware.bin: $(BUILD)/firmware.elf + objcopy -S -O binary $(BUILD)/firmware.elf $@ + +$(BUILD)/firmware.elf: $(OBJ) + $(LD) $(LDFLAGS) --entry=reset_handler -o $@ $(OBJ) $(LIBS) + +$(OBJ): $(HEADER_BUILD)/generated.h | $(OBJ_DIRS) +$(HEADER_BUILD)/generated.h: | $(HEADER_BUILD) + touch $@ + +OBJ_DIRS = $(sort $(dir $(OBJ))) +$(OBJ_DIRS): + $(MKDIR) -p $@ +$(HEADER_BUILD): + $(MKDIR) -p $@ +-include $(OBJ:.o=.P) diff --git a/README.md b/README.md new file mode 100644 index 0000000..93f072d --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +Fernly - Fernvale Reversing OS +======================================== + +Fernly is a simple operating system designed for use in the reverse engineering +of the Fernvale CPU. It will likely be disposed of when the system has been +understood well enough to implement a full operating system. + + +Usage +----- + +To compile, simply run "make". + +To install, use radare2: + + $ sudo radare2 fv:// + [0x00000000]> s 0x3460 + [0x00003460]> wf .//build/firmware.bin + diff --git a/fernvale.ld b/fernvale.ld new file mode 100644 index 0000000..49ab75c --- /dev/null +++ b/fernvale.ld @@ -0,0 +1,85 @@ +/************************************************************ + * configs/c5471evm/scripts/ld.script + * + * Copyright (C) 2007, 2011-2012, 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +OUTPUT_ARCH(arm) +ENTRY(_stext) +SECTIONS +{ + /* The OS entry point is here */ + + . = 0x10003460; + .text : { + _stext = ABSOLUTE(.); + KEEP(*(vectors)) + *(.text) + *(.fixup) + *(.gnu.warning) + *(.rodata) + *(.glue_7) + *(.glue_7t) + *(.got) /* Global offset table */ + _etext = ABSOLUTE(.); + } + + _eronly = ABSOLUTE(.); /* See below */ + . = ALIGN(4096); + + .data : { + _sdata = ABSOLUTE(.); + *(.data) + CONSTRUCTORS + _edata = ABSOLUTE(.); + } + + .bss : { /* BSS */ + _sbss = ABSOLUTE(.); + *(.bss) + *(COMMON) + _ebss = ABSOLUTE(.); + } + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/include/gnu/stubs-soft.h b/include/gnu/stubs-soft.h new file mode 100644 index 0000000..3c53253 --- /dev/null +++ b/include/gnu/stubs-soft.h @@ -0,0 +1,27 @@ +/* This file is automatically generated. + It defines a symbol `__stub_FUNCTION' for each function + in the C library which is a stub, meaning it will fail + every time called, usually setting errno to ENOSYS. */ + +#ifdef _LIBC +# error Applications may not define the macro _LIBC +#endif + +#define __stub_chflags +#define __stub_create_module +#define __stub_fattach +#define __stub_fchflags +#define __stub_fdetach +#define __stub_get_kernel_syms +#define __stub_getmsg +#define __stub_getpmsg +#define __stub_gtty +#define __stub_lchmod +#define __stub_putmsg +#define __stub_putpmsg +#define __stub_query_module +#define __stub_revoke +#define __stub_setlogin +#define __stub_sigreturn +#define __stub_sstk +#define __stub_stty diff --git a/include/serial.h b/include/serial.h new file mode 100644 index 0000000..060f073 --- /dev/null +++ b/include/serial.h @@ -0,0 +1,9 @@ +#ifndef __UART_H__ +#define __UART_H__ + +#include + +int uart_putc(uint8_t c); +int uart_puts(char *s); + +#endif /* __UART_H__ */ diff --git a/magic.mk b/magic.mk new file mode 100644 index 0000000..1e5d5cb --- /dev/null +++ b/magic.mk @@ -0,0 +1,44 @@ +# This file expects that OBJ contains a list of all of the object files. +# The directory portion of each object file is used to locate the source +# and should not contain any ..'s but rather be relative to the top of the +# tree. +# +# So for example, py/map.c would have an object file name py/map.o +# The object files will go into the build directory and mantain the same +# directory structure as the source tree. So the final dependency will look +# like this: +# +# build/py/map.o: py/map.c +# +# We set vpath to point to the top of the tree so that the source files +# can be located. By following this scheme, it allows a single build rule +# to be used to compile all .c files. + +vpath %.S . $(TOP) +$(BUILD)/%.o: %.S + $(ECHO) "CC $<" + $(Q)$(CC) $(CFLAGS) -c -o $@ $< + +vpath %.s . $(TOP) +$(BUILD)/%.o: %.s + $(ECHO) "AS $<" + $(Q)$(AS) -o $@ $< + +define compile_c +$(ECHO) "CC $<" +$(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< +@# The following fixes the dependency file. +@# See http://make.paulandlesley.org/autodep.html for details. +@$(CP) $(@:.o=.d) $(@:.o=.P); \ + $(SED) -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ + $(RM) -f $(@:.o=.d) +endef + +vpath %.c . $(TOP) +$(BUILD)/%.o: %.c + $(call compile_c) + +$(BUILD)/%.pp: %.c + $(ECHO) "PreProcess $<" + $(Q)$(CC) $(CFLAGS) -E -Wp,-C,-dD,-dI -o $@ $< diff --git a/main.c b/main.c new file mode 100644 index 0000000..e0449bc --- /dev/null +++ b/main.c @@ -0,0 +1,10 @@ +#include "serial.h" + +int main(int argc, char **argv) { + while(1) { + int i; + uart_puts("Hello, world!\n"); + for (i = 0; i < 0xf000; i++); + } + return 0; +} diff --git a/mkenv.mk b/mkenv.mk new file mode 100644 index 0000000..e6708d0 --- /dev/null +++ b/mkenv.mk @@ -0,0 +1,58 @@ +ifneq ($(lastword a b),b) +$(error These Makefiles require make 3.81 or newer) +endif + +# Set TOP to be the path to get from the current directory (where make was +# invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns +# the name of this makefile relative to where make was invoked. +# +# We assume that this file is in the py directory so we use $(dir ) twice +# to get to the top of the tree. + +THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) +TOP := $(patsubst %/py/mkenv.mk,%,$(THIS_MAKEFILE)) + +# Turn on increased build verbosity by defining BUILD_VERBOSE in your main +# Makefile or in your environment. You can also use V=1 on the make command +# line. + +ifeq ("$(origin V)", "command line") +BUILD_VERBOSE=$(V) +endif +ifndef BUILD_VERBOSE +BUILD_VERBOSE = 0 +endif +ifeq ($(BUILD_VERBOSE),0) +Q = @ +else +Q = +endif +# Since this is a new feature, advertise it +ifeq ($(BUILD_VERBOSE),0) +$(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) +endif + +# default settings; can be overriden in main Makefile + +BUILD ?= build + +RM = rm +ECHO = @echo +CP = cp +MKDIR = mkdir +SED = sed +PYTHON = python + +AS = $(CROSS_COMPILE)as +CC = $(CROSS_COMPILE)clang +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy +SIZE = $(CROSS_COMPILE)size +STRIP = $(CROSS_COMPILE)strip + +all: +.PHONY: all + +.DELETE_ON_ERROR: + +MKENV_INCLUDED = 1 diff --git a/serial.c b/serial.c new file mode 100644 index 0000000..7ffd7df --- /dev/null +++ b/serial.c @@ -0,0 +1,20 @@ +#include +#include "serial.h" + +int uart_putc(uint8_t c) { + uint32_t *uart_ldr = (uint32_t *)0xa0080014; + uint32_t *uart_sbr = (uint32_t *)0xa0080000; + /* Wait for UART to be empty */ + while (! (*uart_ldr & 0x20)); + *uart_sbr = c; + return 0; +} + +int uart_puts(char *s) { + while(*s) { + if (*s == '\n') + uart_putc('\r'); + uart_putc(*s++); + } + return 0; +} diff --git a/start.S b/start.S new file mode 100644 index 0000000..f9667fc --- /dev/null +++ b/start.S @@ -0,0 +1,49 @@ +.section vectors + b do_reset + b do_undef + b do_swi + b do_prefetch_abort + b do_data_abort + b do_reserved + b do_irq + b do_fiq + +do_reset: + b reset_handler +do_undef: + b undef_handler +do_swi: + b swi_handler +do_prefetch_abort: + b prefetch_abort_handler +do_data_abort: + b data_abort_handler +do_reserved: + b reserved_handler +do_irq: + b irq_handler +do_fiq: + b fiq_handler + +.text + +.global other +other: + add r1, r2, r1 + bx lr + +.global __start +__start: + add r3, r2, r3 + bx lr + +.global _start +_start: + add r4, r3, r4 + bx lr + +.global other2 +other2: + add r5, r4, r5 + bx lr + diff --git a/vectors.c b/vectors.c new file mode 100644 index 0000000..57bae7a --- /dev/null +++ b/vectors.c @@ -0,0 +1,34 @@ + +void reset_handler(void) { + extern int main(int argc, char **argv); + main(1, 0); + return; +} + +void undef_handler(void) { + return; +} + +void swi_handler(void) { + return; +} + +void prefetch_abort_handler(void) { + return; +} + +void data_abort_handler(void) { + return; +} + +void reserved_handler(void) { + return; +} + +void irq_handler(void) { + return; +} + +void fiq_handler(void) { + return; +}