Porównaj commity

...

14 Commity

Autor SHA1 Wiadomość Data
sq5bpf 241ab18b61 warn of firmware flash mode when in eeprom read mode 2023-12-29 23:07:47 +01:00
sq5bpf e4b2c47d17 wait for only 0x518 command on flashing 2023-12-29 22:20:34 +01:00
sq5bpf 350e667c5d minor fixes 2023-12-29 21:28:17 +01:00
sq5bpf 3eb6e144fc minor fixes 2023-12-29 21:27:50 +01:00
sq5bpf 990eeb60aa
Merge pull request #15 from brohee/main
Various messages / comments improvements
2023-12-29 19:19:20 +01:00
sq5bpf 767688f746
Merge pull request #19 from wutje/fix_wrong_filename
Fix wrong filename printed in open failure message.
2023-12-29 19:17:33 +01:00
sq5bpf 4e6ebbc760
Merge pull request #20 from wutje/fix_out_of_sync
Fix 3 rx handling bugs; timeout, short read, out-of-sync
2023-12-29 19:12:47 +01:00
Wouter van Gulik c42c8b9f9d Fix 3 rx handling bugs; timeout, short read, out-of-sync.
When not plugging in the radio we expect to only see timeout errors.
However due to timeout being checked AFTER the read() call the len parameter
was updated and no longer was 0 returned.

If less then 4 was read (a short read) then uninitialized data was used,
for length and/or magic check.

If the magic byte does not match then the  rx buffer should be flushed before
trying again. Otherwise sync will probably never be achieved. This
solves the bug where plugging in the radio show continues streams of
magic packet errors. For me k5prog -Y -D now always works, while before
it could fail.
2023-12-18 22:32:46 +13:00
Wouter van Gulik 32b6d4bb9d Fix wrong filename printed in open failure message.
The eeprom filename was printed instead of flash filename.
This really confused me.
2023-12-18 22:08:16 +13:00
Bruno Rohée 83e1118a41
typo fix 2023-11-07 13:51:15 +01:00
Bruno Rohée bc02b2460c
Various typo fixed 2023-11-06 14:14:41 +01:00
Bruno Rohée a3faca61d9
Better messages 2023-11-06 14:12:43 +01:00
Bruno Rohée a9e37bbd50
eeprom -> EEPROM 2023-11-06 14:07:31 +01:00
Bruno Rohée 81db753247
eeprom -> EEPROM 2023-11-06 14:05:18 +01:00
3 zmienionych plików z 80 dodań i 66 usunięć

58
README
Wyświetl plik

@ -1,14 +1,14 @@
k5prog - Quansheng UV-K5 EEPROM and flash programmer v0.9
(c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
This program can read and write the eeprom of Quansheng UV-K5.
This program can read and write the EEPROM of Quansheng UV-K5.
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.
Note that this program does not edit the contents of the eeprom. Use an
Note that this program does not edit the contents of the EEPROM. Use an
external hex editor.
@ -19,7 +19,7 @@ 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
Please use extreme caution, as reprogramming the radioflash can potentially
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
@ -31,38 +31,38 @@ 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.
on GNU/Linux, but macOS and Windows under Cygwin should work too.
For licensing see the file LICENSE.
---- Usage ----
for help run the programwithout arguments, or with the -h option.
to display help run the program without arguments, or with the -h option.
The configuration options are:
Quansheng UV-K5 EEPROM programmer v0.8 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
cmdline opts:
-f <file> filename that contains the eeprom dump (default: k5_eeprom.raw)
-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
-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!
-M <ver> Set the firmware major version to <ver> during the flash process (default: *.01.23)
-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)
-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 ----
---- Reading/writing the configuration EEPROM ----
For a basic usage use -r to read eeprom, -w to write eeprom. The -v option
For a basic usage use -r to read EEPROM, -w to write EEPROM. The -v option
gives more verbosity.
Read configuration:
@ -72,10 +72,10 @@ Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowsk
k5_prepare: try 0
****** Connected to firmware version: [k5_2.01.23]
Sucessfuly read eeprom
Successfully read EEPROM
The eeprom contents are written to the file k5_eeprom.raw, this can be
The EEPROM contents are written to the file k5_eeprom.raw, this can be
changed with the -f option.
@ -87,14 +87,14 @@ Quansheng UV-K5 EEPROM programmer v0.5 (c) 2023 Jacek Lipkowski <sq5bpf@lipkowsk
k5_prepare: try 0
****** Connected to firmware version: [k5_2.01.23]
Read file k5_eeprom.raw success
Sucessfuly wrote eeprom
Successfully wrote EEPROM
The -w option writes only the memory blocks which are written by the original
radio software, in the same order.
The -W option is a bit more brave, it writes all memory upto 0x1d00. I _think_
The -W option is a bit braver as it writes all memory upto 0x1d00. I _think_
that the radio has calibration data above this address, but of course this is
not certain, because this knowledge is a result of reverse engineering, and not
information from the manufacturer.
@ -105,7 +105,7 @@ 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
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.
@ -114,14 +114,14 @@ have too. So far it hasn't produced any bad results. But of course beware.
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
It is possible to read the bootloader 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
"I know what I'm doing" value set to 1
******** k5 command hexdump [obf_len:44 clear_len:36 crc_ok:1 **********
## obfuscated ##
@ -143,13 +143,13 @@ 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.
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
"I know what I'm doing" value set to 6
******** k5 command hexdump [obf_len:44 clear_len:36 crc_ok:1 **********
## obfuscated ##
@ -190,19 +190,19 @@ simple makefile:
sq5bpf@dellix:~/k5prog-0.1$ make
gcc -O2 k5prog.c -o k5prog
Other POSIX platforms should work also, including MacOS X.
Other POSIX platforms should work also, including macOS.
The software compiles under Cygwin/Microsoft Windows, but has not been tested.
According to the cygwin documentation you should use /dev/comX to use port comX
According to the Cygwin documentation you should use /dev/comX to use port comX
(for example using com6: k5prog.exe -v -r -p /dev/com6)
If port this to another platform, or do anything interesting with this
If you port this to another platform, or do anything interesting with this
software, tell me about it.
---- Other uses ----
The file uvk5_original_eeprom.raw contains an eeprom downloaded from a UV-K5
The file uvk5_original_eeprom.raw contains an EEPROM downloaded from an UV-K5
radio. Maybe it can be used to resurrect another radio of the same type
if it was broken (perhaps by the use of this software :).
@ -220,13 +220,13 @@ The format of the datagram sent to the radio is:
0xAB 0xCD len 0x00 <data bytes> <2 bytes CRC> 0xDC 0xBA
The length is the length od the data bytes.
The length is the length of the data bytes.
The data is protected by a typical CRC-16 xmodem algorithm.
The data bytes and the CRC are obfuscated by xor-in it with an 8-byte
sequence.
Fortunately the eeprom data contains a lot of 0xFF and 0x00 bytes, so the XOR
Fortunately the EEPROM data contains a lot of 0xFF and 0x00 bytes, so the XOR
sequence is easy to find by observing the traffic.
@ -235,7 +235,7 @@ The datagram sent from the radio is the same, but the CRC field is set to
obfuscation (same as the XOR).
I intend to publish a further description of the protocol, and the eeprom
I intend to publish a further description of the protocol, and the EEPROM
contents, meanwhile the sources can be used as documentation.

Wyświetl plik

@ -1,7 +1,7 @@
/* Quansheng UV-K5 EEPROM programmer v0.9
* (c) 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
*
* This program can read and write the eeprom of Quansheng UVK5 Mark II
* This program can read and write the EEPROM of Quansheng UVK5 Mark II
* and probably other similar radios via the serial port.
*
* It can read/write arbitrary data, and might be useful for reverse
@ -110,8 +110,8 @@ unsigned char uvk5_hello2[]={0x14, 0x05, 0x04, 0x00, 0x9f, 0x25, 0x5a, 0x64};
/* commands:
* 0x14 - hello
* 0x1b - read eeprom
* 0x1d - write eeprom
* 0x1b - read EEPROM
* 0x1d - write EEPROM
* 0xdd - reset radio
*/
@ -229,6 +229,13 @@ int read_timeout(int fd, unsigned char *buf, int maxlen, int timeout)
ret=select(fd+1,&rfd,0,0,&tv);
if (ret==0) {
if(timeout) /* Only print if we requested a timeout */
fprintf(stderr,"read_timeout\n");
/* error or timeout */
break;
}
if (FD_ISSET(fd,&rfd)) {
nr=read(fd,buf,maxlen);
@ -236,17 +243,9 @@ int read_timeout(int fd, unsigned char *buf, int maxlen, int timeout)
buf=buf+nr;
if (nr>=0) maxlen=maxlen-nr;
if (maxlen==0) break;
}
if (ret==0) {
fprintf(stderr,"read_timeout\n");
/* error albo timeout */
break;
}
}
if (verbose>2) {
if (verbose>2 && len > 0) {
printf("RXRXRX:\n");
hdump(buf2,len);
}
@ -427,11 +426,22 @@ struct k5_command *k5_receive(int fd,int tmout) {
return(0);
}
/* During plugging in etc we can receive a single byte.
* Handle this case here. */
if (len != sizeof(buf))
{
fprintf(stderr,"k5_receive: got %d expected %ld\n", len, sizeof(buf));
return(0);
}
if ((buf[0]!=0xab)||(buf[1]!=0xcd)) {
fprintf(stderr,"k5_receive: bad magic number\n");
return(0);
}
if ((buf[0]!=0xab)||(buf[1]!=0xcd)) {
fprintf(stderr,"k5_receive: bad magic number\n");
/* Assume we are out of sync and flush rx buffer by reading everything.
* This works because the boot message is repeated. */
while (len>0)
len =read_timeout(fd,(unsigned char *)&buf,sizeof(buf),10000);
return(0);
}
if (buf[3]!=0) {
fprintf(stderr,"k5_receive: it seems that byte 3 can be something else than 0, please notify the author\n");
@ -455,7 +465,7 @@ struct k5_command *k5_receive(int fd,int tmout) {
return(cmd);
}
/******************************/
/* eeprom read/write support */
/* EEPROM read/write support */
/******************************/
int k5_readmem(int fd, unsigned char *buf, unsigned char maxlen, int offset)
{
@ -542,7 +552,7 @@ int k5_reset(int fd)
r=k5_send_buf(fd,uvk5_reset,sizeof(uvk5_reset));
return(r);
}
/* end of eeprom read/write support */
/* end of EEPROM read/write support */
/******************************/
@ -564,8 +574,9 @@ int wait_flash_message(int fd,int ntimes) {
cmd=k5_receive(fd,10000);
if (!cmd) {
printf("wait_flash_message: timeout\n");
continue;
/* No need to print, k5_receive already printed why it failed */
//printf("wait_flash_message: timeout\n");
continue;
}
k5_hexdump(cmd);
@ -576,8 +587,8 @@ int wait_flash_message(int fd,int ntimes) {
continue;
}
if (cmd->cmd[0]!=0x18) {
printf("wait_flash_message: got unexpected command type 0x%2.2x\n",cmd->cmd[0]);
if ((cmd->cmd[0]!=0x18)&&(cmd->cmd[1]!=0x05)) {
printf("wait_flash_message: got unexpected command type 0x%2.2x 0x%2.2x\n",cmd->cmd[1],cmd->cmd[0]);
destroy_k5_struct(cmd);
continue;
}
@ -600,11 +611,6 @@ int wait_flash_message(int fd,int ntimes) {
* 0x000020: 00 00 00 20 ...
*/
if ((cmd->cmd[2]!=0x20)||(cmd->cmd[3]!=0x0)||(cmd->cmd[4]!=0x1)||(cmd->cmd[5]!=0x2)||(cmd->cmd[6]!=0x2)) {
printf("wait_flash_message: got unexpected packet contents\n");
destroy_k5_struct(cmd);
continue;
}
/* all is good, so break */
ok=1; break;
@ -748,14 +754,14 @@ void helpme()
"cmdline opts:\n"
"-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"
"-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"
"-M <ver> \tSet the firmware major version to <ver> during the flash process (default: " DEFAULT_FLASH_VERSION ")\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"
"-B \twrite ALL of the eeprom (the \"brick my radio\" mode)\n"
"-W \twrite most of the EEPROM (but without what I think is calibration data)\n"
"-B \twrite ALL of the EEPROM (the \"brick my radio\" mode)\n"
"-p <port>\tdevice name (default: " DEFAULT_SERIAL_PORT ")\n"
"-s <speed>\tserial speed (default: 38400, the UV-K5 doesn't accept any other speed)\n"
"-h \tprint this help\n"
@ -929,6 +935,14 @@ int k5_prepare(int fd) {
cmd=k5_receive(fd,10000);
if (!cmd) return(0);
/* this is a bit problem with people trying to read the radio config in firmware flash mode,
* don't know why people do this, but they do it quite often */
if ((cmd->cmd[0]==0x18)&&(cmd->cmd[1]==0x05)) {
fprintf(stderr,"\nWARNING: this radio is in firmware flash mode (PTT + turn on).\n"
"Please have the radio in normal mode to read the EEPROM\n\n");
return(0);
}
printf ("cmd: %2.2x %2.2x ok:%i\n",cmd->cmd[0],cmd->cmd[1],cmd->crcok);
printf("****** Connected to firmware version: [%s]\n",(cmd->cmd)+4);
destroy_k5_struct(cmd);
@ -990,7 +1004,7 @@ int main(int argc,char **argv)
ffd=open(flash_file,O_RDONLY);
if (ffd<0) {
fprintf(stderr,"open %s error %d %s\n", file, errno, strerror(errno));
fprintf(stderr,"open %s error %d %s\n", flash_file, errno, strerror(errno));
exit(1);
}
flash_length=read(ffd,(unsigned char *)&flash,UVK5_MAX_FLASH_SIZE);
@ -998,7 +1012,7 @@ int main(int argc,char **argv)
/* arbitrary limit do that someone doesn't flash some random short file */
if ((i_know_what_im_doing<5)&&(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);
fprintf(stderr,"Failed to read whole EEPROM from file %s (read %i), file too short or some other error\n",file,flash_length);
if (flash_length>0) {
fprintf(stderr,"This failsafe is here so that people don't mistake config files with flash.\nIt can be ignored with an 'i know what i'm doing' value of at least 5\n");
}
@ -1079,7 +1093,7 @@ int main(int argc,char **argv)
}
}
close(fd);
if (verbose>0) { printf("\rSucessfuly read eeprom\n"); }
if (verbose>0) { printf("\rSuccessfully read EEPROM\n"); }
if (verbose>2) { hdump((unsigned char *)&eeprom,UVK5_EEPROM_SIZE); }
write_file(file,(unsigned char *)&eeprom,UVK5_EEPROM_SIZE);
@ -1090,7 +1104,7 @@ int main(int argc,char **argv)
case MODE_WRITE_MOST:
case MODE_WRITE_ALL:
if ((mode==MODE_WRITE_ALL)&&(i_know_what_im_doing<1)) {
printf("ERROR: the \"I know what i'm doing\" value has to be at least 1 to confirm that you know what you're doing\n");
printf("ERROR: the \"I know what I'm doing\" value has to be at least 1 to confirm that you know what you're doing\n");
exit(0);
}
@ -1102,7 +1116,7 @@ int main(int argc,char **argv)
}
r=read(ffd,(unsigned char *)&eeprom[i],UVK5_EEPROM_SIZE);
if (r!=UVK5_EEPROM_SIZE) {
fprintf(stderr,"Failed to read whole eeprom from file %s, file too short?\n",file);
fprintf(stderr,"Failed to read whole EEPROM from file %s, file too short?\n",file);
exit(1);
}
close(ffd);
@ -1146,7 +1160,7 @@ int main(int argc,char **argv)
}
}
k5_reset(fd);
if (verbose>0) { printf("\rSucessfuly wrote eeprom\n"); }
if (verbose>0) { printf("\rSuccessfully wrote EEPROM\n"); }
break;

2
uvk5.h
Wyświetl plik

@ -1,4 +1,4 @@
/* UV-K5 eeprom programmer */
/* UV-K5 EEPROM programmer */
#ifndef UVK5_INCLUDE_H
#define UVK5_INCLUDE_H