]>
Commit | Line | Data |
---|---|---|
1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ | |
2 | /* | |
3 | * load kernel modules | |
4 | * | |
5 | * Copyright © 2011 ProFUSION embedded systems | |
6 | */ | |
7 | ||
8 | #include "device-util.h" | |
9 | #include "module-util.h" | |
10 | #include "string-util.h" | |
11 | #include "strv.h" | |
12 | #include "udev-builtin.h" | |
13 | ||
14 | static struct kmod_ctx *ctx = NULL; | |
15 | ||
16 | static int builtin_kmod(UdevEvent *event, int argc, char *argv[]) { | |
17 | sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); | |
18 | int r; | |
19 | ||
20 | if (event->event_mode != EVENT_UDEV_WORKER) { | |
21 | log_device_debug(dev, "Running in test mode, skipping execution of 'kmod' builtin command."); | |
22 | return 0; | |
23 | } | |
24 | ||
25 | if (!ctx) | |
26 | return 0; | |
27 | ||
28 | if (argc < 2 || !streq(argv[1], "load")) | |
29 | return log_device_warning_errno(dev, SYNTHETIC_ERRNO(EINVAL), | |
30 | "%s: expected: load [module…]", argv[0]); | |
31 | ||
32 | char **modules = strv_skip(argv, 2); | |
33 | if (modules) | |
34 | STRV_FOREACH(module, modules) | |
35 | (void) module_load_and_warn(ctx, *module, /* verbose = */ false); | |
36 | else { | |
37 | const char *modalias; | |
38 | ||
39 | r = sd_device_get_property_value(dev, "MODALIAS", &modalias); | |
40 | if (r < 0) | |
41 | return log_device_warning_errno(dev, r, "Failed to read property \"MODALIAS\": %m"); | |
42 | ||
43 | (void) module_load_and_warn(ctx, modalias, /* verbose = */ false); | |
44 | } | |
45 | ||
46 | return 0; | |
47 | } | |
48 | ||
49 | /* called at udev startup and reload */ | |
50 | static int builtin_kmod_init(void) { | |
51 | int r; | |
52 | ||
53 | if (ctx) | |
54 | return 0; | |
55 | ||
56 | r = module_setup_context(&ctx); | |
57 | if (r < 0) | |
58 | return log_error_errno(r, "Failed to initialize libkmod context: %m"); | |
59 | ||
60 | log_debug("Loaded kernel module index."); | |
61 | return 0; | |
62 | } | |
63 | ||
64 | /* called on udev shutdown and reload request */ | |
65 | static void builtin_kmod_exit(void) { | |
66 | if (!ctx) | |
67 | return; | |
68 | ||
69 | ctx = sym_kmod_unref(ctx); | |
70 | log_debug("Unloaded kernel module index."); | |
71 | } | |
72 | ||
73 | /* called every couple of seconds during event activity; 'true' if config has changed */ | |
74 | static bool builtin_kmod_should_reload(void) { | |
75 | if (!ctx) | |
76 | return false; | |
77 | ||
78 | if (sym_kmod_validate_resources(ctx) != KMOD_RESOURCES_OK) { | |
79 | log_debug("Kernel module index needs reloading."); | |
80 | return true; | |
81 | } | |
82 | ||
83 | return false; | |
84 | } | |
85 | ||
86 | const UdevBuiltin udev_builtin_kmod = { | |
87 | .name = "kmod", | |
88 | .cmd = builtin_kmod, | |
89 | .init = builtin_kmod_init, | |
90 | .exit = builtin_kmod_exit, | |
91 | .should_reload = builtin_kmod_should_reload, | |
92 | .help = "Kernel module loader", | |
93 | .run_once = false, | |
94 | }; |