-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #101 from stache3000/uvmod_kitchen_K6_V3.00.15
Partial mods port for firmware v3.00.15
- Loading branch information
Showing
11 changed files
with
350 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
@echo off | ||
@rmdir /q /s temp 2>NUL | ||
@mkdir temp | ||
|
||
@echo Extracting firmare... | ||
python qsfirm.py unpack K6_V3.00.15.bin temp\fw.dec.bin temp\fw.ver.bin | ||
|
||
:: here comment or uncomment mods | ||
|
||
python mod_custom_freq_ranges.py temp\fw.dec.bin | ||
python mod_remove_tx_limits.py temp\fw.dec.bin | ||
python mod_universal_version.py temp\fw.ver.bin | ||
python mod_battery_icon.py temp\fw.dec.bin | ||
python mod_increases_abr_values.py temp\fw.dec.bin | ||
python mod_custom_steps.py temp\fw.dec.bin | ||
|
||
:: end of mods | ||
|
||
@echo Repacking firmware... | ||
python qsfirm.py pack temp\fw.dec.bin temp\fw.ver.bin K6_V3.00.15-MODDED.bin | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/bin/bash | ||
|
||
rm -rf temp 2>/dev/null | ||
mkdir temp | ||
|
||
python3 qsfirm.py unpack K6_V3.00.15.bin temp/fw.dec.bin temp/fw.ver.bin | ||
|
||
# here comment or uncomment mods | ||
|
||
python3 mod_custom_freq_ranges.py temp/fw.dec.bin | ||
python3 mod_remove_tx_limits.py temp/fw.dec.bin | ||
python3 mod_universal_version.py temp/fw.ver.bin | ||
python3 mod_battery_icon.py temp/fw.dec.bin | ||
python3 mod_increases_abr_values.py temp/fw.dec.bin | ||
python3 mod_custom_steps.py temp/fw.dec.bin | ||
|
||
# end of mods | ||
|
||
python3 qsfirm.py pack temp/fw.dec.bin temp/fw.ver.bin K6_V3.00.15-MODDED.bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# the original battery icon looks stupid, with the bars starting on the left and the odd line art. this replaces it with a more familiar design. | ||
# the two offsets used in fw[0xCF18+134:0xCF18+223] limit the data to just the battery bitmaps, while fw[0xCF18:0xCF18] contains the entire set of 8px symbols for future mods | ||
|
||
|
||
##--------------------- do not modify below this line --------------------------------------------------- | ||
import os,sys,struct | ||
print('Running',os.path.basename(sys.argv[0]),'mod...') | ||
|
||
fw = bytearray(open(sys.argv[1],'rb').read()) | ||
|
||
if fw[0xCF18+134:0xCF18+223] == b'>"\x7fAAAAAAAAAAAAAc\x00>"\x7fA]]AAAAAAAAAAc\x00>"\x7fA]]A]]AAAAAAAc\x00>"\x7fA]]A]]A]]AAAAc\x00>"\x7fA]]A]]A]]A]]Ac': | ||
print('Patching battery icon data...') | ||
fw[0xCF18+134:0xCF18+223] = b'>"cAAAAAAAAAAAAA\x7f\x00>"cAAAAAAAAAA]]Ac\x00>"cAAAAAAA]]A]]A\x7f\x00>"cAAAA]]A]]A]]A\x7f\x00>"cA]]A]]A]]A]]A\x7f' | ||
else: | ||
print('ERROR: Cant find data') | ||
sys.exit(0) | ||
|
||
|
||
open(sys.argv[1],'wb').write(fw) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# change below sets to new ones, values are in Hz | ||
new_freq_low_limit = [18_000_000, 76_000_000, 136_000_000, 174_000_000, 350_000_000, 400_000_000, 470_000_000] | ||
new_freq_high_limit = [75_999_900, 135_999_900, 173_999_900, 349_999_900, 399_999_900, 469_999_900, 1300_000_000] | ||
|
||
|
||
|
||
##--------------------- do not modify below this line --------------------------------------------------- | ||
import os,sys,struct | ||
|
||
LOFREQ_FW_LOC = 0xEB30 #v3.00.15 | ||
HIFREQ_FW_LOC = 0xEB4C #v3.00.15 | ||
|
||
print('\n>>> Running',os.path.basename(sys.argv[0]),'mod...') | ||
|
||
#prechecks | ||
if len(new_freq_low_limit)!=7: print('Do not change number of entries! Exiting'); exit(0) | ||
if len(new_freq_high_limit)!=7: print('Do not change number of entries! Exiting'); exit(0) | ||
|
||
|
||
#read fw to buffer | ||
fw = bytearray(open(sys.argv[1],'rb').read()) | ||
|
||
#Show old ranges | ||
print('Replacing ranges:') | ||
current_lo_limits = struct.unpack_from('<IIIIIII', fw, offset=LOFREQ_FW_LOC) | ||
current_hi_limits = struct.unpack_from('<IIIIIII', fw, offset=HIFREQ_FW_LOC) | ||
for i in range(7): | ||
print('Range F{} {:>11} Hz -{:>11} Hz --> {:>11} Hz -{:>11} Hz'.format(i+1, | ||
current_lo_limits[i]*10 , | ||
current_hi_limits[i]*10 , | ||
new_freq_low_limit[i] , | ||
new_freq_high_limit[i] | ||
)) | ||
|
||
|
||
|
||
|
||
|
||
|
||
## REPLACE LOFREQ | ||
if fw[LOFREQ_FW_LOC:LOFREQ_FW_LOC+(4*7)] == bytearray(struct.pack('<IIIIIII', *[5000000, 10800000, 13600000, 17400000, 35000000, 40000000, 47000000])): | ||
print('LOFREQ table found, replacing...') | ||
fw[LOFREQ_FW_LOC:LOFREQ_FW_LOC+(4*7)] = bytearray(struct.pack('<IIIIIII', *[i//10 for i in new_freq_low_limit])) | ||
else: | ||
print('Error, orginal LOFREQ table doesnt match default values. Wrong fw ver?') | ||
|
||
|
||
## REPLACE HIFREQ | ||
if fw[HIFREQ_FW_LOC:HIFREQ_FW_LOC+(4*7)] == bytearray(struct.pack('<IIIIIII', *[7600000, 13599990, 17399990, 34999990, 39999990, 46999990, 60000000])): | ||
print('HIFREQ table found, replacing...') | ||
fw[HIFREQ_FW_LOC:HIFREQ_FW_LOC+(4*7)] = bytearray(struct.pack('<IIIIIII', *[i//10 for i in new_freq_high_limit])) | ||
else: | ||
print('Error, orginal HIFREQ table doesnt match default values. Wrong fw ver?') | ||
|
||
|
||
|
||
|
||
#write fw back | ||
open(sys.argv[1],'wb').write(fw) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# change below sets to new ones, values are in Hz | ||
new_freq_steps = [2500, 5000, 6250, 10000, 12500, 25000, 8330] | ||
|
||
|
||
|
||
##--------------------- do not modify below this line --------------------------------------------------- | ||
import os,sys,struct | ||
if len(new_freq_steps)!=7: print('Do not change number of entries'); exit(0) | ||
|
||
print('Running',os.path.basename(sys.argv[0]),'mod...') | ||
|
||
addr = 0xE170 | ||
|
||
fw = bytearray(open(sys.argv[1],'rb').read()) | ||
current_steps = struct.unpack_from('<HHHHHHH', fw, offset=addr) | ||
print('Old freq steps:', [f'{i*10} Hz' for i in current_steps]) | ||
|
||
|
||
if fw[addr :addr+ 2] == bytearray(struct.pack('<H', 250)): fw[addr :addr+ 2] = struct.pack('<H',new_freq_steps[0]//10); print('.',end='') | ||
if fw[addr+ 2:addr+ 4] == bytearray(struct.pack('<H', 500)): fw[addr+ 2:addr+ 4] = struct.pack('<H',new_freq_steps[1]//10); print('.',end='') | ||
if fw[addr+ 4:addr+ 6] == bytearray(struct.pack('<H', 625)): fw[addr+ 4:addr+ 6] = struct.pack('<H',new_freq_steps[2]//10); print('.',end='') | ||
if fw[addr+ 6:addr+ 8] == bytearray(struct.pack('<H',1000)): fw[addr+ 6:addr+ 8] = struct.pack('<H',new_freq_steps[3]//10); print('.',end='') | ||
if fw[addr+ 8:addr+10] == bytearray(struct.pack('<H',1250)): fw[addr+ 8:addr+10] = struct.pack('<H',new_freq_steps[4]//10); print('.',end='') | ||
if fw[addr+10:addr+12] == bytearray(struct.pack('<H',2500)): fw[addr+10:addr+12] = struct.pack('<H',new_freq_steps[5]//10); print('.',end='') | ||
if fw[addr+12:addr+14] == bytearray(struct.pack('<H', 833)): fw[addr+12:addr+14] = struct.pack('<H',new_freq_steps[6]//10); print('.',end='') | ||
print() | ||
|
||
|
||
current_steps = struct.unpack_from('<HHHHHHH', fw, offset=addr) | ||
print('New freq steps:', [f'{i*10} Hz' for i in current_steps]) | ||
|
||
|
||
|
||
open(sys.argv[1],'wb').write(fw) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# This mod allows you to increase the value of the ABR by 2 by 4 or by 8 , remove # at the beginning of the line , according to the value of interest | ||
|
||
|
||
# multi=int(64) # | ||
# multi=int(128) # (1 corresponds to 2 seconds, 2 corresponds to 4 seconds... up to 5, which corresponds to 10 seconds) | ||
multi=int(192) # (1 corresponds to 4 seconds, 2 corresponds to 8 seconds... up to 5, which corresponds to 20 seconds) | ||
# multi=int(256) # (1 corresponds to 8 seconds, 2 corresponds to 16 seconds... up to 5, which corresponds to 40 seconds) | ||
##--------------------- do not modify below this line --------------------------------------------------- | ||
import os,sys,struct | ||
print('Running',os.path.basename(sys.argv[0]),'mod...') | ||
|
||
fw = bytearray(open(sys.argv[1],'rb').read()) | ||
|
||
if fw[0x57A6] == 0x40 and fw[0x57A7] == 0x00 : | ||
print('Doubling screen timeout values...') | ||
fw[0x57A6:0x57A6+4] = struct.pack('<I',multi) | ||
else: | ||
print('ERROR: Cant find function') | ||
|
||
|
||
open(sys.argv[1],'wb').write(fw) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# change below sets to new ones, values are in Hz | ||
tx_low_limit = 18_000_000 | ||
tx_high_limit = 1_300_000_000 | ||
|
||
|
||
|
||
##--------------------- do not modify below this line --------------------------------------------------- | ||
import os,sys,struct | ||
|
||
TXLOLIM_FW_LOC = 0x1438 | ||
TXHILIM_FW_LOC = 0x143C | ||
BLOCKFN_FW_LOC = 0x173A # CMP R2, #0xCF | ||
|
||
print('\n>>> Running',os.path.basename(sys.argv[0]),'mod...') | ||
fw = bytearray(open(sys.argv[1],'rb').read()) | ||
|
||
|
||
print('Changing TX limit: {} Hz - {} Hz --> {} Hz - {} Hz'.format( | ||
struct.unpack_from('<I', fw, offset=TXLOLIM_FW_LOC)[0]*10, | ||
struct.unpack_from('<I', fw, offset=TXHILIM_FW_LOC)[0]*10, | ||
tx_low_limit, | ||
tx_high_limit | ||
)) | ||
|
||
|
||
fw[TXLOLIM_FW_LOC:TXLOLIM_FW_LOC+4] = struct.pack('<I',tx_low_limit//10) | ||
fw[TXHILIM_FW_LOC:TXHILIM_FW_LOC+4] = struct.pack('<I',tx_high_limit//10) | ||
|
||
|
||
|
||
print('Patching tx_not_allowed() funtion...') | ||
if fw[BLOCKFN_FW_LOC:BLOCKFN_FW_LOC+2] == b'\xcf\x2a': | ||
fw[BLOCKFN_FW_LOC:BLOCKFN_FW_LOC+2] = b'\x5d\xe0' | ||
else: | ||
print('ERROR: Cant find function') | ||
|
||
|
||
|
||
|
||
|
||
open(sys.argv[1],'wb').write(fw) | ||
print('Done') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#nothing to configure here | ||
|
||
##--------------------- do not modify below this line --------------------------------------------------- | ||
import os,sys,struct | ||
print('\n>>> Running',os.path.basename(sys.argv[0]),'mod...') | ||
|
||
fw = bytearray(open(sys.argv[1],'rb').read()) | ||
|
||
print('Setting universal version...', end=' ') | ||
fw[0x0:0x0+1] = b'*' | ||
|
||
open(sys.argv[1],'wb').write(fw) | ||
print('Done') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import sys,os | ||
|
||
|
||
# Handle arguments | ||
if len(sys.argv)!=5 or sys.argv[1] not in ['unpack','pack'] : print(f''' | ||
Usage: {os.path.basename(sys.argv[0])} unpack <encoded_firmware_in.bin> <decoded_firmware_out.bin> <versionfile_out.bin> | ||
{os.path.basename(sys.argv[0])} pack <decoded_firmware_in.bin> <versionfile_in.bin> <encoded_firmware_out.bin> | ||
''') ; exit(1) | ||
|
||
# CRC Routines | ||
Crc16Tab = [0, 4129, 8258, 12387, 16516, 20645, 24774, 28903, 33032, 37161, 41290, 45419, 49548, 53677, 57806, 61935, 4657, 528, 12915, 8786, 21173, 17044, 29431, 25302, | ||
37689, 33560, 45947, 41818, 54205, 50076, 62463, 58334, 9314, 13379, 1056, 5121, 25830, 29895, 17572, 21637, 42346, 46411, 34088, 38153, 58862, 62927, 50604, 54669, 13907, | ||
9842, 5649, 1584, 30423, 26358, 22165, 18100, 46939, 42874, 38681, 34616, 63455, 59390, 55197, 51132, 18628, 22757, 26758, 30887, 2112, 6241, 10242, 14371, 51660, 55789, | ||
59790, 63919, 35144, 39273, 43274, 47403, 23285, 19156, 31415, 27286, 6769, 2640,14899, 10770, 56317, 52188, 64447, 60318, 39801, 35672, 47931, 43802, 27814, 31879, | ||
19684, 23749, 11298, 15363, 3168, 7233, 60846, 64911, 52716, 56781, 44330, 48395,36200, 40265, 32407, 28342, 24277, 20212, 15891, 11826, 7761, 3696, 65439, 61374, | ||
57309, 53244, 48923, 44858, 40793, 36728, 37256, 33193, 45514, 41451, 53516, 49453, 61774, 57711, 4224, 161, 12482, 8419, 20484, 16421, 28742, 24679, 33721, 37784, 41979, | ||
46042, 49981, 54044, 58239, 62302, 689, 4752, 8947, 13010, 16949, 21012, 25207, 29270, 46570, 42443, 38312, 34185, 62830, 58703, 54572, 50445, 13538, 9411, 5280, 1153, 29798, | ||
25671, 21540, 17413, 42971, 47098, 34713, 38840, 59231, 63358, 50973, 55100, 9939, 14066, 1681, 5808, 26199, 30326, 17941, 22068, 55628, 51565, 63758, 59695, 39368, | ||
35305, 47498, 43435, 22596, 18533, 30726, 26663, 6336, 2273, 14466, 10403, 52093, 56156, 60223, 64286, 35833, 39896, 43963, 48026, 19061, 23124, 27191, 31254, 2801, | ||
6864, 10931, 14994, 64814, 60687, 56684, 52557, 48554, 44427, 40424, 36297, 31782, 27655, 23652, 19525, 15522, 11395, 7392, 3265, 61215, 65342, 53085, 57212, 44955, | ||
49082, 36825, 40952, 28183, 32310, 20053, 24180, 11923, 16050, 3793, 7920] | ||
|
||
def crc16_ccitt(data): | ||
i2 = 0 | ||
for i3 in range(0, len(data)): | ||
out = Crc16Tab[((i2 >> 8) ^ data[i3]) & 255] | ||
i2 = out ^ (i2 << 8) | ||
return 65535 & i2 | ||
|
||
def crc16_ccitt_le(data): | ||
crc = crc16_ccitt(data) | ||
return bytes([crc & 0xFF,]) + bytes([crc>>8,]) | ||
|
||
|
||
# Encoding/decoding algo | ||
def firmware_xor(fwcontent): | ||
XOR_ARRAY = bytes.fromhex('4722c0525d574894b16060db6fe34c7cd84ad68b30ec25e04cd9007fbfe35405e93a976bb06e0cfbb11ae2c9c15647e9baf142b6675f0f96f7c93c841b26e14e3b6f66e6a06ab0bfc6a5703aba189e271a535b71b1941e18f2d6810222fd5a2891dbba5d64c6fe86839c501c730311d6af30f42c77b27dbb3f29285722d6928b') | ||
XOR_LEN = len(XOR_ARRAY) | ||
|
||
ba=bytearray(fwcontent) | ||
for i in range(0,len(ba)): | ||
ba[i] ^= XOR_ARRAY[i%XOR_LEN] | ||
return bytes(ba) | ||
|
||
|
||
|
||
#-------- main ------------------ | ||
if sys.argv[1]=='unpack': | ||
encoded_firmware = open(sys.argv[2],'rb').read() | ||
#check CRC, information only | ||
if crc16_ccitt_le(encoded_firmware[:-2]) == encoded_firmware[-2:]: | ||
print('CRC OK') | ||
else: | ||
print('CRC MISMATCH!') | ||
|
||
decoded_firmware = firmware_xor(encoded_firmware[:-2]) | ||
|
||
#save decoded firmware to file | ||
open(sys.argv[3],'wb').write(decoded_firmware[:0x2000]+decoded_firmware[0x2000+16:]) | ||
print(f'Saved decoded firmware to {sys.argv[3]}') | ||
|
||
#save 16 bytes with version string to file | ||
open(sys.argv[4],'wb').write(decoded_firmware[0x2000:0x2000+16]) | ||
print(f'Saved version info to {sys.argv[4]}') | ||
|
||
|
||
|
||
|
||
elif sys.argv[1]=='pack': | ||
decoded_firmware = open(sys.argv[2],'rb').read() | ||
|
||
# visual indicator for firmware size and big warning if too big | ||
current_size = len(decoded_firmware) | ||
max_size = 0xefff | ||
|
||
percentage = (current_size / max_size) * 100 | ||
bar_length = int(percentage / 2) # Assuming each character represents 2% progress | ||
size_bar = '[' + '=' * bar_length + ' ' * (50 - bar_length) + ']' | ||
|
||
print(f"\n\nFirmware takes up {current_size}/{max_size} bytes of available space:") | ||
print(f"Flash usage: {size_bar} {percentage:.2f}%\n\n") | ||
|
||
if current_size > max_size: | ||
print("WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING") | ||
print("WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING") | ||
print("WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING") | ||
print("WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING\n") | ||
print("WARNING: Firmware size exceeds the maximum allowed size of 0xefff (61439) bytes!") | ||
print("Using an oversize firmware will not work correctly and may lead to freezes, crashes and defects.\n") | ||
|
||
|
||
version_info = open(sys.argv[3],'rb').read()[0:16] | ||
|
||
firmware_with_version = decoded_firmware[0:0x2000] + version_info + decoded_firmware[0x2000:] | ||
firmware_with_version_encoded = firmware_xor(firmware_with_version) | ||
|
||
open(sys.argv[4],'wb').write(firmware_with_version_encoded+crc16_ccitt_le(firmware_with_version_encoded)) | ||
print(f'Saved encoded firmware to {sys.argv[4]}') | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
## Create your own custom rom for Quansheng UV-K5! | ||
|
||
### Prerequisites | ||
- Windows | ||
- [Latest python](https://www.python.org/downloads/) installed | ||
|
||
### How to use this? | ||
- customize included mods, for example `mod_custom_freq_ranges.py` has possibility to edit frequency ranges | ||
- edit `build.bat`/`build.sh`, if you want omit execution of any mod, prefix its line with `::` or `rem` (`#` in `build.sh`) | ||
- [start command prompt](https://www.google.com/search?q=how+to+open+command+prompt+windows) in `uvmod_kitchen_31` directory | ||
- run command `build.bat`/`build.sh` | ||
- look for any errors | ||
- now you can flash new firmware file named `K6_V3.00.15-MODDED.bin` | ||
|
||
## List of mods | ||
Porting most useful mods from v2.01.31 to v3.00.15, for now below mods are ported: | ||
- `mod_custom_freq_ranges.py` - customize frequency ranges F1 - F7 | ||
- `mod_remove_tx_limits.py` - completely removes transmit limits | ||
- `mod_universal_version.py` - allow to flash output firmware also on `UV-K6` and `UV-5R PLUS` | ||
- `mod_battery_icon.py` - fix original stupid battery icon | ||
- `mod_increases_abr_values.py` - increase the value of the ABR by factor 2, 4 or 8 | ||
- `mod_remove_tx_limits.py` - remove TX LImits | ||
|