From befec94cc6e34414db5b1991dda007ccdd80ddce Mon Sep 17 00:00:00 2001 From: Torsten Harenberg Date: Tue, 21 Dec 2021 17:26:43 +0100 Subject: [PATCH] Implemented additional checks. Add force flag to flash firmware even if modem is in BIOS mode. --- firmware/firmware.go | 3 +-- main.go | 15 +++++++++++++-- update/update.go | 31 +++++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/firmware/firmware.go b/firmware/firmware.go index 150fcac..d1fd49d 100644 --- a/firmware/firmware.go +++ b/firmware/firmware.go @@ -18,6 +18,7 @@ func FwExists(path string) bool { return !errors.Is(err, os.ErrNotExist) } +// ChkHeader: runs header and CRC checks on the firmware file func ChkHeader(fwfile string) error { log.Info("checking ", fwfile) // 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 } 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])) - //if bytes.Equal(a, firmware[4+size:8+size]) { // PTC-3 if bytes.Equal(a, firmware[offset+size:offset+size+4]) { log.Info("CRC checksum ok!") } else { diff --git a/main.go b/main.go index c04cbd9..62552fe 100644 --- a/main.go +++ b/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 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."}) 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"}) + 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"}) + 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) cLog := console.New(true) if *debug { @@ -27,6 +34,10 @@ func main() { 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 { 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 { var err error if *serialDevice != "" { - err = update.Update(*serialDevice, baudrate, *f) + err = update.Update(*serialDevice, baudrate, *sertimeout, *f, *force) } else { - err = update.Update(ports[0].Port, baudrate, *f) + err = update.Update(ports[0].Port, baudrate, *sertimeout, *f, *force) } if err != nil { log.Panic(err) diff --git a/update/update.go b/update/update.go index a6a77c3..3da8a14 100644 --- a/update/update.go +++ b/update/update.go @@ -14,22 +14,25 @@ import ( "regexp" "strings" "time" + "unicode" ) +// Size of a "firmware packet" over the serial line const CHUNKSIZE = 256 type modem struct { 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, serial.WithBaudrate(baudrate), serial.WithDataBits(8), serial.WithParity(serial.NoParity), serial.WithStopBits(serial.OneStopBit), - serial.WithReadTimeout(70), - serial.WithWriteTimeout(70)) // 50 was not stable, bump to 70 + serial.WithReadTimeout(sertimeout), + serial.WithWriteTimeout(sertimeout)) if err != nil { fmt.Printf("ERROR: File %s could not be opened\n", serport) return nil, err @@ -38,9 +41,12 @@ func initmodem(serport string, baudrate int) (*modem, error) { return m, nil } +// write: writes to the serial ports, returns answer and logs output func (m *modem) write(out string, nolog ...bool) ([]byte, error) { if len(nolog) == 0 { - log.Debug("Sending " + out) + log.Debug("Sending " + strings.TrimFunc(out, func(r rune) bool { + return !unicode.IsGraphic(r) + })) } else { if len(out) < 200 { // in other cases it's the firmware! 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) { answer, err := m.write("\rsys sern\r") if err != nil { @@ -77,6 +84,7 @@ func (m *modem) getSerNum() (string, error) { return sn, nil } +// setDateTime: sets the current date and time (taken from the host) to the modem func (m *modem) setDateTime() error { ct := time.Now() answer, err := m.write("DATE " + ct.Format("020106\r")) @@ -93,6 +101,7 @@ func (m *modem) setDateTime() error { 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 { _, err := m.write("UPDATE\r") if err != nil { @@ -174,6 +183,7 @@ func (m *modem) writeUpdate(fwfile string) error { return nil } +// checkFirmwareFits: checks the type of the modem and compares the file extension. func (m *modem) checkFirmwareFits(fwfile string) error { answer, err := m.write("ver ##\r") if err != nil { @@ -215,8 +225,9 @@ func (m *modem) checkFirmwareFits(fwfile string) error { } -func Update(serport string, baudrate int, fwfile string) error { - m, err := initmodem(serport, baudrate) +// Update: main firmware update utility. Runs pre-checks and calls main flashing function writeUpdate +func Update(serport string, baudrate int, sertimeout int, fwfile string, force bool) error { + m, err := initmodem(serport, baudrate, sertimeout) defer m.port.Close() if err != nil { return errors.New("FEHLER in Update") @@ -232,8 +243,12 @@ func Update(serport string, baudrate int, fwfile string) error { if m.setDateTime() != nil { return err } - if m.checkFirmwareFits(fwfile) != nil { - return err + if force == false { + 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 { return err