Read about our upcoming Code of Conduct on this issue

Commit c7d18685 authored by alex@thinkpad's avatar alex@thinkpad
Browse files

Merged digic6-dumper into 1300D

(boot method refactoring required here as well)

--HG--
branch : 1300D
/*
* Copyright (C) 2015 Magic Lantern Team
*
* 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.
*/
/*
This code was obtained from:
http://chdk.wikia.com/wiki/Obtaining_a_firmware_dump
which references to:
https://drive.google.com/uc?id=0B08pqRtyrObjTGpKNHJJZld2ZzQ&export=download
It does not mention any license, so it is probably either public domain or some
other free license. But we cannot 100% guarantee this.
As this code uses a CRC16 implementation that is 100% matching the linux kernel's
CRC16 implementation at https://github.com/torvalds/linux/blob/master/lib/crc16.c
just with linux-specific macros removed, it is to assume that the crc16.c is being
licensed under GPL.
Due to the nature of GPL, all other code then must be also GPL licensed.
If this is an incorrect assumption, please tell us.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <getopt.h>
#define ST_SYNC 0
#define ST_BIT 1
#define ST_SPACE 2
#define LEVEL_UNK 0
#define LEVEL_HI 1
#define LEVEL_LO 2
/* may get tweaked to better match the bit times of the recording */
uint32_t len_sync = 20;
uint32_t len_zero = 3;
uint32_t len_one = 10;
uint32_t len_space = 3;
uint32_t inverted = 0;
/* this parameter should match the setting in dumper, assuming bit times above were untouched */
uint32_t slowdown = 1;
/* make them fit the signal amplitudes */
int32_t level_hi = 120;
int32_t level_lo = 110;
/* auto DC-offset compensation, the lower the number, the slower it learns.
tries to undo sound card's DC filtering by integrating.
for rates close to the sampling rate, 0.6 seems to be a good starting point.
*/
float avg_fact = 0;
float dc_offset = 0;
int get_level(short v)
{
static int last_level = LEVEL_UNK;
if (v >= level_hi)
{
last_level = inverted?LEVEL_LO:LEVEL_HI;
}
else if (v <= level_lo)
{
last_level = inverted?LEVEL_HI:LEVEL_LO;
}
return last_level;
}
int main(int argc, char *argv[])
{
uint8_t buf[1024];
int bytes_written = 0;
int len = 0;
int p = 0;
int state = ST_SYNC;
int pp = 0;
int lv = 0;
int cnt = 0;
int bits = 0;
int n = 0;
unsigned char byte = 0;
FILE *fo = NULL;
FILE *f = NULL;
char *out_filename = "dump";
char *in_filename = "-";
struct option long_options[] = {
{"len_sync", required_argument, NULL, 'y' },
{"len_space", required_argument, NULL, 's' },
{"len_zero", required_argument, NULL, 'z' },
{"len_one", required_argument, NULL, 'o' },
{"level_hi", required_argument, NULL, 'h' },
{"level_lo", required_argument, NULL, 'l' },
{"inverted", no_argument, &inverted, 1 },
{0, 0, 0, 0 }
};
int index = 0;
char opt = ' ';
while ((opt = getopt_long(argc, argv, "y:s:z:o:h:l:", long_options, &index)) != -1)
{
switch (opt)
{
case 'y':
if(!optarg)
{
printf("Error: Missing parameter\n");
return -1;
}
else
{
len_sync = atoi(optarg);
}
break;
case 's':
if(!optarg)
{
printf("Error: Missing parameter\n");
return -1;
}
else
{
len_space = atoi(optarg);
}
break;
case 'z':
if(!optarg)
{
printf("Error: Missing parameter\n");
return -1;
}
else
{
len_zero = atoi(optarg);
}
break;
case 'o':
if(!optarg)
{
printf("Error: Missing parameter\n");
return -1;
}
else
{
len_one = atoi(optarg);
}
break;
case 'h':
if(!optarg)
{
printf("Error: Missing parameter\n");
return -1;
}
else
{
level_hi = atoi(optarg);
}
break;
case 'l':
if(!optarg)
{
printf("Error: Missing parameter\n");
return -1;
}
else
{
level_lo = atoi(optarg);
}
break;
case 0:
break;
default:
return -1;
}
}
if(optind >= argc)
{
printf("Error: Missing input filename\n");
return -1;
}
if(optind < argc)
{
in_filename = argv[optind];
}
optind++;
if(optind < argc)
{
out_filename = argv[optind];
}
/* open input file */
if(!strcmp(in_filename, "-"))
{
printf("Reading from stdin\n");
f = stdin;
}
else
{
f = fopen(in_filename, "r+b");
}
if(!f)
{
printf("Failed to open input file '%s'\n", in_filename);
return;
}
/* open output filename */
if(!strcmp(out_filename, "-"))
{
printf("Writing to stdout\n");
fo = stdout;
}
else
{
fo = fopen(out_filename, "w+b");
}
if(!fo)
{
printf("Failed to open output file '%s'\n", out_filename);
return;
}
while (!feof(f))
{
pp += len;
len = fread(buf, 1, sizeof(buf), f);
p=0;
while (p<len)
{
uint8_t signal = buf[p++];
dc_offset = (dc_offset * (1 - avg_fact)) + (signal * avg_fact);
lv = get_level(signal + dc_offset);
if (lv == LEVEL_UNK)
{
continue;
}
#if 0
fwrite((lv == LEVEL_HI)?"^":"_",1,1,fo);
continue;
#endif
switch (state)
{
case ST_SYNC:
if(lv == LEVEL_HI)
{
++cnt;
}
else
{
printf("sync: %d\n", cnt);
if(cnt >= len_sync * slowdown)
{
cnt = 1;
state = ST_BIT;
bits = 0;
byte = 0;
}
else
{
cnt = 0;
state = ST_SYNC;
printf("%06X [0x%08X]: SYNC ERROR!\n", n, pp+p);
}
}
break;
case ST_BIT:
if(lv == LEVEL_LO)
{
++cnt;
}
else
{
printf("bit: %d\n", cnt);
if(cnt >= len_one * slowdown && cnt <= 2 * len_one * slowdown)
{
cnt = 1;
byte |= (1<<bits);
if((++bits) == 8)
{
fwrite(&byte, 1, 1, fo);
bytes_written++;
state = ST_SYNC;
++n;
}
else
{
state = ST_SPACE;
}
}
else if(cnt >= len_zero * slowdown && cnt < len_one * slowdown)
{
cnt = 1;
if((++bits) == 8)
{
fwrite(&byte, 1, 1, fo);
bytes_written++;
state = ST_SYNC;
++n;
}
else
{
state = ST_SPACE;
}
}
else
{
cnt = 1;
state = ST_SYNC;
printf("%06X [0x%08X]: BIT SYNC ERROR!\n", n, pp+p);
}
}
break;
case ST_SPACE:
if(lv == LEVEL_HI)
{
++cnt;
}
else
{
printf("space: %d\n", cnt);
if(cnt >= len_space * slowdown)
{
cnt = 1;
state = ST_BIT;
}
else
{
cnt = 0;
state = ST_SYNC;
printf("%06X [0x%08X]: SPACE SYNC ERROR!\n", n, pp+p);
}
}
break;
}
}
}
printf("Done, wrote %d byte, DC offset was %2.2f\n", bytes_written, dc_offset);
fclose(fo);
fclose(f);
}
#include "crc16.h"
/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
u16 const crc16_table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
/**
* crc16 - compute the CRC-16 for the data buffer
* @crc: previous CRC value
* @buffer: data pointer
* @len: number of bytes in the buffer
*
* Returns the updated CRC value.
*/
u16 crc16(u16 crc, u8 const *buffer, long len)
{
while (len--)
crc = crc16_byte(crc, *buffer++);
return crc;
}
typedef unsigned char u8;
typedef unsigned short u16;
extern u16 const crc16_table[256];
extern u16 crc16(u16 crc, const u8 *buffer, long len);
static inline u16 crc16_byte(u16 crc, const u8 data)
{
return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
}
/*
* Copyright (C) 2015 Magic Lantern Team
*
* 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.
*/
/*
This code was obtained from:
http://chdk.wikia.com/wiki/Obtaining_a_firmware_dump
which references to:
https://drive.google.com/uc?id=0B08pqRtyrObjTGpKNHJJZld2ZzQ&export=download
It does not mention any license, so it is probably either public domain or some
other free license. But we cannot 100% guarantee this.
As this code uses a CRC16 implementation that is 100% matching the linux kernel's
CRC16 implementation at https://github.com/torvalds/linux/blob/master/lib/crc16.c
just with linux-specific macros removed, it is to assume that the crc16.c is being
licensed under GPL.
Due to the nature of GPL, all other code then must be also GPL licensed.
If this is an incorrect assumption, please tell us.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
static uint8_t *file_data = NULL;
static uint32_t file_length = 0;
#include "crc16.c"
struct dump_header
{
uint32_t address;
uint16_t blocksize;
uint8_t blocktype;
} __attribute__((packed));
int32_t findsig(int32_t sp)
{
int32_t i;
for (i=0; i < (file_length - sp - 4); i++)
{
if ((file_data[sp+i+0] == 0x0a) &&
(file_data[sp+i+1] == 0x55) &&
(file_data[sp+i+2] == 0xaa) &&
(file_data[sp+i+3] == 0x50) )
{
return sp + i;
}
}
return -1;
}
int main(int argc, char *argv[])
{
uint32_t addr = 0;
uint32_t blk = 0;
uint32_t block_size = 1024;
uint32_t base = 0;
FILE *file_out = NULL;
FILE *file_in = NULL;
char *out_filename = "dump.dat";
char *in_filename = "-";
if(argc > 1)
{
in_filename = argv[1];
}
if(argc > 2)
{
out_filename = argv[2];
}
/* open input file */
if(!strcmp(in_filename, "-"))
{
printf("Reading from stdin\n");
file_in = stdin;
}
else
{
file_in = fopen(in_filename, "r+b");
}
if(!file_in)
{
printf("Failed to open input file\n");
return;
}
/* open output filename */
if(!strcmp(out_filename, "-"))
{
printf("Writing to stdout\n");
file_out = stdout;
}
else
{
file_out = fopen(out_filename, "w+b");
}
if(!file_out)
{
printf("Failed to open output file\n");
return;
}
/* get the file size */
fseek(file_in, 0, SEEK_END);
file_length = ftell(file_in);
fseek(file_in, 0, SEEK_SET);
/* read it at once */
file_data = malloc(file_length);
int read = fread(file_data,1, file_length, file_in);
printf("read %d bytes... \n", read);
fclose(file_in);
int32_t file_offset = findsig(0);
if(file_offset < 0)
{
printf("Failed to find signature\n");
return -1;
}
while(file_offset >= 0)
{
uint32_t block_start = file_offset;
uint32_t offset = 0;
uint16_t crc_read = 0;
uint16_t crc_calc = 0;
uint8_t block_type