Skip to content

Drop support for MKR 1000 and MKR Vidor 4000 #209

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .ecrc
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"Exclude": [
"^indexes/download/testdata/module_firmware_index\\.json$",
"^indexes/download/testdata/plugin_firmware_index\\.json$",
"^indexes/download/testdata/package_index\\.json$",
"^indexes/firmwareindex/testdata/module_firmware_index\\.json$",
"^indexes/testdata/package_index\\.json$",
"^indexes/firmwareindex/testdata/plugin_firmware_index\\.json$",
"^LICENSE\\.txt$",
"^poetry\\.lock$",
"^\\.licenses/",
Expand Down
25 changes: 2 additions & 23 deletions .github/workflows/generate-index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,13 @@ jobs:
- name: Install Poetry
run: pip install poetry

- name: Install Arduino CLI
uses: arduino/setup-arduino-cli@v1

- name: Install platforms
run: |
arduino-cli core update-index -v
arduino-cli version
arduino-cli core install arduino:samd@${{ env.SAMD_V }} -v
env:
SAMD_V: 1.8.11

- name: Install dependencies
run: |
cd $GITHUB_WORKSPACE
task poetry:install-deps

- name: Generate plugin firmware index
run: poetry run ./generator.py -a $(which arduino-cli)

- name: Generate module firmware index
run: poetry run ./generator.py -a $(which arduino-cli) --no-new
run: poetry run ./generator.py

# fix `gpg: signing failed: Inappropriate ioctl for device`
# https://github.com/keybase/keybase-issues/issues/2798
Expand All @@ -68,13 +54,6 @@ jobs:

# disable gpg pass prompt
# https://stackoverflow.com/questions/49072403/suppress-the-passphrase-prompt-in-gpg-command
- name: sign the module firmware index json
run: |
gpg \
--pinentry-mode=loopback \
--passphrase "${{ secrets.PASSPHRASE }}" \
--output boards/module_firmware_index.json.sig \
--detach-sign boards/module_firmware_index.json

- name: sign the plugin firmware index json
run: |
Expand All @@ -85,7 +64,7 @@ jobs:
--detach-sign boards/plugin_firmware_index.json

- name: create the gzip
run: gzip --keep boards/module_firmware_index.json boards/plugin_firmware_index.json
run: gzip --keep boards/plugin_firmware_index.json

- name: s3 sync
run: |
Expand Down
4 changes: 2 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
.vs/
.ionide/

indexes/download/testdata/module_firmware_index.json
indexes/download/testdata/plugin_firmware_index.json
indexes/download/testdata/package_index.json
indexes/firmwareindex/testdata/module_firmware_index.json
indexes/firmwareindex/testdata/plugin_firmware_index.json
indexes/testdata/package_index.json

# Generated files
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Arduino Firmware Uploader

The Arduino Firmware Uploader is a tool made to update the firmware and/or add SSL certificates for any Arduino board
equipped with WINC or NINA Wi-Fi module.
equipped with ESP32-S3 or NINA Wi-Fi module.

[![Test Go status](https://github.com/arduino/arduino-fwuploader/actions/workflows/test-go-task.yml/badge.svg)](https://github.com/arduino/arduino-fwuploader/actions/workflows/test-go-task.yml)
[![Codecov](https://codecov.io/gh/arduino/arduino-fwuploader/branch/main/graph/badge.svg)](https://codecov.io/gh/arduino/arduino-fwuploader)
Expand Down
2 changes: 1 addition & 1 deletion cli/arguments/arguments.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ type Flags struct {

// AddToCommand adds the flags used to set address and fqbn to the specified Command
func (f *Flags) AddToCommand(cmd *cobra.Command) {
cmd.Flags().StringVarP(&f.Fqbn, "fqbn", "b", "", "Fully Qualified Board Name, e.g.: arduino:samd:mkr1000, arduino:mbed_nano:nanorp2040connect")
cmd.Flags().StringVarP(&f.Fqbn, "fqbn", "b", "", "Fully Qualified Board Name, e.g.: arduino:samd:mkrwifi1010, arduino:mbed_nano:nanorp2040connect")
cmd.Flags().StringVarP(&f.Address, "address", "a", "", "Upload port, e.g.: COM10, /dev/ttyACM0")
}
92 changes: 8 additions & 84 deletions cli/certificates/flash.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,13 @@ import (
"fmt"
"io"
"os"
"strings"
"time"

"github.com/arduino/arduino-fwuploader/certificates"
"github.com/arduino/arduino-fwuploader/cli/arguments"
"github.com/arduino/arduino-fwuploader/cli/common"
"github.com/arduino/arduino-fwuploader/cli/feedback"
"github.com/arduino/arduino-fwuploader/cli/globals"
"github.com/arduino/arduino-fwuploader/flasher"
"github.com/arduino/arduino-fwuploader/indexes/download"
"github.com/arduino/arduino-fwuploader/indexes/firmwareindex"
"github.com/arduino/arduino-fwuploader/plugin"
"github.com/arduino/go-paths-helper"
"github.com/sirupsen/logrus"
Expand All @@ -54,9 +50,9 @@ func NewFlashCommand() *cobra.Command {
Short: "Flashes certificates to board.",
Long: "Flashes specified certificates to board at specified address.",
Example: "" +
" " + os.Args[0] + " certificates flash --fqbn arduino:samd:mkr1000 --address COM10 --url arduino.cc:443 --file /home/me/Digicert.cer\n" +
" " + os.Args[0] + " certificates flash -b arduino:samd:mkr1000 -a COM10 -u arduino.cc:443 -u google.com:443\n" +
" " + os.Args[0] + " certificates flash -b arduino:samd:mkr1000 -a COM10 -f /home/me/VeriSign.cer -f /home/me/Digicert.cer\n",
" " + os.Args[0] + " certificates flash --fqbn arduino:samd:mkrwifi1010 --address COM10 --url arduino.cc:443 --file /home/me/Digicert.cer\n" +
" " + os.Args[0] + " certificates flash -b arduino:renesas_uno:unor4wifi -a COM10 -u arduino.cc:443 -u google.com:443\n" +
" " + os.Args[0] + " certificates flash -b arduino:samd:mkrwifi1010 -a COM10 -f /home/me/VeriSign.cer -f /home/me/Digicert.cer\n",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
runFlash(certificateURLs, certificatePaths)
Expand All @@ -81,25 +77,19 @@ func runFlash(certificateURLs, certificatePaths []string) {
board := common.GetBoard(firmwareIndex, commonFlags.Fqbn)
uploadToolDir := common.DownloadRequiredToolsForBoard(packageIndex, board)

var res *flasher.FlashResult
var flashErr error
if !board.IsPlugin() {
res, flashErr = flashCertificates(board, uploadToolDir, certificateURLs, certificatePaths)
} else {
uploader, err := plugin.NewFWUploaderPlugin(uploadToolDir)
if err != nil {
feedback.Fatal(fmt.Sprintf("Could not open uploader plugin: %s", err), feedback.ErrGeneric)
}
res, flashErr = flashCertificatesWithPlugin(uploader, certificateURLs, certificatePaths)
uploader, err := plugin.NewFWUploaderPlugin(uploadToolDir)
if err != nil {
feedback.Fatal(fmt.Sprintf("Could not open uploader plugin: %s", err), feedback.ErrGeneric)
}

res, flashErr := flashCertificates(uploader, certificateURLs, certificatePaths)
feedback.PrintResult(res)
if flashErr != nil {
os.Exit(int(feedback.ErrGeneric))
}
}

func flashCertificatesWithPlugin(uploader *plugin.FwUploader, certificateURLs, certificatePaths []string) (*flasher.FlashResult, error) {
func flashCertificates(uploader *plugin.FwUploader, certificateURLs, certificatePaths []string) (*flasher.FlashResult, error) {
tmp, err := paths.MkTempDir("", "")
if err != nil {
return nil, err
Expand Down Expand Up @@ -161,69 +151,3 @@ func flashCertificatesWithPlugin(uploader *plugin.FwUploader, certificateURLs, c
},
}, err
}

func flashCertificates(board *firmwareindex.IndexBoard, uploadToolDir *paths.Path, certificateURLs, certificatePaths []string) (*flasher.FlashResult, error) {
loaderSketchPath, err := download.DownloadSketch(board.LoaderSketch)
if err != nil {
feedback.Fatal(fmt.Sprintf("Error downloading loader sketch from %s: %s", board.LoaderSketch.URL, err), feedback.ErrGeneric)
}
logrus.Debugf("loader sketch downloaded in %s", loaderSketchPath.String())

loaderSketch := strings.ReplaceAll(loaderSketchPath.String(), loaderSketchPath.Ext(), "")
programmerOut, programmerErr, err := common.FlashSketch(board, loaderSketch, uploadToolDir, commonFlags.Address)
if err != nil {
feedback.FatalError(err, feedback.ErrGeneric)
}

// Wait a bit after flashing the loader sketch for the board to become
// available again.
logrus.Debug("sleeping for 3 sec")
time.Sleep(3 * time.Second)

// Get flasher depending on which module to use
var f flasher.Flasher
moduleName := board.Module

// This matches the baudrate used in the FirmwareUpdater.ino sketch
// https://github.com/arduino-libraries/WiFiNINA/blob/master/examples/Tools/FirmwareUpdater/FirmwareUpdater.ino
const baudRate = 1000000
switch moduleName {
case "NINA":
// we use address and not bootloaderPort because the board should not be in bootloader mode
f, err = flasher.NewNinaFlasher(commonFlags.Address, baudRate, 30)
case "WINC1500":
f, err = flasher.NewWincFlasher(commonFlags.Address, baudRate, 30)
default:
err = fmt.Errorf("unknown module: %s", moduleName)
}
if err != nil {
feedback.Fatal(fmt.Sprintf("Error during certificates flashing: %s", err), feedback.ErrGeneric)
}
defer f.Close()

// now flash the certificate
certFileList := paths.NewPathList(certificatePaths...)
flasherOut := new(bytes.Buffer)
flasherErr := new(bytes.Buffer)
if feedback.GetFormat() == feedback.JSON {
err = f.FlashCertificates(&certFileList, certificateURLs, flasherOut)
if err != nil {
flasherErr.Write([]byte(fmt.Sprintf("Error during certificates flashing: %s", err)))
}
} else {
err = f.FlashCertificates(&certFileList, certificateURLs, io.MultiWriter(flasherOut, os.Stdout))
if err != nil {
os.Stderr.Write([]byte(fmt.Sprintf("Error during certificates flashing: %s", err)))
}
}
return &flasher.FlashResult{
Programmer: &flasher.ExecOutput{
Stdout: programmerOut.String(),
Stderr: programmerErr.String(),
},
Flasher: &flasher.ExecOutput{
Stdout: flasherOut.String(),
Stderr: flasherErr.String(),
},
}, err
}
76 changes: 3 additions & 73 deletions cli/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,15 @@
package common

import (
"bytes"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/arduino/serialutils"
"github.com/arduino/arduino-fwuploader/cli/feedback"
"github.com/arduino/arduino-fwuploader/cli/globals"
"github.com/arduino/arduino-fwuploader/indexes"
"github.com/arduino/arduino-fwuploader/indexes/download"
"github.com/arduino/arduino-fwuploader/indexes/firmwareindex"
programmer "github.com/arduino/arduino-fwuploader/programmers"
"github.com/arduino/go-paths-helper"
"github.com/arduino/go-properties-orderedmap"
"github.com/sirupsen/logrus"
)

Expand All @@ -59,24 +52,19 @@ func InitIndexes() (*packagemanager.PackageManager, *firmwareindex.Index) {
}

// Load main firmware index and optional additional indexes
firmwareIndex, err := indexes.GetFirmwareIndex(globals.ModuleFirmwareIndexGZURL, true)
pluginFirmwareIndex, err := indexes.GetFirmwareIndex(globals.PluginFirmwareIndexGZURL, true)
if err != nil {
feedback.Fatal(fmt.Sprintf("Can't load firmware index: %s", err), feedback.ErrGeneric)
}
if pluginIndex, err := indexes.GetFirmwareIndex(globals.PluginFirmwareIndexGZURL, true); err != nil {
feedback.Fatal(fmt.Sprintf("Can't load (plugin) firmware index: %s", err), feedback.ErrGeneric)
} else {
firmwareIndex.MergeWith(pluginIndex)
}
for _, additionalURL := range AdditionalFirmwareIndexURLs {
additionalIndex, err := indexes.GetFirmwareIndex(additionalURL, false)
if err != nil {
feedback.Fatal(fmt.Sprintf("Can't load firmware index: %s", err), feedback.ErrGeneric)
}
firmwareIndex.MergeWith(additionalIndex)
pluginFirmwareIndex.MergeWith(additionalIndex)
}

return pmbuilder.Build(), firmwareIndex
return pmbuilder.Build(), pluginFirmwareIndex
}

// CheckFlags runs a basic check, errors if the flags are not defined
Expand Down Expand Up @@ -105,11 +93,6 @@ func GetBoard(firmwareIndex *firmwareindex.Index, fqbn string) *firmwareindex.In
// DownloadRequiredToolsForBoard is an helper function that downloads the correct tool to flash a board,
// it returns the path of the downloaded tool
func DownloadRequiredToolsForBoard(pm *packagemanager.PackageManager, board *firmwareindex.IndexBoard) *paths.Path {
if !board.IsPlugin() {
// Just download the upload tool for integrated uploaders
return downloadTool(pm, board.Uploader)
}

// Download the plugin
toolDir := downloadTool(pm, board.UploaderPlugin)

Expand All @@ -133,56 +116,3 @@ func downloadTool(pm *packagemanager.PackageManager, tool string) *paths.Path {
logrus.Debugf("upload tool downloaded in %s", toolDir.String())
return toolDir
}

// FlashSketch is the business logic that handles the flashing procedure,
// it returns using a buffer the stdout and the stderr of the programmer
func FlashSketch(board *firmwareindex.IndexBoard, sketch string, uploadToolDir *paths.Path, address string) (programmerOut, programmerErr *bytes.Buffer, err error) {
bootloaderPort, err := GetNewAddress(board, address)
if err != nil {
return nil, nil, err
}

uploaderCommand := board.GetUploaderCommand()
uploaderCommand = strings.ReplaceAll(uploaderCommand, "{tool_dir}", filepath.FromSlash(uploadToolDir.String()))
uploaderCommand = strings.ReplaceAll(uploaderCommand, "{serial.port.file}", bootloaderPort)
uploaderCommand = strings.ReplaceAll(uploaderCommand, "{loader.sketch}", sketch) // we leave that name here because it's only a template,

logrus.Debugf("uploading with command: %s", uploaderCommand)
commandLine, err := properties.SplitQuotedString(uploaderCommand, "\"", false)
if err != nil {
feedback.Fatal(fmt.Sprintf(`Error splitting command line "%s": %s`, uploaderCommand, err), feedback.ErrGeneric)
}

// Flash the actual sketch
programmerOut = new(bytes.Buffer)
programmerErr = new(bytes.Buffer)
if feedback.GetFormat() == feedback.JSON {
err = programmer.Flash(commandLine, programmerOut, programmerErr)
} else {
err = programmer.Flash(commandLine, os.Stdout, os.Stderr)
}
if err != nil {
return nil, nil, fmt.Errorf("error during sketch flashing: %s", err)
}
return programmerOut, programmerErr, err
}

// GetNewAddress is a function used to reset a board and put it in bootloader mode
// it could happen that the board is assigned to a different serial port, after the reset,
// this fuction handles also this possibility
func GetNewAddress(board *firmwareindex.IndexBoard, oldAddress string) (string, error) {
// Check if board needs a 1200bps touch for upload
bootloaderPort := oldAddress
if board.UploadTouch {
logrus.Info("Putting board into bootloader mode")
newUploadPort, err := serialutils.Reset(oldAddress, board.UploadWait, nil, false)
if err != nil {
return "", fmt.Errorf("error during sketch flashing: missing board address. %s", err)
}
if newUploadPort != "" {
logrus.Infof("Found port to upload: %s", newUploadPort)
bootloaderPort = newUploadPort
}
}
return bootloaderPort, nil
}
Loading