Commit b17a3008 authored by a1ex's avatar a1ex
Browse files

First attempt to create an unified ML source tree (for 550D and 60D)

--HG--
branch : unified
parent c528951f5d6f
/** \file
* Code to run on the 5D once it has been relocated.
*
* This has been updated to work with the 2.0.3 firmware.
* IT DOES NOT WORK WITH 1.1.0 NOR 1.0.7 ANY MORE!
*/
/*
* Copyright (C) 2009 Trammell Hudson <hudson+ml@osresearch.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "dryos.h"
#include "config.h"
#include "version.h"
#include "bmp.h"
#include "menu.h"
#include "version.h"
#include "property.h"
/** If CONFIG_EARLY_PORT is defined, only a few things will be enabled */
#undef CONFIG_EARLY_PORT
/** These are called when new tasks are created */
void my_task_dispatch_hook( struct context ** );
void my_init_task(void);
void my_bzero( uint8_t * base, uint32_t size );
/** This just goes into the bss */
#define RELOCSIZE 0x10000
static uint8_t _reloc[ RELOCSIZE ];
#define RELOCADDR ((uintptr_t) _reloc)
/** Translate a firmware address into a relocated address */
#define INSTR( addr ) ( *(uint32_t*)( (addr) - ROMBASEADDR + RELOCADDR ) )
/** Fix a branch instruction in the relocated firmware image */
#define FIXUP_BRANCH( rom_addr, dest_addr ) \
INSTR( rom_addr ) = BL_INSTR( &INSTR( rom_addr ), (dest_addr) )
/** Was this an autoboot or firmware file load? */
int autoboot_loaded;
/** Specified by the linker */
extern uint32_t _bss_start[], _bss_end[];
static inline void
zero_bss( void )
{
uint32_t *bss = _bss_start;
while( bss < _bss_end )
*(bss++) = 0;
}
void
__attribute__((noreturn,noinline,naked))
copy_and_restart( int offset )
{
zero_bss();
// Set the flag if this was an autoboot load
autoboot_loaded = (offset == 0);
// Copy the firmware to somewhere safe in memory
const uint8_t * const firmware_start = (void*) ROMBASEADDR;
const uint32_t firmware_len = RELOCSIZE;
uint32_t * const new_image = (void*) RELOCADDR;
blob_memcpy( new_image, firmware_start, firmware_start + firmware_len );
/*
* in entry2() (0xff010134) make this change to
* return to our code before calling cstart().
* This should be a "BL cstart" instruction.
*/
INSTR( 0xFF01019C ) = RET_INSTR;
/*
* in cstart() (0xff010ff4) make these changes:
* calls bzero(), then loads bs_end and calls
* create_init_task
*/
// Reserve memory after the BSS for our application
INSTR( 0xFF01109C ) = (uintptr_t) _bss_end;
// Fix the calls to bzero32() and create_init_task()
FIXUP_BRANCH( 0xFF011004, bzero32 );
FIXUP_BRANCH( 0xFF01108C, create_init_task );
// Set our init task to run instead of the firmware one
INSTR( 0xFF0110A8 ) = (uint32_t) my_init_task;
// Make sure that our self-modifying code clears the cache
clean_d_cache();
flush_caches();
// We enter after the signature, avoiding the
// relocation jump that is at the head of the data
thunk reloc_entry = (thunk)( RELOCADDR + 0xC );
reloc_entry();
/*
* We're back!
* The RAM copy of the firmware startup has:
* 1. Poked the DMA engine with what ever it does
* 2. Copied the rw_data segment to 0x1900 through 0x20740
* 3. Zeroed the BSS from 0x20740 through 0x47550
* 4. Copied the interrupt handlers to 0x0
* 5. Copied irq 4 to 0x480.
* 6. Installed the stack pointers for CPSR mode D2 and D3
* (we are still in D3, with a %sp of 0x1000)
* 7. Returned to us.
*
* Now is our chance to fix any data segment things, or
* install our own handlers.
*/
#ifndef CONFIG_EARLY_PORT
// Install our task creation hooks
task_dispatch_hook = my_task_dispatch_hook;
#endif
// This will jump into the RAM version of the firmware,
// but the last branch instruction at the end of this
// has been modified to jump into the ROM version
// instead.
void (*ram_cstart)(void) = (void*) &INSTR( cstart );
ram_cstart();
// Unreachable
while(1)
;
}
#ifndef CONFIG_EARLY_PORT
void
null_task( void )
{
DebugMsg( DM_SYS, 3, "%s created (and exiting)", __func__ );
return;
}
/**
* Called by DryOS when it is dispatching (or creating?)
* a new task.
*/
void
my_task_dispatch_hook(
struct context ** context
)
{
if( !context )
return;
// Do nothing unless a new task is starting via the trampoile
if( (*context)->pc != (uint32_t) task_trampoline )
return;
// Determine the task address
struct task * const task = *(struct task**) 0x1a20;
thunk entry = (thunk) task->entry;
// Search the task_mappings array for a matching entry point
extern struct task_mapping _task_overrides_start[];
extern struct task_mapping _task_overrides_end[];
const struct task_mapping * mapping = _task_overrides_start;
for( ; mapping < _task_overrides_end ; mapping++ )
{
thunk original_entry = mapping->orig;
if( original_entry != entry )
continue;
/* -- can't call debugmsg from this context */
#if 0
DebugMsg( DM_SYS, 3, "***** Replacing task %x with %x",
original_entry,
mapping->replacement
);
#endif
task->entry = mapping->replacement;
break;
}
}
/** First task after a fresh rebuild.
*
* Try to dump the debug log after ten seconds.
* This requires the create_task(), dmstart(), msleep() and dumpf()
* routines to have been found.
*/
void
my_dump_task( void )
{
dmstart();
msleep( 10000 );
dispcheck();
dumpf();
dmstop();
}
struct config * global_config;
static volatile int init_funcs_done;
static void
call_init_funcs( void * priv )
{
// Call all of the init functions
extern struct task_create _init_funcs_start[];
extern struct task_create _init_funcs_end[];
struct task_create * init_func = _init_funcs_start;
for( ; init_func < _init_funcs_end ; init_func++ )
{
DebugMsg( DM_MAGIC, 3,
"Calling init_func %s (%x)",
init_func->name,
(unsigned) init_func->entry
);
thunk entry = (thunk) init_func->entry;
entry();
}
}
#endif // !CONFIG_EARLY_PORT
static void nop( void ) { }
void menu_init( void ) __attribute__((weak,alias("nop")));
void debug_init( void ) __attribute__((weak,alias("nop")));
int magic_off = 0;
int magic_is_off()
{
return magic_off;
}
int _hold_your_horses = 1;
// only after this task finished, the others are started
void init_task_read_config()
{
show_logo();
display_clock();
config_parse_file( "B:/magic.cfg" );
debug_init_stuff();
_hold_your_horses = 0;
}
void hold_your_horses(int showlogo)
{
while (_hold_your_horses)
{
msleep( 500 );
}
}
/** Initial task setup.
*
* This is called instead of the task at 0xFF811DBC.
* It does all of the stuff to bring up the debug manager,
* the terminal drivers, stdio, stdlib and armlib.
*/
void
my_init_task(void)
{
// Call their init task
init_task();
#ifndef CONFIG_EARLY_PORT
// Overwrite the PTPCOM message
dm_names[ DM_MAGIC ] = "[MAGIC] ";
//~ dmstart(); // already called by firmware?
DebugMsg( DM_MAGIC, 3, "Magic Lantern %s (%s)",
build_version,
build_id
);
DebugMsg( DM_MAGIC, 3, "Built on %s by %s",
build_date,
build_user
);
#endif
// Re-write the version string.
// Don't use strcpy() so that this can be done
// before strcpy() or memcpy() are located.
extern char additional_version[];
additional_version[0] = '-';
additional_version[1] = 'm';
additional_version[2] = 'l';
additional_version[3] = '-';
additional_version[4] = build_version[0];
additional_version[5] = build_version[1];
additional_version[6] = build_version[2];
additional_version[7] = build_version[3];
additional_version[8] = build_version[4];
additional_version[9] = build_version[5];
additional_version[10] = build_version[6];
additional_version[11] = build_version[7];
additional_version[12] = build_version[8];
additional_version[13] = '\0';
#ifndef CONFIG_EARLY_PORT
msleep( 1500 );
magic_off = FOCUS_CONFIRMATION_AF_PRESSED ? 1 : 0;
if (magic_off)
{
bmp_printf(FONT_LARGE, 0, 0, "Magic OFF");
additional_version[0] = '-';
additional_version[1] = 'm';
additional_version[2] = 'l';
additional_version[3] = '-';
additional_version[4] = 'o';
additional_version[5] = 'f';
additional_version[6] = 'f';
additional_version[7] = '\0';
return;
}
BMP_SEM(
msleep( 1000 );
menu_init();
debug_init();
call_init_funcs( 0 );
/* bmp_printf( FONT_MED, 0, 40,
"Magic Lantern v.%s (%s)\n"
"Built on %s by %s\n",
build_version,
build_id,
build_date,
build_user
);*/
// this is better in a separate task (not sure why, but causes instability if called right from here)
// let's try not to open files from here
task_create("config_init", 0x1e, 0x1000, init_task_read_config, 0 );
hold_your_horses(0);
// Create all of our auto-create tasks
extern struct task_create _tasks_start[];
extern struct task_create _tasks_end[];
struct task_create * task = _tasks_start;
int ml_tasks = 0;
for( ; task < _tasks_end ; task++ )
{
//~ DebugMsg( DM_MAGIC, 3,
//~ "Creating task %s(%d) pri=%02x flags=%08x",
//~ task->name,
//~ task->arg,
//~ task->priority,
//~ task->flags
//~ );
task_create(
task->name,
task->priority,
task->flags,
task->entry,
task->arg
);
ml_tasks++;
}
//~ bmp_printf( FONT_MED, 0, 85,
//~ "Magic Lantern is up and running... %d tasks started.",
//~ ml_tasks
//~ );
msleep(500);
)
redraw();
//~ DebugMsg( DM_MAGIC, 3, "magic lantern init done" );
#endif // !CONFIG_EARLY_PORT
}
......@@ -198,8 +198,6 @@ dumper_entry.o: flasher-stubs.S
reboot.o: reboot.c magiclantern.bin
5d-hack.bin: 5d-hack
magiclantern.lds: magiclantern.lds.S
$(call build,CPP,$(CPP) $(CFLAGS) $< | grep -v '^#' > $@)
......@@ -209,8 +207,8 @@ magiclantern.lds: magiclantern.lds.S
ML_OBJS-y = \
magiclantern.lds \
entry.o \
5d-hack.o \
stubs-550d.109.o \
boot-hack.o \
platform/550D.109/stubs.o \
version.o \
bmp.o \
font-large.o \
......@@ -225,9 +223,13 @@ ML_OBJS-y = \
lens.o \
property.o \
propvalues.o \
gui.o \
platform/550D.109/gui.o \
platform/550D.109/misc.o \
platform/550D.109/lens.o \
platform/550D.109/cfn.o \
zebra.o \
shoot.o \
lcdsensor.o \
focus.o \
chdk-gui_draw.o \
movtweaks.o \
......
ARM_PATH=~/arm-toolchain
ARM_BINPATH=$(ARM_PATH)/bin
GCC_VERSION=4.6.0
CC=$(ARM_BINPATH)/arm-elf-gcc-$(GCC_VERSION)
OBJCOPY=$(ARM_BINPATH)/arm-elf-objcopy
AR=$(ARM_BINPATH)/arm-elf-ar
RANLIB=$(ARM_BINPATH)/arm-elf-ranlib
LD=$(CC)
HOST_CC=gcc
HOST_CFLAGS=-g -O3 -W -Wall
# Naming convention for Magic Lantern builds:
# General rules:
# - Always specify the camera and its firmware version number in the build name (e.g. 550d.fw109)
# - For non-release builds, specify the build date and author's (nick)name.
# - For experimental builds, add a short keyword indicating the particular feature tested.
# Examples for experimental builds:
# magiclantern-2010dec07.550d.fw108.cropmarks.a1ex.zip
# magiclantern-2010nov23.550d.fw108.selectable-audio.piers.zip
# Example for pre-release builds:
# magiclantern-2010dec17.550d.fw109.PRERELEASE.alex.zip
# Release builds:
# magiclantern-0.2.0.rc1.550d.fw109.zip
#~ VERSION=0.2.0.rc1.550d.fw109
BUILDVER=alpha12.$(shell whoami)
CONFIG_PYMITE = n
CONFIG_RELOC = n
CONFIG_TIMECODE = n
CONFIG_LUA = n
CONFIG_PTP = n
CONFIG_CONSOLE = n
CONFIG_DEBUGMSG = 0
#MacOS
#UMOUNT=hdiutil unmount
#CF_CARD="/Volumes/EOS_DIGITAL"
#Linux (Ubuntu 10.04)
CF_CARD_GLOB=/media/EOS_*
CF_CARD=$(shell echo $(CF_CARD_GLOB))
UMOUNT=umount
all: magiclantern.fir
VERSION:=$(shell LC_TIME=EN date +'%Y%b%d').60d.fw109.$(BUILDVER)
# DryOSmemory map
# RESTARTSTART is selected to be just above the end of the bss
#
ROMBASEADDR = 0xFF010000
RESTARTSTART = 0x5f000
# Firmware file IDs
FIRMWARE_ID_5D = 0x80000218
FIRMWARE_ID_7D = 0x80000250
FIRMWARE_ID_550D = 0x80000270
FIRMWARE_ID_60D = 0x80000270
FIRMWARE_ID = $(FIRMWARE_ID_60D)
# PyMite scripting paths
PYMITE_PATH = $(HOME)/build/pymite-08
PYMITE_LIB = $(PYMITE_PATH)/src/vm/libpmvm_dryos.a
PYMITE_CFLAGS = \
-I$(PYMITE_PATH)/src/vm \
-I$(PYMITE_PATH)/src/platform/dryos \
# Lua includes and libraries
LUA_PATH = ./lua
LUA_LIB = $(LUA_PATH)/liblua.a
LUA_CFLAGS = -I$(LUA_PATH)
ifeq ($(CONFIG_LUA),y)
include $(LUA_PATH)/Makefile
endif
#
# Install a normal firmware file to the CF card.
#
install: autoexec.bin
cp $^ $(CF_CARD)
mkdir $(CF_CARD)/cropmks || echo "no problem"
cp cropmks_rle/*.bmp $(CF_CARD)/cropmks/
cp logo.bmp $(CF_CARD)
$(UMOUNT) $(CF_CARD)
ptpinstall: autoexec.bin
gvfs-mount -s gphoto2
sleep 2
cat ptpcam.txt | ptpcam --chdk
diff autoexec.bin autoexec.test
zip: magiclantern-$(VERSION).zip
%.pdf:
cp doc/*.pdf .
# zip.txt must be the first item on the list!
magiclantern-$(VERSION).zip: \
zip.txt \
magiclantern.fir \
autoexec.bin \
README \
INSTALL.pdf \
UserGuide.pdf \
UserGuide-diff.pdf \
make_bootable.sh\
logo.bmp\
cropmks/* \
-rm $@
chmod -x autoexec.bin
zip -z $@ < $^
FLAGS=\
-Wp,-MMD,$(dir $@).$(notdir $@).d \
-Wp,-MT,$@ \
-nostdlib \
-mlong-calls \
-fomit-frame-pointer \
-fno-strict-aliasing \
-DCONFIG_MAGICLANTERN=1 \
-DCONFIG_60D=1 \
-DRESTARTSTART=$(RESTARTSTART) \
-DROMBASEADDR=$(ROMBASEADDR) \
-DVERSION=\"$(VERSION)\" \
-DCONFIG_DEBUGMSG=$(CONFIG_DEBUGMSG) \
CFLAGS=\
$(FLAGS) \
-Os \
-Wall \
-W \
-mstructure-size-boundary=32 \
-Wno-unused-parameter \
-Wno-implicit-function-declaration \
-Wno-unused-function \
-Wno-format \
-D__ARM__ \
ifeq ($(CONFIG_PYMITE),y)
CFLAGS += $(PYMITE_CFLAGS)
endif
ifeq ($(CONFIG_LUA),y)
CFLAGS += $(LUA_CFLAGS)
endif
NOT_USED_FLAGS=\
-march=armv5te \
-mthumb-interwork \
-msoft-float \
AFLAGS=\
$(FLAGS) \
%.s: %.c
$(call build,CC -S,$(CC) $(CFLAGS) -S -o $@ $<)
%.o: %.c
$(call build,CC,$(CC) $(CFLAGS) -c -o $@ $<)
%.i: %.c
$(call build,CPP,$(CC) $(CFLAGS) -E -c -o $@ $<)
%: %.c
$(call build,LD,$(CC) $(CFLAGS) -o $@ $<)
%.o: %.S
$(call build,AS,$(CC) $(AFLAGS) -c -o $@ $<)
%.bin: %
$(call build,OBJCOPY,$(OBJCOPY) -O binary $< $@)
dumper: dumper_entry.o dumper.o
$(call build,LD,$(LD) \
-o $@ \
-nostdlib \
-mthumb-interwork \
-march=armv5te \
-e _start \
$^ \
)
test: test.o
$(call build,LD,$(LD) \
-o $@ \
-nostdlib \
-mthumb-interwork \
-march=armv5te \
-e _start \
$^ \