kopia lustrzana https://github.com/sq5bpf/k5prog
fix flashing firmware larger than 0xe600 bytes
rodzic
15e1dde73e
commit
d68ec83d92
162
README
162
README
|
@ -1,4 +1,4 @@
|
|||
k5prog - Quansheng UV-K5 EEPROM programmer v0.1
|
||||
k5prog - Quansheng UV-K5 EEPROM and flash programmer v0.5
|
||||
(c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
|
||||
This program can read and write the eeprom of Quansheng UV-K5.
|
||||
|
@ -6,12 +6,30 @@ It can read/write arbitrary data, and might be useful for making backups of
|
|||
the configuration, mass programming of radios or reverse engineering of
|
||||
the radio configuration. Please note that it is probably possible to break
|
||||
your radio by writing a bad configuration to it, so please use at your own
|
||||
risk.
|
||||
risk.
|
||||
|
||||
Note that this program does not edit the contents of the eeprom. Use an
|
||||
external hex editor.
|
||||
|
||||
|
||||
The program can also flash the firmware on the Quansheng UV-K5. This will
|
||||
flash the raw binary, and not the Quansheng-encrypted firmware files.
|
||||
A Quansheng-encrypted firmware can be decrypted using the fw.py script from
|
||||
here:
|
||||
https://github.com/fagci/qs-uvk5-firmware-modder
|
||||
An example decrypted file is provided in k5_flash_test.raw, this is the vendor
|
||||
2.01.23 firmware without any modifications.
|
||||
Please use extreme caution, as reprogramming the radioflash can potentially i
|
||||
brick your radio. If unsure, please use the vendor flashing software.
|
||||
|
||||
The flashing support in k5prog was used in at least 2 cases to recover radios
|
||||
which were bricked by flashing firmware using the vendor flasher. I don't know
|
||||
why this worked, but it did.
|
||||
|
||||
|
||||
To compile, please see the compiling section at the end.
|
||||
|
||||
|
||||
The program is written to (hopefully) run on POSIX systems. Testing was done
|
||||
on GNU/Linux, but MacOS X and windows under cygwin should work too.
|
||||
|
||||
|
@ -20,13 +38,38 @@ For licensing see the file LICENSE.
|
|||
|
||||
---- Usage ----
|
||||
|
||||
for help run the programwithout arguments, or with the -h option.
|
||||
|
||||
The configuration options are:
|
||||
Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
|
||||
cmdline opts:
|
||||
-f <file> filename that contains the eeprom dump (default: k5_eeprom.raw)
|
||||
-b <file> filename that contains the raw flash image (default k5_flash.raw)
|
||||
-Y increase "I know what i'm doing" value, to enable functionality likely to break the radio
|
||||
-D wait for the message from the radio flasher, print it's version
|
||||
-F flash firmware, WARNING: this will likely brick your radio!
|
||||
-O offset of block to flash in hex (default: 0)
|
||||
-L length of file to flash in hex (default: all)
|
||||
-r read eeprom
|
||||
-w write eeprom like the original software does
|
||||
-W write most of the eeprom (but without what i think is calibration data)
|
||||
-B write ALL of the eeprom (the "brick my radio" mode)
|
||||
-p <port> device name (default: /dev/ttyUSB0)
|
||||
-s <speed> serial speed (default: 38400, the UV-K5 doesn't accept any other speed)
|
||||
-h print this help
|
||||
-v be verbose, use multiple times for more verbosity
|
||||
|
||||
|
||||
---- Reading/writing the configuration eeprom ----
|
||||
|
||||
For a basic usage use -r to read eeprom, -w to write eeprom. The -v option
|
||||
gives more verbosity.
|
||||
|
||||
Read configuration:
|
||||
|
||||
sq5bpf@chronos:~/k5prog$ ./k5prog -r -v
|
||||
Quansheng UV-K5 EEPROM programmer v0.2 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
|
||||
k5_prepare: try 0
|
||||
****** Connected to firmware version: [k5_2.01.23]
|
||||
|
@ -40,7 +83,7 @@ changed with the -f option.
|
|||
Write configuration from file k5_eeprom.raw:
|
||||
|
||||
sq5bpf@chronos:~/chirp/k5prog$ ./k5prog -w -v
|
||||
Quansheng UV-K5 EEPROM programmer v0.2 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
|
||||
k5_prepare: try 0
|
||||
****** Connected to firmware version: [k5_2.01.23]
|
||||
|
@ -63,22 +106,109 @@ allowing overwriting of calibration data (if there is any) or other data which
|
|||
may be critical to the proper functioning of your radio. I have used this on
|
||||
my radio, and it still works but please be extra-careful.
|
||||
|
||||
I have written the radio eeprom with the -W option tens of times, and others
|
||||
have too. So far it hasn't produced any bad results. But of course beware.
|
||||
|
||||
|
||||
Other configuration options are:
|
||||
---- Flashing support ----
|
||||
|
||||
The flashing support is for the really brave people who know what they are
|
||||
doing (hence the -Y flag is needed).
|
||||
|
||||
It is possible to read the bootloder version using the -D option. This option
|
||||
is safe, but needs the -Y value. Put the radio into flash mode and:
|
||||
|
||||
./k5prog -Y -D
|
||||
|
||||
Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
|
||||
"I know what i'm doing" value set to 1
|
||||
******** k5 command hexdump [obf_len:44 clear_len:36 crc_ok:1 **********
|
||||
## obfuscated ##
|
||||
|
||||
0x00002c |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |a |b |c |d |e |f |
|
||||
---------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+------------
|
||||
0x000000: ab cd 24 00 0e 69 34 e6 2f 93 0f 46 3d 66 85 0a ..$..i4./..F=f..
|
||||
0x000010: 24 44 16 8f 9a 6c 47 e6 1c bf 3d 70 0f 05 e3 40 $D...lG...=p...@
|
||||
0x000020: 27 09 e9 80 16 6c 14 c6 d1 6e dc ba '....l...n..
|
||||
## cleartext ##
|
||||
|
||||
0x000024 |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |a |b |c |d |e |f |
|
||||
---------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+------------
|
||||
0x000000: 18 05 20 00 01 02 02 06 1c 53 50 4a 37 47 ff 0f .. ......SPJ7G..
|
||||
0x000010: 8c 00 53 00 32 2e 30 30 2e 30 36 00 34 0a 00 00 ..S.2.00.06.4...
|
||||
0x000020: 00 00 00 20 ...
|
||||
*****************
|
||||
Flasher version is: [2.00.06]
|
||||
|
||||
The radio can also be flashed with the raw unencrypted binary.
|
||||
An example binary is provided in the k5_flash.raw file (this is the 2.01.23
|
||||
firmware). The binary file can be specified with the -b option.
|
||||
Flashing the radio requires the "i know what i'm doing value" of at least 5.
|
||||
|
||||
./k5prog -b k5_flash.raw -YYYYYY -F
|
||||
|
||||
Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
|
||||
"I know what i'm doing" value set to 6
|
||||
******** k5 command hexdump [obf_len:44 clear_len:36 crc_ok:1 **********
|
||||
## obfuscated ##
|
||||
|
||||
0x00002c |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |a |b |c |d |e |f |
|
||||
---------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+------------
|
||||
0x000000: ab cd 24 00 0e 69 34 e6 2f 93 0f 46 3d 66 85 0a ..$..i4./..F=f..
|
||||
0x000010: 24 44 16 8f 9a 6c 47 e6 1c bf 3d 70 0f 05 e3 40 $D...lG...=p...@
|
||||
0x000020: 27 09 e9 80 16 6c 14 c6 d1 6e dc ba '....l...n..
|
||||
## cleartext ##
|
||||
|
||||
0x000024 |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |a |b |c |d |e |f |
|
||||
---------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+------------
|
||||
0x000000: 18 05 20 00 01 02 02 06 1c 53 50 4a 37 47 ff 0f .. ......SPJ7G..
|
||||
0x000010: 8c 00 53 00 32 2e 30 30 2e 30 36 00 34 0a 00 00 ..S.2.00.06.4...
|
||||
0x000020: 00 00 00 20 ...
|
||||
*****************
|
||||
Flasher version is: [2.00.06]
|
||||
*** FLASH at 0x0000 length 0x0100 result=1
|
||||
*** FLASH at 0x0100 length 0x0100 result=1
|
||||
*** FLASH at 0x0200 length 0x0100 result=1
|
||||
*** FLASH at 0x0300 length 0x0100 result=1
|
||||
etc... until all flash is writtem
|
||||
|
||||
|
||||
It is possible to overwrite only one flash block. Each block has 0x100 bytes
|
||||
size. The offset can be specified by the -O option, and the length by the -L
|
||||
option. The length is rounded up to the nearest block size.
|
||||
|
||||
For example program 0x300 bytes starting at offset 0xe000:
|
||||
|
||||
./k5prog -b k5_flash.raw -YYYYYY -F -L 0x300 -O 0xe000
|
||||
|
||||
Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
|
||||
"I know what i'm doing" value set to 6
|
||||
******** k5 command hexdump [obf_len:44 clear_len:36 crc_ok:1 **********
|
||||
## obfuscated ##
|
||||
|
||||
0x00002c |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |a |b |c |d |e |f |
|
||||
---------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+------------
|
||||
0x000000: ab cd 24 00 0e 69 34 e6 2f 93 0f 46 3d 66 85 0a ..$..i4./..F=f..
|
||||
0x000010: 24 44 16 8f 9a 6c 47 e6 1c bf 3d 70 0f 05 e3 40 $D...lG...=p...@
|
||||
0x000020: 27 09 e9 80 16 6c 14 c6 d1 6e dc ba '....l...n..
|
||||
## cleartext ##
|
||||
|
||||
0x000024 |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |a |b |c |d |e |f |
|
||||
---------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+------------
|
||||
0x000000: 18 05 20 00 01 02 02 06 1c 53 50 4a 37 47 ff 0f .. ......SPJ7G..
|
||||
0x000010: 8c 00 53 00 32 2e 30 30 2e 30 36 00 34 0a 00 00 ..S.2.00.06.4...
|
||||
0x000020: 00 00 00 20 ...
|
||||
*****************
|
||||
Flasher version is: [2.00.06]
|
||||
Writing blocks from address 0xe000 until 0xe300
|
||||
*** FLASH at 0xe000 length 0x0100 result=1
|
||||
*** FLASH at 0xe100 length 0x0100 result=1
|
||||
*** FLASH at 0xe200 length 0x0100 result=1
|
||||
|
||||
Quansheng UV-K5 EEPROM programmer v0.2 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
|
||||
|
||||
cmdline opts:
|
||||
-f <file> filename that contains the eeprom dump (default: k5_eeprom.raw)
|
||||
-r read eeprom
|
||||
-w write eeprom like the original software does
|
||||
-W write most of the eeprom (but without what i think is calibration data)
|
||||
-B write ALL of the eeprom (the "brick my radio" mode)
|
||||
-p <port> device name (default: /dev/ttyUSB0)
|
||||
-s <speed> serial speed (default: 38400, the UV-K5 doesn't accept any other speed)
|
||||
-h print this help
|
||||
-v be verbose, use multiple times for more verbosity
|
||||
|
||||
|
||||
|
||||
|
|
66
k5prog.c
66
k5prog.c
|
@ -50,7 +50,7 @@
|
|||
#include <stdint.h>
|
||||
#include "uvk5.h"
|
||||
|
||||
#define VERSION "Quansheng UV-K5 EEPROM programmer v0.4 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>"
|
||||
#define VERSION "Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>"
|
||||
|
||||
#define MODE_NONE 0
|
||||
#define MODE_READ 1
|
||||
|
@ -651,7 +651,7 @@ int k5_send_flash_version_message(int fd) {
|
|||
return(1);
|
||||
}
|
||||
|
||||
int k5_writeflash(int fd, unsigned char *buf, int len, int offset)
|
||||
int k5_writeflash(int fd, unsigned char *buf, int len, int offset,int max_flash_addr)
|
||||
{
|
||||
int l;
|
||||
unsigned char writeflash[512];
|
||||
|
@ -679,8 +679,10 @@ int k5_writeflash(int fd, unsigned char *buf, int len, int offset)
|
|||
|
||||
writeflash[8]=(offset>>8)&0xff;
|
||||
writeflash[9]=offset&0xff;
|
||||
writeflash[10]=0xe6;
|
||||
//writeflash[10]=0xe6;
|
||||
writeflash[10]=(max_flash_addr>>8)&0xff;
|
||||
writeflash[11]=0x00;
|
||||
//writeflash[11]=max_flash_addr&0xff;
|
||||
writeflash[12]=len&0xff;
|
||||
writeflash[13]=(len>>8)&0xff;
|
||||
writeflash[14]=0x00;
|
||||
|
@ -741,8 +743,10 @@ void helpme()
|
|||
"-f <file>\tfilename that contains the eeprom dump (default: " DEFAULT_FILE_NAME ")\n"
|
||||
"-b <file>\tfilename that contains the raw flash image (default " DEFAULT_FLASH_NAME ")\n"
|
||||
"-Y \tincrease \"I know what i'm doing\" value, to enable functionality likely to break the radio\n"
|
||||
"-D\twait for the message from the radio flasher, print it's version\n"
|
||||
"-F\tflash firmware, WARNING: this will likely brick your radio!\n"
|
||||
"-D \twait for the message from the radio flasher, print it's version\n"
|
||||
"-F \tflash firmware, WARNING: this will likely brick your radio!\n"
|
||||
"-O \toffset of block to flash in hex (default: 0)\n"
|
||||
"-L \tlength of file to flash in hex (default: all)\n"
|
||||
"-r \tread eeprom\n"
|
||||
"-w \twrite eeprom like the original software does\n"
|
||||
"-W \twrite most of the eeprom (but without what i think is calibration data)\n"
|
||||
|
@ -805,7 +809,7 @@ void parse_cmdline(int argc, char **argv)
|
|||
int opt;
|
||||
int tmpval;
|
||||
|
||||
int res;
|
||||
int res;
|
||||
/* cmdline opts:
|
||||
* -f <file>
|
||||
* -b <flash file>
|
||||
|
@ -947,7 +951,8 @@ int main(int argc,char **argv)
|
|||
unsigned char eeprom[UVK5_EEPROM_SIZE];
|
||||
unsigned char flash[UVK5_MAX_FLASH_SIZE];
|
||||
int flash_length;
|
||||
int flash_length2;
|
||||
int flash_max_addr;
|
||||
int flash_max_block_addr;
|
||||
int i,r,j,len;
|
||||
|
||||
printf (VERSION "\n\n");
|
||||
|
@ -999,41 +1004,44 @@ int main(int argc,char **argv)
|
|||
exit(1);
|
||||
}
|
||||
flash_length=read(ffd,(unsigned char *)&flash,UVK5_MAX_FLASH_SIZE);
|
||||
close(ffd);
|
||||
|
||||
/* arbitrary limit do that someone doesn't flash some random short file */
|
||||
if (flash_length<50000) {
|
||||
fprintf(stderr,"Failed to read whole eeprom from file %s (read %i), file too short or some other error\n",file,flash_length);
|
||||
exit(1);
|
||||
}
|
||||
if ((write_length>0)&&((write_length+write_offset)>=UVK5_MAX_FLASH_SIZE)) {
|
||||
fprintf(stderr,"write_length (%d) + write_offset (%d) is bigger than the flash size (%d)\n", write_length, write_offset, UVK5_MAX_FLASH_SIZE);
|
||||
if (verbose>0) { printf ("Read file %s success\n",flash_file); }
|
||||
flash_max_addr=flash_length;
|
||||
|
||||
if (write_length>0) flash_max_addr=write_offset+write_length;
|
||||
if (flash_max_addr>flash_length) flash_max_addr=flash_length;
|
||||
|
||||
if (flash_max_addr&0xff) {
|
||||
flash_max_block_addr=(flash_max_addr&0xff00)+UVK5_FLASH_BLOCKSIZE;
|
||||
} else {
|
||||
flash_max_block_addr=(flash_max_addr&0xff00);
|
||||
}
|
||||
|
||||
printf("Writing blocks from address 0x%x until 0x%x, firmware size is 0x%x\n",write_offset,flash_max_block_addr,flash_length);
|
||||
|
||||
|
||||
if (flash_max_block_addr>UVK5_MAX_FLASH_SIZE) {
|
||||
fprintf(stderr,"flash length 0x%x is greater than max flash size 0x%s\n",flash_max_block_addr,UVK5_MAX_FLASH_SIZE);
|
||||
exit(1);
|
||||
}
|
||||
close(ffd);
|
||||
|
||||
if (verbose>0) { printf ("Read file %s success\n",flash_file); }
|
||||
r=wait_flash_message(fd,10000);
|
||||
if (!r) exit(0);
|
||||
|
||||
k5_send_flash_version_message(fd);
|
||||
|
||||
r=wait_flash_message(fd,10000);
|
||||
if (!r) exit(0);
|
||||
|
||||
k5_send_flash_version_message(fd);
|
||||
|
||||
/* for(i=0; i<flash_length; i+=UVK5_FLASH_BLOCKSIZE) */
|
||||
flash_length2=flash_length;
|
||||
if (write_length>0) {
|
||||
flash_length2=write_offset+write_length;
|
||||
if (flash_length2%UVK5_FLASH_BLOCKSIZE>0) {
|
||||
flash_length2=flash_length2-flash_length2%UVK5_FLASH_BLOCKSIZE+UVK5_FLASH_BLOCKSIZE;
|
||||
}
|
||||
if (flash_length2>flash_length) flash_length2=flash_length;
|
||||
printf("Writing blocks from address 0x%x until 0x%x\n",write_offset,flash_length2);
|
||||
}
|
||||
for(i=write_offset; i<flash_length2; i+=UVK5_FLASH_BLOCKSIZE)
|
||||
for(i=write_offset; i<flash_max_addr; i+=UVK5_FLASH_BLOCKSIZE)
|
||||
{
|
||||
len=flash_length-i;
|
||||
len=flash_max_addr-i;
|
||||
if (len>UVK5_FLASH_BLOCKSIZE) len=UVK5_FLASH_BLOCKSIZE;
|
||||
|
||||
r=k5_writeflash(fd, (unsigned char *)&flash+i,len,i);
|
||||
r=k5_writeflash(fd, (unsigned char *)&flash+i,len,i,flash_max_block_addr);
|
||||
|
||||
printf("*** FLASH at 0x%4.4x length 0x%4.4x result=%i\n",i,len,r);
|
||||
if (!r) {
|
||||
|
|
Ładowanie…
Reference in New Issue