Skip to content

Commit 6c0b703

Browse files
authored
Add command to flash certificates (#54)
1 parent 625b338 commit 6c0b703

File tree

3 files changed

+223
-1
lines changed

3 files changed

+223
-1
lines changed

cli/certificates/certificates.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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 certificates
21+
22+
import (
23+
"os"
24+
25+
"github.com/spf13/cobra"
26+
)
27+
28+
func NewCommand() *cobra.Command {
29+
firmwareCmd := &cobra.Command{
30+
Use: "certificates",
31+
Short: "Commands to operate on certificates.",
32+
Long: "A subset of commands to perform various certificates operations.",
33+
Example: " " + os.Args[0] + " certificates ...",
34+
}
35+
36+
firmwareCmd.AddCommand(NewFlashCommand())
37+
return firmwareCmd
38+
}

cli/certificates/flash.go

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
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 certificates
21+
22+
import (
23+
"bytes"
24+
"os"
25+
"path/filepath"
26+
"strings"
27+
"time"
28+
29+
"github.com/arduino/FirmwareUploader/flasher"
30+
"github.com/arduino/FirmwareUploader/indexes"
31+
"github.com/arduino/FirmwareUploader/indexes/download"
32+
programmer "github.com/arduino/FirmwareUploader/programmers"
33+
"github.com/arduino/arduino-cli/arduino/serialutils"
34+
"github.com/arduino/arduino-cli/cli/errorcodes"
35+
"github.com/arduino/arduino-cli/cli/feedback"
36+
"github.com/arduino/go-paths-helper"
37+
"github.com/arduino/go-properties-orderedmap"
38+
"github.com/sirupsen/logrus"
39+
"github.com/spf13/cobra"
40+
)
41+
42+
var (
43+
fqbn string
44+
address string
45+
certificateURLs []string
46+
certificatePaths []string
47+
)
48+
49+
// NewCommand created a new `version` command
50+
func NewFlashCommand() *cobra.Command {
51+
command := &cobra.Command{
52+
Use: "flash",
53+
Short: "Flashes certificates to board.",
54+
Long: "Flashes specified certificates to board at specified address.",
55+
Example: "" +
56+
" " + os.Args[0] + " flash --fqbn arduino:samd:mkr1000 --address COM10 --url arduino.cc:443 --file /home/me/Digicert.cer\n" +
57+
" " + os.Args[0] + " flash -b arduino:samd:mkr1000 -a COM10 -u arduino.cc:443 -u google.cc:443\n" +
58+
" " + os.Args[0] + " flash -b arduino:samd:mkr1000 -a COM10 -f /home/me/VeriSign.cer -f /home/me/Digicert.cer\n",
59+
Args: cobra.NoArgs,
60+
Run: run,
61+
}
62+
63+
command.Flags().StringVarP(&fqbn, "fqbn", "b", "", "Fully Qualified Board Name, e.g.: arduino:samd:mkr1000, arduino:mbed_nano:nanorp2040connect")
64+
command.Flags().StringVarP(&address, "address", "a", "", "Upload port, e.g.: COM10, /dev/ttyACM0")
65+
command.Flags().StringSliceVarP(&certificateURLs, "url", "u", []string{}, "List of urls to download root certificates, e.g.: arduino.cc:443")
66+
command.Flags().StringSliceVarP(&certificatePaths, "file", "f", []string{}, "List of paths to certificate file, e.g.: /home/me/Digicert.cer")
67+
return command
68+
}
69+
70+
func run(cmd *cobra.Command, args []string) {
71+
packageIndex, err := indexes.GetPackageIndex()
72+
if err != nil {
73+
feedback.Errorf("Can't load package index: %s", err)
74+
os.Exit(errorcodes.ErrGeneric)
75+
}
76+
77+
firmwareIndex, err := indexes.GetFirmwareIndex()
78+
if err != nil {
79+
feedback.Errorf("Can't load firmware index: %s", err)
80+
os.Exit(errorcodes.ErrGeneric)
81+
}
82+
83+
if fqbn == "" {
84+
feedback.Errorf("Error during certificates flashing: missing board fqbn")
85+
os.Exit(errorcodes.ErrBadArgument)
86+
}
87+
88+
if address == "" {
89+
feedback.Errorf("Error during certificates flashing: missing board address")
90+
os.Exit(errorcodes.ErrBadArgument)
91+
}
92+
93+
if len(certificateURLs) == 0 && len(certificatePaths) == 0 {
94+
feedback.Errorf("Error during certificates flashing: no certificates provided")
95+
os.Exit(errorcodes.ErrBadArgument)
96+
}
97+
98+
board := firmwareIndex.GetBoard(fqbn)
99+
if board == nil {
100+
feedback.Errorf("Can't find board with %s fqbn", fqbn)
101+
os.Exit(errorcodes.ErrBadArgument)
102+
}
103+
104+
toolRelease := indexes.GetToolRelease(packageIndex, board.Uploader)
105+
if toolRelease == nil {
106+
feedback.Errorf("Error getting upload tool %s for board %s", board.Uploader, board.Fqbn)
107+
os.Exit(errorcodes.ErrGeneric)
108+
}
109+
uploadToolDir, err := download.DownloadTool(toolRelease)
110+
if err != nil {
111+
feedback.Errorf("Error downloading tool %s: %s", board.Uploader, err)
112+
os.Exit(errorcodes.ErrGeneric)
113+
}
114+
115+
loaderSketchPath, err := download.DownloadLoaderSketch(board.LoaderSketch)
116+
if err != nil {
117+
feedback.Errorf("Error downloading loader sketch from %s: %s", board.LoaderSketch.URL, err)
118+
os.Exit(errorcodes.ErrGeneric)
119+
}
120+
121+
loaderSketch := strings.ReplaceAll(loaderSketchPath.String(), loaderSketchPath.Ext(), "")
122+
123+
uploaderCommand := board.GetUploaderCommand()
124+
uploaderCommand = strings.ReplaceAll(uploaderCommand, "{tool_dir}", filepath.FromSlash(uploadToolDir.String()))
125+
uploaderCommand = strings.ReplaceAll(uploaderCommand, "{serial.port.file}", address)
126+
uploaderCommand = strings.ReplaceAll(uploaderCommand, "{loader.sketch}", loaderSketch)
127+
128+
commandLine, err := properties.SplitQuotedString(uploaderCommand, "\"", false)
129+
if err != nil {
130+
feedback.Errorf(`Error splitting command line "%s": %s`, uploaderCommand, err)
131+
os.Exit(errorcodes.ErrGeneric)
132+
}
133+
134+
// Check if board needs a 1200bps touch for upload
135+
if board.UploadTouch {
136+
logrus.Info("Putting board into bootloader mode")
137+
_, err := serialutils.Reset(address, board.UploadWait, nil)
138+
if err != nil {
139+
feedback.Errorf("Error during certificates flashing: missing board address")
140+
os.Exit(errorcodes.ErrGeneric)
141+
}
142+
}
143+
144+
// Flash loader Sketch
145+
flashOut := new(bytes.Buffer)
146+
flashErr := new(bytes.Buffer)
147+
// var err error
148+
if feedback.GetFormat() == feedback.JSON {
149+
err = programmer.Flash(commandLine, flashOut, flashErr)
150+
} else {
151+
err = programmer.Flash(commandLine, os.Stdout, os.Stderr)
152+
}
153+
if err != nil {
154+
feedback.Errorf("Error during certificates flashing: %s", err)
155+
os.Exit(errorcodes.ErrGeneric)
156+
}
157+
158+
// Wait a bit after flashing the loader sketch for the board to become
159+
// available again.
160+
time.Sleep(1 * time.Second)
161+
162+
// Get flasher depending on which module to use
163+
var f flasher.Flasher
164+
switch board.Module {
165+
case "NINA":
166+
f, err = flasher.NewNinaFlasher(address)
167+
case "SARA":
168+
f, err = flasher.NewSaraFlasher(address)
169+
case "WINC":
170+
f, err = flasher.NewWincFlasher(address)
171+
}
172+
if err != nil {
173+
feedback.Errorf("Error during certificates flashing: %s", err)
174+
os.Exit(errorcodes.ErrGeneric)
175+
}
176+
defer f.Close()
177+
178+
certFileList := paths.NewPathList(certificatePaths...)
179+
if err := f.FlashCertificates(&certFileList, certificateURLs); err != nil {
180+
feedback.Errorf("Error during certificates flashing: %s", err)
181+
os.Exit(errorcodes.ErrGeneric)
182+
}
183+
}

cli/cli.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"strings"
2929
"time"
3030

31+
"github.com/arduino/FirmwareUploader/cli/certificates"
3132
"github.com/arduino/FirmwareUploader/cli/firmware"
3233
"github.com/arduino/FirmwareUploader/cli/version"
3334
"github.com/arduino/FirmwareUploader/modules/nina"
@@ -67,8 +68,8 @@ func NewCommand() *cobra.Command {
6768
}
6869

6970
rootCmd.AddCommand(version.NewCommand())
70-
7171
rootCmd.AddCommand(firmware.NewCommand())
72+
rootCmd.AddCommand(certificates.NewCommand())
7273

7374
rootCmd.Flags().StringVar(&ctx.PortName, "port", "", "serial port to use for flashing")
7475
rootCmd.Flags().StringVar(&ctx.RootCertDir, "certs", "", "root certificate directory")

0 commit comments

Comments
 (0)