Skip to content

Commit f369212

Browse files
committed
Load modules from /etc/modules
Auto-load modules listed in the `/etc/modules` file. This makes it possible for systems to specify (and users to override) the load of kernel modules that may not be detectable via `uevent` messages. Previously these modules were compiled into the kernel, but this does not support cases where they could be optional. For example, it would be nice to have a few USB gadget driver options without hardcoding them into the kernel. This lets systems be made where the default case loads a Ethernet/serial gadget driver (for example), but that can be disabled by overriding `/etc/modules` with a different set of drivers.
1 parent 9e50a29 commit f369212

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ information, see the [hex docs](https://hexdocs.pm/nerves_runtime).
2121
## System Initialization
2222

2323
`nerves_runtime` provides an OTP application (`nerves_runtime`) that can
24-
initialize the system when it is started. For this to be useful,
25-
`nerves_runtime` must be started before other OTP applications, since most will
26-
assume that the system is already initialized before they start. To set up
27-
`nerves_runtime` to work with `shoehorn`, you will need to do the following:
24+
initialize the system on boot. For this to be useful, `nerves_runtime` must be
25+
started before other OTP applications, since most will assume that the system is
26+
already initialized before they start. To set up `nerves_runtime` to work with
27+
`shoehorn`, you will need to do the following:
2828

2929
1. Include `shoehorn` in `mix.exs`
3030
2. Include `shoehorn` in your `rel/config.exs`
@@ -40,9 +40,9 @@ assume that the system is already initialized before they start. To set up
4040

4141
### Kernel Modules
4242

43-
`nerves_runtime` will attempt to auto-load kernel modules by calling `modprobe`
44-
using the `modalias` supplied by the device's `uevent` message. You can disable
45-
this feature by configuring `autoload: false` in your application configuration:
43+
`nerves_runtime` loads kernel modules from the `/etc/modules` file and on
44+
demand as devices are discovered by `uevent` messages. You can disable this
45+
feature by configuring `autoload: false` in your application configuration:
4646

4747
```elixir
4848
config :nerves_runtime, :kernel,

lib/nerves_runtime/application.ex

+39-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
defmodule Nerves.Runtime.Application do
22
@moduledoc false
33

4+
@module_list "/etc/modules"
5+
46
use Application
7+
require Logger
58

69
alias Nerves.Runtime.{
710
Init,
@@ -12,13 +15,6 @@ defmodule Nerves.Runtime.Application do
1215
alias Nerves.Runtime.Log.{KmsgTailer, SyslogTailer}
1316

1417
def start(_type, _args) do
15-
# On systems with hardware random number generation, it is important that
16-
# "rngd" gets started as soon as possible to start adding entropy to the
17-
# system. So much code directly or indirectly uses random numbers that it's
18-
# very easy to block on the random number generator or get low entropy
19-
# numbers.
20-
try_rngd()
21-
2218
target = Nerves.Runtime.target()
2319

2420
children =
@@ -37,6 +33,9 @@ defmodule Nerves.Runtime.Application do
3733
defp target_children(_target) do
3834
kernel_opts = Application.get_env(:nerves_runtime, :kernel, [])
3935

36+
# Kick off startup tasks asynchronously
37+
spawn(fn -> run_startup_tasks(kernel_opts) end)
38+
4039
[
4140
KmsgTailer,
4241
SyslogTailer,
@@ -45,6 +44,20 @@ defmodule Nerves.Runtime.Application do
4544
]
4645
end
4746

47+
defp run_startup_tasks(opts) do
48+
# Auto-load hardcoded modules
49+
if Keyword.get(opts, :autoload_modules, true) do
50+
load_kernel_modules()
51+
end
52+
53+
# On systems with hardware random number generation, it is important that
54+
# "rngd" gets started as soon as possible to start adding entropy to the
55+
# system. So much code directly or indirectly uses random numbers that it's
56+
# very easy to block on the random number generator or get low entropy
57+
# numbers.
58+
try_rngd()
59+
end
60+
4861
defp try_rngd() do
4962
rngd_path = "/usr/sbin/rngd"
5063

@@ -53,4 +66,23 @@ defmodule Nerves.Runtime.Application do
5366
System.cmd(rngd_path, [])
5467
end
5568
end
69+
70+
defp load_kernel_modules() do
71+
with {:ok, contents} <- File.read(@module_list) do
72+
contents
73+
|> String.split("\n")
74+
|> Enum.map(&String.trim/1)
75+
|> Enum.each(&process_modules_line/1)
76+
end
77+
end
78+
79+
defp process_modules_line(""), do: :ok
80+
defp process_modules_line("#" <> _comment), do: :ok
81+
82+
defp process_modules_line(module_name) do
83+
case System.cmd("/sbin/modprobe", [module_name]) do
84+
{_, 0} -> :ok
85+
_other -> Logger.warn("Error loading module #{module_name}. See #{@module_list}.")
86+
end
87+
end
5688
end

0 commit comments

Comments
 (0)