|
| 1 | +/* |
| 2 | + FirmwareUploader |
| 3 | + Copyright (c) 2021 Arduino LLC. All right reserved. |
| 4 | +
|
| 5 | + This library is free software; you can redistribute it and/or |
| 6 | + modify it under the terms of the GNU Lesser General Public |
| 7 | + License as published by the Free Software Foundation; either |
| 8 | + version 2.1 of the License, or (at your option) any later version. |
| 9 | +
|
| 10 | + This library is distributed in the hope that it will be useful, |
| 11 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | + Lesser General Public License for more details. |
| 14 | +
|
| 15 | + You should have received a copy of the GNU Lesser General Public |
| 16 | + License along with this library; if not, write to the Free Software |
| 17 | + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | +*/ |
| 19 | + |
| 20 | +package cli |
| 21 | + |
| 22 | +import ( |
| 23 | + "encoding/json" |
| 24 | + "fmt" |
| 25 | + "log" |
| 26 | + "os" |
| 27 | + "strings" |
| 28 | + "time" |
| 29 | + |
| 30 | + "github.com/arduino/FirmwareUploader/modules/nina" |
| 31 | + "github.com/arduino/FirmwareUploader/modules/sara" |
| 32 | + "github.com/arduino/FirmwareUploader/modules/winc" |
| 33 | + "github.com/arduino/FirmwareUploader/utils" |
| 34 | + "github.com/arduino/FirmwareUploader/utils/context" |
| 35 | + "github.com/arduino/go-paths-helper" |
| 36 | + "github.com/spf13/cobra" |
| 37 | +) |
| 38 | + |
| 39 | +var ctx = &context.Context{} |
| 40 | + |
| 41 | +func NewCommand() *cobra.Command { |
| 42 | + // FirmwareUploader is the root command |
| 43 | + firmwareUploaderCli := &cobra.Command{ |
| 44 | + Use: "FirmwareUploader", |
| 45 | + Short: "FirmwareUploader.", |
| 46 | + Long: "FirmwareUploader (FirmwareUploader).", |
| 47 | + Example: " " + os.Args[0] + " <command> [flags...]", |
| 48 | + Args: cobra.NoArgs, |
| 49 | + Run: run, |
| 50 | + } |
| 51 | + |
| 52 | + firmwareUploaderCli.Flags().StringVar(&ctx.PortName, "port", "", "serial port to use for flashing") |
| 53 | + firmwareUploaderCli.Flags().StringVar(&ctx.RootCertDir, "certs", "", "root certificate directory") |
| 54 | + firmwareUploaderCli.Flags().StringSliceVar(&ctx.Addresses, "address", []string{}, "address (host:port) to fetch and flash root certificate for, multiple values allowed") |
| 55 | + firmwareUploaderCli.Flags().StringVar(&ctx.FirmwareFile, "firmware", "", "firmware file to flash") |
| 56 | + firmwareUploaderCli.Flags().BoolVar(&ctx.ReadAll, "read", false, "read all firmware and output to stdout") |
| 57 | + firmwareUploaderCli.Flags().StringVar(&ctx.FWUploaderBinary, "flasher", "", "firmware upload binary (precompiled for the right target)") |
| 58 | + firmwareUploaderCli.Flags().StringVar(&ctx.BinaryToRestore, "restore_binary", "", "binary to restore after the firmware upload (precompiled for the right target)") |
| 59 | + firmwareUploaderCli.Flags().StringVar(&ctx.ProgrammerPath, "programmer", "", "path of programmer in use (avrdude/bossac)") |
| 60 | + firmwareUploaderCli.Flags().StringVar(&ctx.Model, "model", "", "module model (winc, nina or sara)") |
| 61 | + firmwareUploaderCli.Flags().StringVar(&ctx.BoardName, "get_available_for", "", "Ask for available firmwares matching a given board") |
| 62 | + firmwareUploaderCli.Flags().IntVar(&ctx.Retries, "retries", 9, "Number of retries in case of upload failure") |
| 63 | + |
| 64 | + return firmwareUploaderCli |
| 65 | +} |
| 66 | + |
| 67 | +func run(cmd *cobra.Command, args []string) { |
| 68 | + if ctx.BoardName != "" { |
| 69 | + el, _ := json.Marshal(utils.GetCompatibleWith(ctx.BoardName, "")) |
| 70 | + fmt.Println(string(el)) |
| 71 | + os.Exit(0) |
| 72 | + } |
| 73 | + |
| 74 | + if ctx.PortName == "" { |
| 75 | + log.Fatal("Please specify a serial port") |
| 76 | + } |
| 77 | + |
| 78 | + if ctx.BinaryToRestore != "" { |
| 79 | + // sanity check for BinaryToRestore |
| 80 | + f := paths.New(ctx.BinaryToRestore) |
| 81 | + info, err := f.Stat() |
| 82 | + if err != nil { |
| 83 | + log.Fatalf("Error opening restore_binary: %s", err) |
| 84 | + } |
| 85 | + if info.IsDir() { |
| 86 | + log.Fatalf("Error opening restore_binary: is a directory...") |
| 87 | + } |
| 88 | + if info.Size() == 0 { |
| 89 | + log.Println("WARNING: restore_binary is empty! Will not restore binary after upload.") |
| 90 | + ctx.BinaryToRestore = "" |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + retry := 0 |
| 95 | + for { |
| 96 | + var err error |
| 97 | + if ctx.Model == "nina" || strings.Contains(ctx.FirmwareFile, "NINA") || strings.Contains(ctx.FWUploaderBinary, "NINA") { |
| 98 | + err = nina.Run(ctx) |
| 99 | + } else if ctx.Model == "winc" || strings.Contains(ctx.FirmwareFile, "WINC") || strings.Contains(ctx.FWUploaderBinary, "WINC") { |
| 100 | + err = winc.Run(ctx) |
| 101 | + } else { |
| 102 | + err = sara.Run(ctx) |
| 103 | + } |
| 104 | + if err == nil { |
| 105 | + log.Println("Operation completed: success! :-)") |
| 106 | + break |
| 107 | + } |
| 108 | + log.Println("Error: " + err.Error()) |
| 109 | + |
| 110 | + if retry >= ctx.Retries { |
| 111 | + log.Fatal("Operation failed. :-(") |
| 112 | + } |
| 113 | + |
| 114 | + retry++ |
| 115 | + log.Println("Waiting 1 second before retrying...") |
| 116 | + time.Sleep(time.Second) |
| 117 | + log.Printf("Retrying upload (%d of %d)", retry, ctx.Retries) |
| 118 | + } |
| 119 | +} |
0 commit comments