Implemented additional checks. Add force flag to flash firmware even if modem is in BIOS mode.
This commit is contained in:
@@ -18,6 +18,7 @@ func FwExists(path string) bool {
|
|||||||
return !errors.Is(err, os.ErrNotExist)
|
return !errors.Is(err, os.ErrNotExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChkHeader: runs header and CRC checks on the firmware file
|
||||||
func ChkHeader(fwfile string) error {
|
func ChkHeader(fwfile string) error {
|
||||||
log.Info("checking ", fwfile)
|
log.Info("checking ", fwfile)
|
||||||
// SCS has two different file layouts, one for the "Dragons", the other for any older modem
|
// SCS has two different file layouts, one for the "Dragons", the other for any older modem
|
||||||
@@ -62,9 +63,7 @@ func ChkHeader(fwfile string) error {
|
|||||||
size = uint32(binary.LittleEndian.Uint16(firmware[2:4])) // PTC-3 and Co
|
size = uint32(binary.LittleEndian.Uint16(firmware[2:4])) // PTC-3 and Co
|
||||||
}
|
}
|
||||||
a := make([]byte, 4)
|
a := make([]byte, 4)
|
||||||
//binary.LittleEndian.PutUint32(a, crc32.ChecksumIEEE(firmware[4:size+4])) // PTC-3
|
|
||||||
binary.LittleEndian.PutUint32(a, crc32.ChecksumIEEE(firmware[offset:offset+size]))
|
binary.LittleEndian.PutUint32(a, crc32.ChecksumIEEE(firmware[offset:offset+size]))
|
||||||
//if bytes.Equal(a, firmware[4+size:8+size]) { // PTC-3
|
|
||||||
if bytes.Equal(a, firmware[offset+size:offset+size+4]) {
|
if bytes.Equal(a, firmware[offset+size:offset+size+4]) {
|
||||||
log.Info("CRC checksum ok!")
|
log.Info("CRC checksum ok!")
|
||||||
} else {
|
} else {
|
||||||
|
15
main.go
15
main.go
@@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2021 Torsten Harenberg DL1THM. All rights reserved.
|
||||||
|
|
||||||
|
// A SCS PACTOR modem flashing utility written in Go. Should run anywhere Go runs.
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -16,8 +20,11 @@ func main() {
|
|||||||
serialDevice := parser.String("s", "serialDevice", &argparse.Options{Required: false, Help: "(optional) serial device the modem is attached to, e.g. /dev/ttyUSB0. If not set, go-scsupdate will search for SCS modems."})
|
serialDevice := parser.String("s", "serialDevice", &argparse.Options{Required: false, Help: "(optional) serial device the modem is attached to, e.g. /dev/ttyUSB0. If not set, go-scsupdate will search for SCS modems."})
|
||||||
brate := parser.Int("b", "baudrate", &argparse.Options{Required: false, Help: "(optional, required when -s is set) sets the serial baudrate, e.g. 115200"})
|
brate := parser.Int("b", "baudrate", &argparse.Options{Required: false, Help: "(optional, required when -s is set) sets the serial baudrate, e.g. 115200"})
|
||||||
f := parser.String("f", "file", &argparse.Options{Required: true, Help: "(required) the file to flash, e.g. profi41r.pro"})
|
f := parser.String("f", "file", &argparse.Options{Required: true, Help: "(required) the file to flash, e.g. profi41r.pro"})
|
||||||
|
|
||||||
debug := parser.Flag("d", "debug", &argparse.Options{Required: false, Help: "(optional) enable debug logs"})
|
debug := parser.Flag("d", "debug", &argparse.Options{Required: false, Help: "(optional) enable debug logs"})
|
||||||
dryrun := parser.Flag("n", "dryrun", &argparse.Options{Required: false, Help: "(optional) drying: if set, modem will detected but no firmware being written"})
|
dryrun := parser.Flag("n", "dryrun", &argparse.Options{Required: false, Help: "(optional) drying: if set, modem will detected but no firmware being written"})
|
||||||
|
force := parser.Flag("", "force", &argparse.Options{Required: false, Help: "(optional) skip testing if firmware fits modem. Useful if the modem is bricked and you need to put it into BIOS mode. Read the manual!"})
|
||||||
|
sertimeout := parser.Int("t", "timeout", &argparse.Options{Required: false, Help: "(optional) Sets the read and write timeout. Default: 70. If you have handshake problems, enlarge this values, especially for older modems."})
|
||||||
err := parser.Parse(os.Args)
|
err := parser.Parse(os.Args)
|
||||||
cLog := console.New(true)
|
cLog := console.New(true)
|
||||||
if *debug {
|
if *debug {
|
||||||
@@ -27,6 +34,10 @@ func main() {
|
|||||||
log.AddHandler(cLog, log.InfoLevel, log.ErrorLevel, log.AlertLevel, log.WarnLevel, log.NoticeLevel, log.PanicLevel)
|
log.AddHandler(cLog, log.InfoLevel, log.ErrorLevel, log.AlertLevel, log.WarnLevel, log.NoticeLevel, log.PanicLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *sertimeout == 0 { // if not set, set the write / read timeout to 70
|
||||||
|
*sertimeout = 70
|
||||||
|
}
|
||||||
|
|
||||||
if *serialDevice != "" && *brate == 0 {
|
if *serialDevice != "" && *brate == 0 {
|
||||||
log.Fatal("ERROR: if you specify a device, you need to specify a baud rate as well. Cannot continue")
|
log.Fatal("ERROR: if you specify a device, you need to specify a baud rate as well. Cannot continue")
|
||||||
}
|
}
|
||||||
@@ -79,9 +90,9 @@ func main() {
|
|||||||
if *dryrun != true {
|
if *dryrun != true {
|
||||||
var err error
|
var err error
|
||||||
if *serialDevice != "" {
|
if *serialDevice != "" {
|
||||||
err = update.Update(*serialDevice, baudrate, *f)
|
err = update.Update(*serialDevice, baudrate, *sertimeout, *f, *force)
|
||||||
} else {
|
} else {
|
||||||
err = update.Update(ports[0].Port, baudrate, *f)
|
err = update.Update(ports[0].Port, baudrate, *sertimeout, *f, *force)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
|
@@ -14,22 +14,25 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Size of a "firmware packet" over the serial line
|
||||||
const CHUNKSIZE = 256
|
const CHUNKSIZE = 256
|
||||||
|
|
||||||
type modem struct {
|
type modem struct {
|
||||||
port serial.Port
|
port serial.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
func initmodem(serport string, baudrate int) (*modem, error) {
|
// initmodem: opens the serial line, returns instance of serial.Port
|
||||||
|
func initmodem(serport string, baudrate int, sertimeout int) (*modem, error) {
|
||||||
p, err := serial.Open(serport,
|
p, err := serial.Open(serport,
|
||||||
serial.WithBaudrate(baudrate),
|
serial.WithBaudrate(baudrate),
|
||||||
serial.WithDataBits(8),
|
serial.WithDataBits(8),
|
||||||
serial.WithParity(serial.NoParity),
|
serial.WithParity(serial.NoParity),
|
||||||
serial.WithStopBits(serial.OneStopBit),
|
serial.WithStopBits(serial.OneStopBit),
|
||||||
serial.WithReadTimeout(70),
|
serial.WithReadTimeout(sertimeout),
|
||||||
serial.WithWriteTimeout(70)) // 50 was not stable, bump to 70
|
serial.WithWriteTimeout(sertimeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("ERROR: File %s could not be opened\n", serport)
|
fmt.Printf("ERROR: File %s could not be opened\n", serport)
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -38,9 +41,12 @@ func initmodem(serport string, baudrate int) (*modem, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write: writes to the serial ports, returns answer and logs output
|
||||||
func (m *modem) write(out string, nolog ...bool) ([]byte, error) {
|
func (m *modem) write(out string, nolog ...bool) ([]byte, error) {
|
||||||
if len(nolog) == 0 {
|
if len(nolog) == 0 {
|
||||||
log.Debug("Sending " + out)
|
log.Debug("Sending " + strings.TrimFunc(out, func(r rune) bool {
|
||||||
|
return !unicode.IsGraphic(r)
|
||||||
|
}))
|
||||||
} else {
|
} else {
|
||||||
if len(out) < 200 { // in other cases it's the firmware!
|
if len(out) < 200 { // in other cases it's the firmware!
|
||||||
log.Debugf("Sending %d byte(s)", len(out))
|
log.Debugf("Sending %d byte(s)", len(out))
|
||||||
@@ -67,6 +73,7 @@ func (m *modem) write(out string, nolog ...bool) ([]byte, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getSerNum: tries to find out the serial number of the modem.
|
||||||
func (m *modem) getSerNum() (string, error) {
|
func (m *modem) getSerNum() (string, error) {
|
||||||
answer, err := m.write("\rsys sern\r")
|
answer, err := m.write("\rsys sern\r")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -77,6 +84,7 @@ func (m *modem) getSerNum() (string, error) {
|
|||||||
return sn, nil
|
return sn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setDateTime: sets the current date and time (taken from the host) to the modem
|
||||||
func (m *modem) setDateTime() error {
|
func (m *modem) setDateTime() error {
|
||||||
ct := time.Now()
|
ct := time.Now()
|
||||||
answer, err := m.write("DATE " + ct.Format("020106\r"))
|
answer, err := m.write("DATE " + ct.Format("020106\r"))
|
||||||
@@ -93,6 +101,7 @@ func (m *modem) setDateTime() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeUpdate: main flash utility. Writes the firmware taken from fwfile to the modem. Write progress bar.
|
||||||
func (m *modem) writeUpdate(fwfile string) error {
|
func (m *modem) writeUpdate(fwfile string) error {
|
||||||
_, err := m.write("UPDATE\r")
|
_, err := m.write("UPDATE\r")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -174,6 +183,7 @@ func (m *modem) writeUpdate(fwfile string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkFirmwareFits: checks the type of the modem and compares the file extension.
|
||||||
func (m *modem) checkFirmwareFits(fwfile string) error {
|
func (m *modem) checkFirmwareFits(fwfile string) error {
|
||||||
answer, err := m.write("ver ##\r")
|
answer, err := m.write("ver ##\r")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -215,8 +225,9 @@ func (m *modem) checkFirmwareFits(fwfile string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Update(serport string, baudrate int, fwfile string) error {
|
// Update: main firmware update utility. Runs pre-checks and calls main flashing function writeUpdate
|
||||||
m, err := initmodem(serport, baudrate)
|
func Update(serport string, baudrate int, sertimeout int, fwfile string, force bool) error {
|
||||||
|
m, err := initmodem(serport, baudrate, sertimeout)
|
||||||
defer m.port.Close()
|
defer m.port.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("FEHLER in Update")
|
return errors.New("FEHLER in Update")
|
||||||
@@ -232,8 +243,12 @@ func Update(serport string, baudrate int, fwfile string) error {
|
|||||||
if m.setDateTime() != nil {
|
if m.setDateTime() != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if m.checkFirmwareFits(fwfile) != nil {
|
if force == false {
|
||||||
return err
|
if m.checkFirmwareFits(fwfile) != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Noticef("Skipping checks if firmware fits modem due to force flag!")
|
||||||
}
|
}
|
||||||
if m.writeUpdate(fwfile) != nil {
|
if m.writeUpdate(fwfile) != nil {
|
||||||
return err
|
return err
|
||||||
|
Reference in New Issue
Block a user