version 0.1 lol

This commit is contained in:
Mykola Korobko 2023-08-10 17:44:34 +03:00 committed by Nick UT3UMS
commit ee0ceba35e
Signed by: ut3ums
GPG Key ID: F4376F9A1CBC995A
3 changed files with 538 additions and 0 deletions

130
EMPTY.ICF Normal file
View File

@ -0,0 +1,130 @@
20550200
#
0000102055020000000000A69C718800C0B63E
00101083105000000000000A143232642D3C00
0020108C051903000000000000000000000000
00301000000000000000000000000000000000
00401000000000000000000000000000000000
00501000000000000000000000000000000000
006010123415935700081F04062C0E01022829
0070100000000000090000FF1F1FF8F80A0E0F
008010000D100C808064321E50505050460A0A
0090101E321E1010140A0A1E14051E003C3C0A
00A0100A0A0A000000000000001A480D240000
00B01020202020202020202020202020202020
00C01020202020202020202020202020202020
00D01000000000000000000000000000000000
00E01000000000000000000000000000000000
00F010065A0B680B0C0A35096409180850080D
010010074D071205440E2405750D3306262306
011010240D1402141715091607161217101805
012010190619111A121B0A1C0C1D051E091F04
01301020092104220A2A0B2C091013110A2802
014010290A1115120D25092704646446464628
01501028642110100A0A0A0606100611110C0C
0160100C070711060095009500950095009500
01701000000000000000000000000000000000
01801000000000000000000000000000000000
01901000000000000000000000000000000000
01A01000000000000000000000000000000000
01B01080080080080080080080080080080080
01C01008008008008008008008000000000000
01D0100000FFFFFFFF81000000000081000000
01E01000008100000000008100000000008100
01F010FF000000000080080003023000010000
02001000FFFF00000000008008000302300001
021010000000FFFF0000000000800800030230
0220100001000000FFFF000000000080080003
02301002300001000000FFFF00000000008008
024010000302300001000000FFFF0000000000
0250108008000302300001000000FFFF000000
02601000008008000302300001000000FFFF00
027010000000008008000302300001000000FF
028010FF000000000080080003023000010000
02901000FFFF00000000008008000302300001
02A010000000FFFF0000000000800800030230
02B0100001000000FFFF000000000080080003
02C01002300001000000FFFF00000000008008
02D010000302300001000000FFFF0000000000
02E0108008000302300001000000FFFF000000
02F01000008008000302300001000000FFFF00
030010000000008008000302300001000000FF
031010FF000000000080080003023000010000
03201000FFFF00000000008008000302300001
033010000000FFFF0000000000800800030230
0340100001000000FFFF000000000080080003
03501002300001000000FFFF00000000008008
036010000302300001000000FFFF0000000000
0370108008000302300001000000FFFF000000
03801000008008000302300001000000FFFF00
039010000000008008000302300001000000FF
03A010FF000000000080080003023000010000
03B01000FFFF00000000008008000302300001
03C010000000FFFF0000000000800800030230
03D0100001000000FFFF000000000080080003
03E01002300001000000FFFF00000000008008
03F010000302300001000000FFFF0000000000
0400108008000302300001000000FFFF000000
04101000008008000302300001000000FFFF00
042010000000008008000302300001000000FF
04301011111FFF190022222FFF190033333FFF
044010190044444FFF190055555FFF19006666
0450106FFF190077777FFF190088888FFF1900
04601099999FFF190000000FFF190000000FFF
047010190000000FFF190000000FFF19000000
0480100FFF190000000FFF190000000FFF1900
04901000000FFF190000000FFF190000000FFF
04A010190000000FFF190000000FFF19000000
04B0100FFF190000000FFF190000000FFF1900
04C01000000FFF190000000FFF190000000FFF
04D010190000000FFF190000000FFF00300000
04E0100FFF003000000FFF003000000FFF0030
04F010000082070011111FFF00008306002222
0500102FFF000083060033333FFF0000830600
05101044444FFF000083060055555FFF000083
052010060066666FFF000083060077777FFF00
0530100083060088888FFF0000830600000000
05401020202020202020002020202020202000
05501020202020202020002020202020202000
05601020202020202020002020202020202000
05701020202020202020002020202020202000
05801020202020202020002020202020202000
05901020202020202020002020202020202000
05A01020202020202020002020202020202000
05B01020202020202020002020202020202000
05C01020202020202020002020202020202000
05D01020202020202020002020202020202000
05E01020202020202020002020202020202000
05F01020202020202020002020202020202000
06001020202020202020002020202020202000
06101020202020202020002020202020202000
06201020202020202020002020202020202000
06301020202020202020002020202020202000
06401020202020202020002020202020202000
06501020202020202020002020202020202000
06601020202020202020002020202020202000
06701020202020202020002020202020202000
06801020202020202020002020202020202000
06901020202020202020002020202020202000
06A01020202020202020002020202020202000
06B01020202020202020002020202020202000
06C01020202020202020002020202020202000
06D01020202020202020002020202020202000
06E01020202020202020002020202020202000
06F01020202020202020002020202020202000
07001020202020202020002020202020202000
07101020202020202020002020202020202000
072010202043414C204200202043414C204100
07301020205245532032002020524553203100
074010202047524F555000202043414C4C3100
075010202043414C4C3200202043414C4C3300
076010202043414C4C3400202043414C4C3500
077010202043414C4C3600202043414C4C3700
078010202043414C4C38000000000000000000
07901000000000000000000000000000000000
07A01001010101010101010101010101010101
07B01001010101010101010101010101010101
07C01020205343414E310020205343414E3200
07D01020205343414E330020205343414E3400
07E01020205343414E35002020202020202000
07F010000000000000000049434F4D20496E63

149
README.org Normal file
View File

@ -0,0 +1,149 @@
* ICEX patcher
** Disclaimer
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, YOU ARE USING THIS AT YOUR OWN RISK. PATCHING THE FIRMWARE MIGHT VOID YOUR TRANSEIVER WARRANTY. ENSURE MAKING A BACKUPS AND THINK OF WHAT ACTIONS YOU ARE PERFORMING. NONE OF THE AUTHORS, CONTRIBUTORS, ADMINISTRATORS, OR ANYONE ELSE CONNECTED WITH THIS REPOSITORY, IN ANY WAY WHATSOEVER, CAN BE RESPONSIBLE FOR YOUR USE OF THE SOFTWARE BELOW.
** Motivation
Icom CS software for IC-F0 model is back from 1997, requires DOSbox and not more usefull than =xxb=. That's how we get IC-CS-X, or ICEX
** TODO Usage
=Syntax: ./ic_f300_patcher.sh -s %channel_numeber%=%valuein kHz% -f %path/to/x6110_app%-p %power_setting% -m %modulation_depth%=
File will be created from EMPTY.ICF template, if not provided.
See =./ic_f300_patcher.sh -h= to see the list of supported values for changing.
Help and fallback is not yet stable, so follow the available values:
| %channel_numeber% | 1-30 |
| %power_setting% | l1, l2, h (default) |
| %modulation_depth%= | w (default) |
Example:
#+NAME: example
#+BEGIN_SRC sh :eval never
./ic_f300_patcher.sh -s 1=172867 -p l1 -m n
#+END_SRC
As soon as this script substitutes the existing values inside the binary, provided values shoud have the same bit-length as default. Otherwise it may lead to the segmentation fault. Remember to backup the firmware.
** Theory behind
Well, it needs a bit of a hex-magic. But valuables are easy find-and-replaceable in hexeditor. Here are some offsets to remember:
Start offset of the Rx freq of the first Channel of the first bank - =0000050b=
Length of channel record is 44 bytes?
#+NAME: theoretical chan mapping
#+BEGIN_SRC bash
#!/bin/bash
result=$(( 0x50b - 0x2c ))
for i in {0..30}; do
result=$(($result + 0x2c))
if [ "$i" -eq 9 ]; then
result=$(( $result + 0x8 ))
elif [ "$i" -eq 14 ]; then
result=$(( $result + 0x8))
elif [ "$i" -eq 23 ]; then
result=$(( $result + 0x8))
fi
printf "%d, 0x%X\n" "$((i + 1))" "$result"
done
#+END_SRC
Here is the comparison of calculated channel offsetts and the real one, obtained from the incremental changes diffing
#+RESULTS: theoretical chan mapping
| ch | offset calculated | real offset |
| 1 | 0x50B | 0x50b |
| 2 | 0x537 | 0x537 |
| 3 | 0x563 | 0x563 |
| 4 | 0x58F | 0x58f |
| 5 | 0x5BB | 0x5bb |
| 6 | 0x5E7 | 0x5e7 |
| 7 | 0x613 | 0x613 |
| 8 | 0x63F | 0x63f |
| 9 | 0x66B | 0x673 |
| 10 | 0x69F | 0x69f |
| 11 | 0x6CB | 0x6cb |
| 12 | 0x6F7 | 0x6f7 |
| 13 | 0x723 | 0x723 |
| 14 | 0x74F | 0x74f |
| 15 | 0x783 | 0x77b |
| 16 | 0x7AF | 0x7b5 |
| 17 | 0x7DB | 0x7db |
| 18 | 0x807 | 0x807 |
| 19 | 0x833 | 0x833 |
| 20 | 0x85F | 0x85f |
| 21 | 0x88B | 0x88b |
| 22 | 0x8B7 | 0x8b7 |
| 23 | 0x8E3 | 0x8e3 |
| 24 | 0x917 | 0x91d |
| 25 | 0x943 | 0x943 |
| 26 | 0x96F | 0x96f |
| 27 | 0x99B | 0x99b |
| 28 | 0x9C7 | 0x9c7 |
| 29 | 0x9F3 | 0x9f3 |
| 30 | 0xA1F | 0xa1f |
| 31 | 0xA4B | |
+ Ch8 is 8 bytes longer
+ Ch15 is 8 bytes longer
+ Ch23 is 8 bytes longer
#+NAME: let's try
#+BEGIN_SRC shell :results output
hexdump -s0x50b -n44 -C FIRST_AN.ICF
#+END_SRC
#+RESULTS: let's try
: 0000050b 31 34 35 35 30 30 31 34 36 36 30 30 30 30 43 30 |14550014660000C0|
: 0000051b 30 43 30 33 30 36 33 30 30 30 30 31 30 30 30 30 |0C03063000010000|
: 0000052b 0d 0a 30 32 30 30 31 30 30 30 46 46 |..02001000FF|
: 00000537
Watch the =14550014600= - Rx and Tx freqs of the first channel
Last channel is 31, let's try and pick it directly
#+BEGIN_SRC shell :results output
hexdump -s$(printf "0x%X" $((0x50b + 29 * 0x2c + 3*0x8))) -n44 -C FIRST_AN.ICF
#+END_SRC
#+RESULTS:
: 00000a1f 31 35 35 36 30 30 31 34 34 37 30 30 0d 0a 30 34 |155600144700..04|
: 00000a2f 30 30 31 30 38 30 30 38 30 30 30 33 30 32 33 30 |0010800800030230|
: 00000a3f 30 30 30 31 30 30 30 30 30 30 46 46 |0001000000FF|
: 00000a4b
*** Channel in details
Rx/Tx frequencies are going one by one. Power bit for ch1 is 0x51e. 19th position, offset 0x13
#+NAME: power bit
#+BEGIN_SRC sh :eval once :results output
cd ~/src/radio/IC-F300
binwalk -i -t -W L1N14480.ICF L2N14480.ICF N144800.ICF
#+END_SRC
#+RESULTS: power bit
:
: OFFSET L1N14480.ICF L2N14480.ICF N144800.ICF
: --------------------------------------------------------------------------------
: *
: 0x00000510 30 31 34 34 38 30 30 38 30 30 38 30 30 30 31 30 |0144800800800010| \ 30 31 34 34 38 30 30 38 30 30 38 30 30 30 32 30 |0144800800800020| \ 30 31 34 34 38 30 30 38 30 30 38 30 30 30 33 30 |0144800800800030|
: *
:
Modulation width for ch1 is 0x523. 24th position, offset 0x18
#+NAME: narrow/wide
#+BEGIN_SRC sh :eval once :results output
binwalk -i -W 144800.ICF N144800.ICF
#+END_SRC
#+RESULTS: narrow/wide
:
: OFFSET 144800.ICF N144800.ICF
: --------------------------------------------------------------------------------
: *
: 0x00000520 32 33 30 30 30 30 31 30 30 30 30 0D 0A 30 32 30 |23000010000..020| \ 32 33 30 38 30 30 31 30 30 30 30 0D 0A 30 32 30 |23080010000..020|
: *
:

259
ic_f300_patcher.sh Executable file
View File

@ -0,0 +1,259 @@
#!/usr/bin/env bash
# pure sh has no implementation of hash tables, bash is present on x6100
MODE="undef"
NO_ARGS=0
E_OPTERROR=85
# TODO: unify keys in constants
# ============================== Option descriptions for help output
declare -A description
description["first_ch"]="icom offset for freqs"
CH_STEP=0x29 # 40 bytes
# ============================== Channel address pointers
declare -A addrs
addrs["1"]=0000050b
addrs["2"]=00000537
addrs["3"]=00000563
addrs["4"]=0000058f
addrs["5"]=000005bb
addrs["6"]=000005e7
addrs["7"]=00000613
addrs["8"]=0000063f
addrs["9"]=00000673
addrs["10"]=0000069f
addrs["11"]=000006cb
addrs["12"]=000006f7
addrs["13"]=00000723
addrs["14"]=0000074f
addrs["15"]=0000077b
addrs["16"]=000007b5
addrs["17"]=000007db
addrs["18"]=00000807
addrs["19"]=00000833
addrs["20"]=0000085f
addrs["21"]=0000088b
addrs["22"]=000008b7
addrs["23"]=000008e3
addrs["24"]=0000091d
addrs["25"]=00000943
addrs["26"]=0000096f
addrs["27"]=0000099b
addrs["28"]=000009c7
addrs["29"]=000009f3
addrs["30"]=00000a1f
# ============================== Power address pointers
declare -A pwr
pwr["l1"]=1
pwr["l2"]=2
pwr["h"]=3
power_offset=0x13
# ============================== Modulation address pointers
declare -A mod
mod["n"]=8
mod["w"]=0
modulation_offset=0x18
help()
{
echo "Script, that patches ICOM IC-F320 firmware"
echo
echo "Keys:"
echo "-s %ch%=%frequency_mhz%"
echo "-h see this help"
echo
echo "Syntax: $0 -s %ch%=%frequency_mhz% [-f %path/to/ICF_FILE%"]
echo "takes one %ch%=%frequency_mhz% pair at once for now"
echo
echo "Filename would be created based on date and time,"
echo "if not provided"
echo
echo "Available options:"
for k in "${!description[@]}"
do
printf " - %s\n" "$k: ${description[$k]}"
done
echo
exit 1
}
# ============================== Argparse
if [ $# -eq "$NO_ARGS" ] # Script invoked with no command-line args?
then
echo "Arguments required"
echo
help
exit $E_OPTERROR
fi
ARG_REGEX="(.+)=(.+)"
while getopts "s:g:p:m:f:h" arg; do
case $arg in
h)
help
;;
s)
# TODO: populate a hashtable here and then cycle throug them in a main cycle
MODE="set"
if [[ $OPTARG =~ $ARG_REGEX ]]
then
key="${BASH_REMATCH[1]}"
value="${BASH_REMATCH[2]}"
else
echo "Syntax error at -s parametr"
exit $E_OPTERROR
fi
;;
g)
# TODO get values
# hexdump -s0x50b -n44 $filename
# and parse
MODE="get"
;;
p)
#TODO power
# l1 l2 h (default)
power="${OPTARG:-l1}"
power=$(echo "$power" | tr '[:upper:]' '[:lower:]')
;;
m)
#todo modulation
# n w (n to default?)
modulation="${OPTARG:-n}"
modulation=$(echo "$modulation" | tr '[:upper:]' '[:lower:]')
;;
f)
file="$OPTARG"
;;
esac
done
# ============================== Main code part
generate_filename() {
# is just date
# cho $(date +'%Y-%m-%d_%H-%M').ICF
echo $(date +'%Y-%m').ICF
}
hexify_string() {
# arg1 - value to prepare for inserting into binary
# returns - hex ascii code
local value="$1"
echo "$value" | xxd -ps | head -c-3
}
calculate_offset() {
# ar1 - initial offset
# arg2 - additional offset
local initial=$1
local additional=$2
echo $(printf "%X" $(( 0x$(echo $initial | sed 's/^0*//') + $additional )))
}
compose_patchstring() {
# arg1 - option offset
# arg2 - value in ASCII
# returns - <addr: hex value> formatted string to use in xxd
local addr="$1"
local val="$2"
echo "<$addr: $(hexify_string $val)>"
}
patch_bin() {
# arg1 - prepared binary patch string
# arg2 - path to the file to parch
# returns - void
local patchstring="$1"
local target="$2"
echo "$patchstring" | xxd -r - "$target"
}
patch_value() {
# arg1 - prepared binary patch string
# arg2 - path to the file to parch
# returns - void
local offset="$1"
local value="$2"
patchstring=$(compose_patchstring $offset $value)
# here we might want to convert csv to number of patchstrings
echo "writing :: $patchstring into $filename"
patch_bin "$patchstring" "$filename"
}
prepare_file(){
# arg1 - prepared binary patch string
local filepath="$1"
if [ -z "$filepath" ]; then
local filename=$(generate_filename)
cp ./EMPTY.ICF "./$filename"
echo "./$filename"
else
if [ ! -f "$filepath" ]; then
cp ./EMPTY.ICF "$filepath"
fi
echo "$filepath"
fi
}
main(){
local ch=$1
local freq=$2
# if no $3, then copy EMPTY.ICF to %date%.icf and patch it
local file=$3
local power=$power
local modulation=$modulation
local chan_offset=${addrs["$ch"]}
# TODO IF MODE
filename=$(prepare_file $file)
patch_value $chan_offset $freq
if [ -n "$power" ]; then
offset=$(calculate_offset $chan_offset $power_offset)
echo $offset
patch_value $offset ${pwr["$power"]}
fi
if [ -n "$modulation" ]; then
offset=$(calculate_offset $chan_offset $modulation_offset)
patch_value $offset ${mod["$modulation"]}
fi
}
# ============================== Sanity checks
# TODO optimize
# if [ -z ${file+x} ]; then echo "No file provided"; exit $E_OPTERROR; fi
# if [ ! -f "$file" ]; then
# echo "File $file does not exist."
# exit $E_OPTERROR
# fi
if [ -z ${key+x} ]; then echo "No channel provided"; exit $E_OPTERROR; fi
if [ -z ${value+x} ]; then echo "No frequency provided"; exit $E_OPTERROR; fi
if [ -z ${addrs["$key"]+x} ]; then
echo "Wrong key: $key"
exit $E_OPTERROR
fi
if [ -n "${power+x}" ] && [ -z "${pwr["$power"]+x}" ]; then
echo "Wrong power setting: $power"
exit $E_OPTERROR
fi
if [ -n "${modulation+x}" ] && [ -z ${mod["$modulation"]+x} ]; then
echo "Wrong moudlation: $modulation"
exit $E_OPTERROR
fi
# we should review arguments string
main $key $value $file #$power $modulation