Packages
nerves
0.3.4
1.15.0
1.14.3
1.14.2
1.14.1
1.14.0
1.13.2
1.13.1
1.13.0
1.12.0
1.11.3
1.11.2
1.11.1
1.11.0
1.10.5
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.3
1.9.2
retired
1.9.1
1.9.0
1.8.0
1.7.17
1.7.16
1.7.15
1.7.14
retired
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
retired
1.7.1
retired
1.7.0
retired
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.11.0
0.10.1
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.3
0.8.2
0.8.1
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.4.0-rc.0
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
Craft and deploy bulletproof embedded software
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/firmware.burn.ex
defmodule Mix.Tasks.Firmware.Burn do
use Mix.Task
import Mix.Nerves.Utils
@switches [device: :string, task: :string]
@aliases [d: :device, t: :task]
def run(argv) do
preflight
debug_info "Nerves Firmware Burn"
{opts, argv, _} = OptionParser.parse(argv, switches: @switches, aliases: @aliases)
config = Mix.Project.config
otp_app = config[:app]
target = config[:target]
System.get_env("NERVES_SYSTEM") || raise """
Environment variable $NERVES_SYSTEM is not set
"""
System.get_env("NERVES_TOOLCHAIN") || raise """
Environment variable $NERVES_TOOLCHAIN is not set
"""
fw = Path.join(File.cwd!, "_images/#{target}/#{otp_app}.fw")
unless File.exists?(fw) do
Mix.raise "Firmware for target #{target} not found at #{fw} run `mix firmware` to build"
end
dev =
case opts[:device] do
nil -> prompt_dev()
dev -> dev
end
burn(fw, dev, opts, argv)
end
defp burn(fw, dev, opts, argv) do
task = opts[:task] || "complete"
args = ["-a", "-i", fw, "-t", task, "-d", dev] ++ argv
{cmd, args} =
case :os.type do
{_, :darwin} ->
{"fwup", args}
{_, :linux} ->
ask_pass = System.get_env("SUDO_ASKPASS") || "/usr/bin/ssh-askpass"
System.put_env("SUDO_ASKPASS", ask_pass)
{"sudo", ["fwup"] ++ args}
{_, type} ->
raise "Unable to burn firmware on your host #{inspect type}"
end
shell(cmd, args)
end
defp get_devs do
{result, 0} = System.cmd("fwup", ["--detect"])
if result == "" do
Mix.raise "Could not auto detect your SD card"
end
result
|> String.strip
|> String.split("\n")
|> Enum.map(&String.split(&1, ","))
end
defp prompt_dev() do
case get_devs() do
[[dev, bytes]] ->
choice =
Mix.shell.yes?("Use #{bytes_to_gigabytes(bytes)} GiB memory card found at #{dev}?")
if choice do
dev
else
Mix.raise "Aborted"
end
devs ->
choices =
devs
|> Enum.zip(0..length(devs))
|> Enum.reduce([], fn({[dev, bytes], idx}, acc) ->
["#{idx}) #{bytes_to_gigabytes(bytes)} GiB found at #{dev}" | acc]
end)
|> Enum.reverse
choice = Mix.shell.prompt("Discovered devices:\n#{Enum.join(choices, "\n")}\nWhich device do you want to burn to?")
|> String.strip
idx =
case Integer.parse(choice) do
{idx, _} -> idx
_ -> Mix.raise "Invalid selection #{choice}"
end
case Enum.fetch(devs, idx) do
{:ok, [dev, _]} -> dev
_ -> Mix.raise "Invalid selection #{choice}"
end
end
end
defp bytes_to_gigabytes(bytes) when is_binary(bytes) do
{bytes, _} = Integer.parse(bytes)
bytes_to_gigabytes(bytes)
end
defp bytes_to_gigabytes(bytes) do
gb = bytes / 1024 / 1024 / 1024
Float.round(gb, 2)
end
end