Commit 938c26d3 authored by alex@thinkpad's avatar alex@thinkpad
Browse files

Merged unified into crop_rec_4k

--HG--
branch : crop_rec_4k
......@@ -56,10 +56,12 @@ On the 5D there are the following fonts added to the stubs.S file:
0xf00d1110: HCanonGothic 36 px, ascii only (0xFFE2)
0xf00d585c: CanonMonoSpace 40 px, ascii only (0xFFD8)
Alex, 16Mar2011
https://bitbucket.org/hudson/magic-lantern/changeset/cfba492ea84d
Daniel Fort, 05Jul2017
https://bitbucket.org/hudson/magic-lantern/pull-requests/844/find_fntpy-update/diff
"""
......@@ -105,6 +107,17 @@ def parseBitmap(m, off, base):
nb_byte = nb_byte + 1
print ' bitmap size = 0x%x' % ( nb_byte*height )
def guess_load_addr(rom, name):
if rom[4:12] == "gaonisoy":
return 0xFF010000 # assume old DIGIC 4 ROM dumped from 0xFF010000
if "ROM0" in name:
return 0xF0000000 # ROM0 from ML/LOGS/
if "ROM1" in name:
return 0xF8000000 # ROM1 from ML/LOGS/
# unknown, just report the offset inside the ROM.
return 0
f = open(sys.argv[1], 'rb')
m = f.read()
f.close()
......@@ -112,10 +125,11 @@ f.close()
if (len(sys.argv)>2):
base = int(sys.argv[2], 16)
else:
base = 0xff010000
base = guess_load_addr(m, sys.argv[1])
print 'Find bitmap fonts in Canon DSLR firmwares'
print 'Arm.Indy. based on work by Pel, Trammel Hudson and A1ex\n'
print 'Arm.Indy. based on work by Pel, Trammel Hudson and A1ex'
print 'Assume ROM file was dumped from 0x%08x \n' % base
off = 0
while off < len(m) and off <> -1:
......
MODEL=5D3
FW_VERSION=113
CFLAG_USER += -DCONFIG_5D3_113=1
x: clean_install_fir
......
MODEL=5D3
FW_VERSION=123
CFLAG_USER += -DCONFIG_5D3_123=1
x: clean_install_fir
include ../Makefile.minimal
MODEL=EOSM
include ../Makefile.minimal
......@@ -230,7 +230,7 @@ static void mem_benchmark_task()
if (HAS_EDMAC_MEMCPY)
{
mem_benchmark_run("edmac_memcpy ", &y, bufsize, (mem_bench_fun)edmac_memcpy, (intptr_t)UNCACHEABLE(buf1), (intptr_t)UNCACHEABLE(buf2), bufsize, 0);
mem_benchmark_run("edmac_memcpy ", &y, bufsize, (mem_bench_fun)edmac_memcpy, (intptr_t)UNCACHEABLE(buf1), (intptr_t)UNCACHEABLE(buf2), bufsize, 0, 1);
mem_benchmark_run("edmac_copy_rectangle", &y, 720*480, (mem_bench_fun)mem_test_edmac_copy_rectangle, 0, 0, 0, 0, 0);
}
......
# define the module name - make sure name is max 8 characters
MODULE_NAME=edmac
MODULE_OBJS=edmac.o edmac_util.o
MODULE_OBJS=edmac.o edmac_util.o edmac_test.o md5.o
# include modules environment
include ../Makefile.modules
# fixme: cleaner way to localize symbols?
edmac.sym: edmac.mo
$(call build,STRIP,$(READELF) -sW $< | grep GLOBAL | grep -v UND | grep -v COM | grep -v "__module_.*$(MODULE_NAME)" | $(AWK) "{print \$$8;}" | sort \
| grep -v edmac_format_size > localsyms)
$(call build,STRIP,$(OBJCOPY) edmac.mo edmac.mo --localize-symbols localsyms)
$(call rm_files, localsyms)
$(call build,EXPORTS,$(READELF) -sW $< | grep GLOBAL | grep -v UND | grep -v COM | grep -v "__module_.*$(MODULE_NAME)" | $(AWK) "{print \$$2 \" \" \$$8;}" | sort > $@ && cat $@)
......@@ -10,6 +10,8 @@
#include <timer.h>
#include <asm.h>
extern WEAK_FUNC(ret_0) char * asm_guess_func_name_from_string(uint32_t func_addr);
static int edmac_selection;
static void edmac_display_page(int i0, int x0, int y0)
......@@ -114,10 +116,33 @@ static void edmac_display_detailed(int channel)
/* http://magiclantern.wikia.com/wiki/Register_Map#EDMAC */
uint32_t dir = edmac_get_dir(channel);
char* dir_s =
dir == EDMAC_DIR_READ ? "read" :
dir == EDMAC_DIR_WRITE ? "write" :
"unused";
if (dir == EDMAC_DIR_UNUSED)
{
/* attempting to get info from unused channels may crash on old models */
/* if it doesn't crash, the additional info doesn't make any sense */
bmp_printf(FONT_MONO_20, 50, y + font_large.height, "Unused");
return;
}
uint32_t state = edmac_get_state(channel);
uint32_t flags = edmac_get_flags(channel);
uint32_t addr = edmac_get_address(channel);
char flags_desc[32] = "";
if (flags)
{
snprintf(flags_desc, sizeof(flags_desc),
"(%d bytes per transfer)",
edmac_bytes_per_transfer(flags)
);
}
union edmac_size_t
{
struct { short x, y; } size;
......@@ -134,12 +159,6 @@ static void edmac_display_detailed(int channel)
uint32_t off2a = shamem_read(base + 0x24);
uint32_t off3 = shamem_read(base + 0x28);
uint32_t off40 = shamem_read(base + 0x40);
uint32_t dir = edmac_get_dir(channel);
char* dir_s =
dir == EDMAC_DIR_READ ? "read" :
dir == EDMAC_DIR_WRITE ? "write" :
"unused?";
uint32_t conn_w = edmac_get_connection(channel, EDMAC_DIR_WRITE);
uint32_t conn_r = edmac_get_connection(channel, EDMAC_DIR_READ);
......@@ -150,7 +169,7 @@ static void edmac_display_detailed(int channel)
bmp_printf(FONT_MONO_20, 50, y += fh, "Address : %8x ", addr);
bmp_printf(FONT_MONO_20, 50, y += fh, "State : %8x ", state);
bmp_printf(FONT_MONO_20, 50, y += fh, "Flags : %8x ", flags);
bmp_printf(FONT_MONO_20, 50, y += fh, "Flags : %8x %s", flags, flags_desc);
bmp_printf(FONT_MONO_20, 50, y += fh, "Size : %s ", edmac_format_size(&info));
y += fh;
bmp_printf(FONT_MONO_20, 50, y += fh, "Size A : %8x (%d x %d) ", size_a.raw, size_a.size.x, size_a.size.y);
......@@ -165,18 +184,19 @@ static void edmac_display_detailed(int channel)
y += fh;
bmp_printf(FONT_MONO_20, 50, y += fh, "Connection : write=0x%x read=0x%x dir=%s", conn_w, conn_r, dir_s);
#if defined(CONFIG_5D3)
/**
* ConnectReadEDmac(channel, conn)
* RAM:edmac_register_interrupt(channel, cbr_handler, ...)
* => *(8 + 32*arg0 + *0x12400) = arg1
* and also: *(12 + 32*arg0 + *0x12400) = arg1
*/
uint32_t cbr1 = MEM(8 + 32*(channel) + MEM(0x12400));
uint32_t cbr2 = MEM(12 + 32*(channel) + MEM(0x12400));
bmp_printf(FONT_MONO_20, 50, y += fh, "CBR handler: %8x %s", cbr1, asm_guess_func_name_from_string(cbr1));
bmp_printf(FONT_MONO_20, 50, y += fh, "CBR abort : %8x %s", cbr2, asm_guess_func_name_from_string(cbr2));
#endif
if (is_camera("5D3", "*"))
{
/**
* ConnectReadEDmac(channel, conn)
* RAM:edmac_register_interrupt(channel, cbr_handler, ...)
* => *(8 + 32*arg0 + *0x12400) = arg1
* and also: *(12 + 32*arg0 + *0x12400) = arg1
*/
uint32_t cbr1 = MEM(8 + 32*(channel) + MEM(0x12400));
uint32_t cbr2 = MEM(12 + 32*(channel) + MEM(0x12400));
bmp_printf(FONT_MONO_20, 50, y += fh, "CBR handler: %8x %s", cbr1, asm_guess_func_name_from_string(cbr1));
bmp_printf(FONT_MONO_20, 50, y += fh, "CBR abort : %8x %s", cbr2, asm_guess_func_name_from_string(cbr2));
}
}
static MENU_UPDATE_FUNC(edmac_display)
......@@ -195,12 +215,12 @@ static MENU_UPDATE_FUNC(edmac_display)
else
{
edmac_display_page(16, 0, 30);
#ifdef CONFIG_DIGIC_V
edmac_display_page(32, 360, 30);
#endif
if (edmac_get_dir(32) != EDMAC_DIR_UNUSED)
{
edmac_display_page(32, 360, 30);
}
}
//~ int x = 20;
bmp_printf(
FONT_MONO_20,
20, 450, "EDMAC state: "
......@@ -492,6 +512,9 @@ static void log_edmac_usage()
NotifyBox(2000, "Finished!");
}
/* edmac_test.c */
extern void edmac_test();
static struct menu_entry edmac_menu[] =
{
{
......@@ -525,6 +548,13 @@ static struct menu_entry edmac_menu[] =
.priv = log_edmac_usage,
.help = "Log EDMAC status changes every 0.1ms.",
},
{
.name = "EDMAC model test",
.select = run_in_separate_task,
.priv = edmac_test,
.help = "Tests to confirm our hypothesis on how EDMAC works.",
.help2 = "Should be executed on both camera and QEMU."
},
MENU_EOL
}
},
......
#include <dryos.h>
#include <console.h>
#include <bmp.h>
#include <edmac.h>
#include <edmac-memcpy.h>
#include "md5.h"
static FILE * logfile = 0;
static int Log(const char * fmt, ...)
{
va_list ap;
char buf[128];
va_start( ap, fmt );
int len = vsnprintf( buf, sizeof(buf)-1, fmt, ap );
va_end( ap );
if (logfile) FIO_WriteFile( logfile, buf, len );
printf("%s", buf);
return len;
}
extern uint32_t edmac_read_chan;
extern uint32_t edmac_write_chan;
extern uint32_t dmaConnection;
static void edmac_read_complete_cbr (void* ctx)
{
*((uint32_t *)ctx) = 1;
}
static void edmac_write_complete_cbr (void* ctx)
{
*((uint32_t *)ctx) = 1;
}
static void edmac_test_copy(
void * src, void * dst,
struct edmac_info * src_info,
struct edmac_info * dst_info,
uint32_t src_flags, uint32_t dst_flags,
uint32_t src_start_flags, uint32_t dst_start_flags,
int show_elapsed, int check_copy
)
{
volatile uint32_t write_done = 0;
volatile uint32_t read_done = 0;
/* EDMAC addresses are cacheable */
src = CACHEABLE(src);
dst = CACHEABLE(dst);
/* EDMAC CBRs (to mark the operation as finished) */
RegisterEDmacCompleteCBR(edmac_read_chan, &edmac_read_complete_cbr, (void*) &read_done);
RegisterEDmacAbortCBR(edmac_read_chan, &edmac_read_complete_cbr, (void*) &read_done);
RegisterEDmacPopCBR(edmac_read_chan, &edmac_read_complete_cbr, (void*) &read_done);
RegisterEDmacCompleteCBR(edmac_write_chan, &edmac_write_complete_cbr, (void*) &write_done);
RegisterEDmacAbortCBR(edmac_write_chan, &edmac_write_complete_cbr, (void*) &write_done);
RegisterEDmacPopCBR(edmac_write_chan, &edmac_write_complete_cbr, (void*) &write_done);
/* connect the selected channels to 6 so any data read from RAM is passed to write channel */
ConnectWriteEDmac(edmac_write_chan, dmaConnection);
ConnectReadEDmac(edmac_read_chan, dmaConnection);
/* set buffers, geometry and flags */
SetEDmac(edmac_read_chan, src, src_info, src_flags);
SetEDmac(edmac_write_chan, dst, dst_info, dst_flags);
/* start transfer. no flags for write, 2 for read channels */
info_led_on();
int64_t t0 = get_us_clock_value();
StartEDmac(edmac_write_chan, dst_start_flags);
StartEDmac(edmac_read_chan, src_start_flags);
while(!read_done || !write_done)
{
if (get_us_clock_value() - t0 > 200000)
{
if(!read_done)
{
Log("Read EDMAC timeout.\n");
}
if(!write_done)
{
Log("Write EDMAC timeout.\n");
}
break;
}
}
/* not always needed, but shouldn't do any harm */
AbortEDmac(edmac_read_chan);
AbortEDmac(edmac_write_chan);
int64_t t1 = get_us_clock_value();
info_led_off();
if (show_elapsed)
{
Log("Elapsed time: %d "SYM_MICRO"s.\n", (int)(t1 - t0));
}
msleep(100);
uint32_t src_end_addr = edmac_get_pointer(edmac_read_chan);
uint32_t dst_end_addr = edmac_get_pointer(edmac_write_chan);
uint32_t expected_src_end_addr = (uint32_t) src + edmac_get_total_size(src_info, 1);
uint32_t expected_dst_end_addr = (uint32_t) dst + edmac_get_total_size(dst_info, 1);
if (src_end_addr != expected_src_end_addr)
{
Log("Read EDMAC %srun (%d)\n",
src_end_addr > expected_src_end_addr ? "over" : "under",
src_end_addr - expected_src_end_addr
);
}
if (dst_end_addr != expected_dst_end_addr)
{
Log("Write EDMAC %srun (%d)\n",
dst_end_addr > expected_dst_end_addr ? "over" : "under",
dst_end_addr - expected_dst_end_addr
);
}
if (check_copy)
{
int total_size_src = edmac_get_total_size(src_info, 0);
int total_size_dst = edmac_get_total_size(dst_info, 0);
if (total_size_src != total_size_dst)
{
Log("Warning: src/dst sizes do not match (%d, %d)\n", total_size_src, total_size_dst);
}
if (memcmp(src, dst, total_size_dst) == 0)
{
Log("Copied %d bytes.\n", total_size_dst);
}
else
{
/* Try to figure out what it did.
* Assume it copies the entire input (no offsets in src_info);
* it may add some gaps in the output (positive offsets in dst_info).
*/
int prev_copied = -1;
int prev_skipped = -1;
int repeats = 0;
int copied_acc = 0;
int skipped_acc = 0;
const int maxiter = 5000;
for (int k = 0; k < maxiter; k++)
{
int copied = 0;
while (*(uint8_t*)(dst + copied_acc + skipped_acc + copied) == *(uint8_t*)(src + copied_acc + copied))
{
copied++;
}
copied_acc += copied;
int skipped = 0;
while (*(uint8_t*)(dst + copied_acc + skipped_acc + skipped) == 0xEE)
{
skipped++;
}
skipped_acc += skipped;
if (copied == prev_copied && skipped == prev_skipped)
{
repeats++;
}
else
{
if (repeats)
{
Log("Repeated %d times (%d runs).\n", repeats, repeats + 1);
}
Log("Copied %d, skipped %d.\n", copied, skipped);
repeats = 0;
}
prev_copied = copied;
prev_skipped = skipped;
if (copied_acc >= total_size_dst)
{
break;
}
}
if (repeats)
{
Log("Repeated %d times (%d runs).\n", repeats, repeats + 1);
}
if (copied_acc == total_size_dst)
{
Log("Source copied correctly.\n");
}
else if (copied_acc < total_size_dst)
{
Log("Only copied %d of %d.\n", copied_acc, total_size_dst);
}
else
{
Log("Copied too much: %d, expected %d.\n", copied_acc, total_size_dst);
}
}
}
UnregisterEDmacCompleteCBR(edmac_read_chan);
UnregisterEDmacAbortCBR(edmac_read_chan);
UnregisterEDmacPopCBR(edmac_read_chan);
UnregisterEDmacCompleteCBR(edmac_write_chan);
UnregisterEDmacAbortCBR(edmac_write_chan);
UnregisterEDmacPopCBR(edmac_write_chan);
}
static void Log_md5(void * addr, int size)
{
uint8_t md5_bin[16];
md5((void *) addr, size, md5_bin);
for (int i = 0; i < 16; i++)
Log("%02x", md5_bin[i]);
Log("\n");
}
static void Log_edmac_info(struct edmac_info * info)
{
const char * names[] = {
"xn", "xa", "xb", "yn", "ya", "yb",
"off1a", "off1b", "off2a", "off2b", "off3"
};
int values[] = {
info->xn, info->xa, info->xb, info->yn, info->ya, info->yb,
info->off1a, info->off1b, info->off2a, info->off2b, info->off3
};
for (int i = 0; i < COUNT(values); i++)
if (values[i])
Log("%s=%d, ", names[i], values[i]);
Log("\b\b (");
Log("size %s", format_memory_size(edmac_get_total_size(info, 0)));
Log(", with offsets %s)\n", format_memory_size(edmac_get_total_size(info, 1)));
}
static void edmac_print_buffer_contents(char * buf, int size)
{
for (int i = 0; i < size; i++)
{
if(buf[i] != 0xEE)
{
if (buf[i] >= 'A' && buf[i] <= 'Z')
{
int ch = buf[i];
Log("%s", (char*) &ch);
}
else if (buf[i] == 0)
{
Log(".");
}
else
{
Log("?");
}
}
else
{
Log("-");
}
}
Log("\n");
}
/* note: this may read more than "size" bytes" */
static void edmac_sim_transfer_size(char * src, char * dst, uint32_t size, uint32_t read_bytes, uint32_t write_bytes)
{
uint8_t buf[16] = {0};
ASSERT(read_bytes <= COUNT(buf));
ASSERT(write_bytes <= COUNT(buf));
uint32_t rd = 0;
uint32_t wr = 0;
while (wr < size)
{
for (uint32_t k = 0; k < read_bytes; k++)
{
buf[k] = src[rd++];
}
for (uint32_t k = 0; k < write_bytes && wr < size; k++)
{
dst[wr++] = buf[k];
}
}
}
static void edmac_guess_transfer_size(char * src, char * dst, int size, int * read_size, int * write_size)
{
/* simulate a little more */
char * tmp = malloc(size + 16);
if (!tmp) return;
/* report the closest match */
int best_r = 0;
int best_w = 0;
int best_e = INT_MAX;
for (int r = 1; r <= 16; r *= 2)
{
for (int w = 1; w <= 16; w *= 2)
{
/* simulate what would happen if we'd read "r" bytes and write "w" bytes at a time */
edmac_sim_transfer_size(src, tmp, size + 16, r, w);
/* does it match what the EDMAC did? */
if (memcmp(dst, tmp, size) == 0)
{
int e = ABS((*read_size) - r) + ABS((*write_size) - w);
if (e < best_e)
{
/* match closer to the expected size? */
best_r = r;
best_w = w;
best_e = e;
}
}
}
}
if (!best_r || !best_w)
{
/* no match found: why? */
edmac_sim_transfer_size(src, tmp, size + 16, *read_size, *write_size);
edmac_print_buffer_contents(tmp, size);
edmac_print_buffer_contents(dst, size);
}
*read_size = best_r;
*write_size = best_w;
free(tmp);
}
void edmac_test()
{
console_show();
msleep(1000);
/* fixme: use the trace module? */
logfile = FIO_CreateFile("ML/LOGS/EDMAC.LOG");
Log("Allocating memory...\n"); msleep(200);
int src_size = 8 * 1024 * 1024;
int dst_size = src_size;
char * src = fio_malloc(src_size);
char * dst = fio_malloc(dst_size);
if (!src || !dst)
{
Log("malloc error\n");
return;
}
Log("Filling source buffer...\n"); msleep(200);
for (int i = 0; i < src_size; i++)
{
src[i] = (i < 256)
? 'A' + i % ('Z' - 'A') /* characters, easy to see for small transfers */
: (2*i) | 1; /* random data to test larger transfers (nonzero and != 0xEE) */
}
msleep(500);