Merge ~bamf0/ubuntu/+source/plymouth:tpm-fde-add-password-toggle into ubuntu/+source/plymouth:ubuntu/devel

Proposed by Simon Johnsson
Status: Needs review
Proposed branch: ~bamf0/ubuntu/+source/plymouth:tpm-fde-add-password-toggle
Merge into: ubuntu/+source/plymouth:ubuntu/devel
Diff against target: 519 lines (+497/-0)
3 files modified
debian/changelog (+7/-0)
debian/patches/series (+1/-0)
debian/patches/toggle-password.patch (+489/-0)
Reviewer Review Type Date Requested Status
Alessandro Astone (community) Approve
Skia Pending
git-ubuntu import Pending
Review via email: mp+498160@code.launchpad.net

Description of the change

This merge proposal will introduce the patch `toggle-password.patch` to Plymouth which adds the option "AllowPasswordClearTextToggle" to the two-step module. This option makes the TAB key toggle between bulleted and clear text passwords. Essentially, the option is to simplify inputting large recovery keys when using FDE.

To post a comment you must log in.
Revision history for this message
Simon Johnsson (bamf0) wrote :

I realized that this feature is missing an updated version number. This will get added once the patch has been reviewed.

81eae90... by Simon Johnsson

Update changelog

Revision history for this message
Simon Johnsson (bamf0) wrote (last edit ):

Updated the changelog, as I realized that there was no point in waiting.

Revision history for this message
Alessandro Astone (aleasto) wrote :

I left a review upstream: https://gitlab.freedesktop.org/plymouth/plymouth/-/merge_requests/373

For downstream, I would squash the commits (except changelog) as they're just fixups on top of the first commit introducing the patch.

review: Needs Fixing
Revision history for this message
Simon Johnsson (bamf0) wrote :

Thanks for the review! I have addressed the comments and incorporated the upstream fixes into this branch.

Revision history for this message
Alessandro Astone (aleasto) wrote :

LGTM, thanks.

review: Approve

Unmerged commits

81eae90... by Simon Johnsson

Update changelog

b24dd1e... by Simon Johnsson

Add toggle password patch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 66aedfe..304e5b3 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,10 @@
6+plymouth (24.004.60+git20250831.4a3c171d-0ubuntu2) resolute; urgency=medium
7+
8+ * d/p/toggle-password.patch: Add two-step cleartext password toggle
9+ (LP: #2137639)
10+
11+ -- Simon Johnsson <simon.johnsson@canonical.com> Wed, 07 Jan 2026 15:48:03 +0100
12+
13 plymouth (24.004.60+git20250831.4a3c171d-0ubuntu1) questing; urgency=medium
14
15 * New git snapshot which only contains one new merge request:
16diff --git a/debian/patches/series b/debian/patches/series
17index bde24cd..85f7c53 100644
18--- a/debian/patches/series
19+++ b/debian/patches/series
20@@ -15,3 +15,4 @@ spinfinity-no-meson-symlink.patch
21 remove-plymouth-set-default-theme-populate-initrd.patch
22 include-necessary-files.patch
23 enable-usesimpledrm.patch
24+toggle-password.patch
25diff --git a/debian/patches/toggle-password.patch b/debian/patches/toggle-password.patch
26new file mode 100644
27index 0000000..cec803d
28--- /dev/null
29+++ b/debian/patches/toggle-password.patch
30@@ -0,0 +1,489 @@
31+From: Simon Johnsson <simon.johnsson@canonical.com>
32+Date: Thu, 8 Jan 2026 10:34:54 +0100
33+Subject: [PATCH] feature: add password cleartext toggle
34+Description:
35+ * Introduce functions for allowing passwords to optionally be displayed
36+ in cleartext.
37+
38+ * Introduce a TAB handler that allows themes
39+ to optionally implement a way of displaying cleartext passwords.
40+ Themes not implementing this behavior should not be affected.
41+
42+ * Introduce the option "AllowPasswordClearTextToggle" in the
43+ two-step module configuration such that TAB can toggle viewing
44+ the password in cleartext.
45+
46+Bug-Ubuntu: https://bugs.launchpad.net/bugs/2137639
47+---
48+ .../ply-boot-splash-plugin.h | 3 +
49+ src/libply-splash-core/ply-boot-splash.c | 27 ++++-
50+ src/libply-splash-core/ply-boot-splash.h | 4 +
51+ src/libply-splash-core/ply-keyboard.c | 49 +++++++++
52+ src/libply-splash-core/ply-keyboard.h | 7 ++
53+ src/main.c | 101 +++++++++++++-----
54+ src/plugins/splash/two-step/plugin.c | 75 +++++++++----
55+ 7 files changed, 217 insertions(+), 49 deletions(-)
56+
57+--- a/src/libply-splash-core/ply-boot-splash-plugin.h
58++++ b/src/libply-splash-core/ply-boot-splash-plugin.h
59+@@ -103,6 +103,9 @@ typedef struct
60+ bool (*validate_input) (ply_boot_splash_plugin_t *plugin,
61+ const char *entry_text,
62+ const char *add_text);
63++ void (*display_password_clear_text)(ply_boot_splash_plugin_t *plugin,
64++ const char *prompt,
65++ const char *entry_text);
66+ } ply_boot_splash_plugin_interface_t;
67+
68+ #endif /* PLY_BOOT_SPLASH_PLUGIN_H */
69+--- a/src/libply-splash-core/ply-boot-splash.c
70++++ b/src/libply-splash-core/ply-boot-splash.c
71+@@ -707,17 +707,38 @@ void ply_boot_splash_display_normal (ply
72+ splash->plugin_interface->display_normal (splash->plugin);
73+ }
74+
75+-void ply_boot_splash_display_password (ply_boot_splash_t *splash,
76+- const char *prompt,
77+- int bullets)
78++static inline void
79++assert_password_capable (ply_boot_splash_t *splash)
80+ {
81+ assert (splash != NULL);
82+ assert (splash->plugin_interface != NULL);
83+ assert (splash->plugin != NULL);
84++}
85++
86++void ply_boot_splash_display_password (ply_boot_splash_t *splash,
87++ const char *prompt,
88++ int bullets)
89++{
90++ assert_password_capable (splash);
91+ if (splash->plugin_interface->display_password != NULL)
92+ splash->plugin_interface->display_password (splash->plugin, prompt, bullets);
93+ }
94+
95++bool ply_boot_splash_can_display_password_clear_text (ply_boot_splash_t *splash)
96++{
97++ assert_password_capable (splash);
98++ return splash->plugin_interface->display_password_clear_text != NULL;
99++}
100++
101++void ply_boot_splash_display_password_clear_text (ply_boot_splash_t *splash,
102++ const char *prompt,
103++ const char *entry_text)
104++{
105++ if (!ply_boot_splash_can_display_password_clear_text (splash))
106++ return;
107++ splash->plugin_interface->display_password_clear_text (splash->plugin, prompt, entry_text);
108++}
109++
110+ void ply_boot_splash_display_question (ply_boot_splash_t *splash,
111+ const char *prompt,
112+ const char *entry_text)
113+--- a/src/libply-splash-core/ply-boot-splash.h
114++++ b/src/libply-splash-core/ply-boot-splash.h
115+@@ -79,6 +79,10 @@ void ply_boot_splash_display_normal (ply
116+ void ply_boot_splash_display_password (ply_boot_splash_t *splash,
117+ const char *prompt,
118+ int bullets);
119++bool ply_boot_splash_can_display_password_clear_text (ply_boot_splash_t *splash);
120++void ply_boot_splash_display_password_clear_text (ply_boot_splash_t *splash,
121++ const char *prompt,
122++ const char *entry_text);
123+ void ply_boot_splash_display_question (ply_boot_splash_t *splash,
124+ const char *prompt,
125+ const char *entry_text);
126+--- a/src/libply-splash-core/ply-keyboard.c
127++++ b/src/libply-splash-core/ply-keyboard.c
128+@@ -44,6 +44,7 @@
129+ #define KEY_CTRL_W ('\100' ^ 'W')
130+ #define KEY_CTRL_V ('\100' ^ 'V')
131+ #define KEY_ESCAPE ('\100' ^ '[')
132++#define KEY_TAB '\t'
133+ #define KEY_RETURN '\n'
134+ #define KEY_BACKSPACE '\177'
135+
136+@@ -97,6 +98,7 @@ struct _ply_keyboard
137+ ply_list_t *keyboard_input_handler_list;
138+ ply_list_t *backspace_handler_list;
139+ ply_list_t *escape_handler_list;
140++ ply_list_t *tab_handler_list;
141+ ply_list_t *enter_handler_list;
142+
143+ uint32_t is_active : 1;
144+@@ -114,6 +116,7 @@ ply_keyboard_new_for_terminal (ply_termi
145+ keyboard->keyboard_input_handler_list = ply_list_new ();
146+ keyboard->backspace_handler_list = ply_list_new ();
147+ keyboard->escape_handler_list = ply_list_new ();
148++ keyboard->tab_handler_list = ply_list_new ();
149+ keyboard->enter_handler_list = ply_list_new ();
150+ keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL;
151+ keyboard->provider.if_terminal = calloc (1, sizeof(ply_keyboard_terminal_provider_t));
152+@@ -136,6 +139,7 @@ ply_keyboard_new_for_renderer (ply_rende
153+ keyboard->keyboard_input_handler_list = ply_list_new ();
154+ keyboard->backspace_handler_list = ply_list_new ();
155+ keyboard->escape_handler_list = ply_list_new ();
156++ keyboard->tab_handler_list = ply_list_new ();
157+ keyboard->enter_handler_list = ply_list_new ();
158+ keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_RENDERER;
159+ keyboard->provider.if_renderer = calloc (1, sizeof(ply_keyboard_renderer_provider_t));
160+@@ -219,6 +223,17 @@ process_keyboard_input (ply_keyboard_t *
161+ ply_trace ("end escape key handler");
162+ return;
163+
164++ case KEY_TAB:
165++ ply_trace ("tab key!");
166++ for (node = ply_list_get_first_node (keyboard->tab_handler_list);
167++ node; node = ply_list_get_next_node (keyboard->tab_handler_list, node)) {
168++ ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
169++ ply_keyboard_tab_handler_t tab_handler = (ply_keyboard_tab_handler_t) closure->function;
170++ tab_handler (closure->user_data);
171++ }
172++ ply_trace ("end tab key handler");
173++ return;
174++
175+ case KEY_BACKSPACE:
176+ ply_trace ("backspace key!");
177+ process_backspace (keyboard);
178+@@ -636,6 +651,40 @@ ply_keyboard_remove_escape_handler (ply_
179+ return;
180+ }
181+ }
182++}
183++
184++void
185++ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard,
186++ ply_keyboard_tab_handler_t tab_handler,
187++ void *user_data)
188++{
189++ ply_keyboard_closure_t *closure;
190++
191++ assert (keyboard != NULL);
192++
193++ closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) tab_handler,
194++ user_data);
195++ ply_list_append_data (keyboard->tab_handler_list, closure);
196++}
197++
198++
199++void
200++ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard,
201++ ply_keyboard_tab_handler_t tab_handler)
202++{
203++ ply_list_node_t *node;
204++
205++ assert (keyboard != NULL);
206++
207++ for (node = ply_list_get_first_node (keyboard->tab_handler_list);
208++ node; node = ply_list_get_next_node (keyboard->tab_handler_list, node)) {
209++ ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
210++ if ((ply_keyboard_tab_handler_t) closure->function == tab_handler) {
211++ ply_keyboard_closure_free (closure);
212++ ply_list_remove_node (keyboard->tab_handler_list, node);
213++ return;
214++ }
215++ }
216+ }
217+
218+ void
219+--- a/src/libply-splash-core/ply-keyboard.h
220++++ b/src/libply-splash-core/ply-keyboard.h
221+@@ -40,6 +40,8 @@ typedef void (*ply_keyboard_backspace_ha
222+
223+ typedef void (*ply_keyboard_escape_handler_t) (void *user_data);
224+
225++typedef void (*ply_keyboard_tab_handler_t) (void *user_data);
226++
227+ typedef void (*ply_keyboard_enter_handler_t) (void *user_data,
228+ const char *line);
229+
230+@@ -63,6 +65,11 @@ void ply_keyboard_add_escape_handler (pl
231+ void *user_data);
232+ void ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard,
233+ ply_keyboard_escape_handler_t escape_handler);
234++void ply_keyboard_add_tab_handler (ply_keyboard_t *keyboard,
235++ ply_keyboard_tab_handler_t tab_handler,
236++ void *user_data);
237++void ply_keyboard_remove_tab_handler (ply_keyboard_t *keyboard,
238++ ply_keyboard_tab_handler_t tab_handler);
239+ void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard,
240+ ply_keyboard_enter_handler_t enter_handler,
241+ void *user_data);
242+--- a/src/main.c
243++++ b/src/main.c
244+@@ -116,6 +116,7 @@ typedef struct
245+ uint32_t should_force_details : 1;
246+ uint32_t should_force_default_splash : 1;
247+ uint32_t splash_is_becoming_idle : 1;
248++ uint32_t should_show_password_clear_text : 1;
249+
250+ char *override_splash_path;
251+ char *system_default_splash_path;
252+@@ -155,6 +156,7 @@ static void tell_systemd_to_stop_printin
253+ #endif
254+ static const char *get_cache_file_for_mode (ply_boot_splash_mode_t mode);
255+ static void on_escape_pressed (state_t *state);
256++static void on_tab_pressed (state_t *state);
257+ static void on_enter (state_t *state,
258+ const char *line);
259+ static void on_keyboard_input (state_t *state,
260+@@ -1129,6 +1131,10 @@ on_keyboard_added (state_t *state
261+ ply_keyboard_add_escape_handler (keyboard,
262+ (ply_keyboard_escape_handler_t)
263+ on_escape_pressed, state);
264++ ply_trace ("listening for tab");
265++ ply_keyboard_add_tab_handler (keyboard,
266++ (ply_keyboard_tab_handler_t)
267++ on_tab_pressed, state);
268+ ply_trace ("listening for backspace");
269+ ply_keyboard_add_backspace_handler (keyboard,
270+ (ply_keyboard_backspace_handler_t)
271+@@ -1156,6 +1162,10 @@ on_keyboard_removed (state_t *sta
272+ ply_keyboard_remove_escape_handler (keyboard,
273+ (ply_keyboard_escape_handler_t)
274+ on_escape_pressed);
275++ ply_trace ("no longer listening for tab");
276++ ply_keyboard_remove_tab_handler (keyboard,
277++ (ply_keyboard_tab_handler_t)
278++ on_tab_pressed);
279+ ply_trace ("no longer listening for backspace");
280+ ply_keyboard_remove_backspace_handler (keyboard,
281+ (ply_keyboard_backspace_handler_t)
282+@@ -1600,6 +1610,33 @@ validate_input (state_t *state,
283+ return input_valid;
284+ }
285+
286++static void
287++handle_ply_entry_trigger_type_password (state_t *state,
288++ ply_entry_trigger_t *entry_trigger)
289++{
290++ bool show_password_clear_text =
291++ state->should_show_password_clear_text &&
292++ ply_boot_splash_can_display_password_clear_text (state->boot_splash);
293++ if (show_password_clear_text) {
294++ const char *entry_text = (const char *) ply_buffer_get_bytes (state->entry_buffer);
295++ ply_trace ("WARNING: cleartext password display enabled");
296++ ply_boot_splash_display_password_clear_text (state->boot_splash,
297++ entry_trigger->prompt,
298++ entry_text);
299++ } else {
300++ int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer),
301++ ply_buffer_get_size (state->entry_buffer));
302++ bullets = MAX (0, bullets);
303++ ply_boot_splash_display_password (state->boot_splash,
304++ entry_trigger->prompt,
305++ bullets);
306++ }
307++ ply_boot_splash_display_prompt (state->boot_splash,
308++ entry_trigger->prompt,
309++ ply_buffer_get_bytes (state->entry_buffer),
310++ true);
311++}
312++
313+
314+ static void
315+ update_display (state_t *state)
316+@@ -1608,32 +1645,24 @@ update_display (state_t *state)
317+
318+ ply_list_node_t *node;
319+ node = ply_list_get_first_node (state->entry_triggers);
320+- if (node) {
321+- ply_entry_trigger_t *entry_trigger = ply_list_node_get_data (node);
322+- if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) {
323+- int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer),
324+- ply_buffer_get_size (state->entry_buffer));
325+- bullets = MAX (0, bullets);
326+- ply_boot_splash_display_password (state->boot_splash,
327+- entry_trigger->prompt,
328+- bullets);
329+- ply_boot_splash_display_prompt (state->boot_splash,
330+- entry_trigger->prompt,
331+- ply_buffer_get_bytes (state->entry_buffer),
332+- true);
333+- } else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) {
334+- ply_boot_splash_display_question (state->boot_splash,
335+- entry_trigger->prompt,
336+- ply_buffer_get_bytes (state->entry_buffer));
337+- ply_boot_splash_display_prompt (state->boot_splash,
338+- entry_trigger->prompt,
339+- ply_buffer_get_bytes (state->entry_buffer),
340+- false);
341+- } else {
342+- ply_trace ("unkown entry type");
343+- }
344+- } else {
345++ if (!node) {
346+ ply_boot_splash_display_normal (state->boot_splash);
347++ return;
348++ }
349++
350++ ply_entry_trigger_t *entry_trigger = ply_list_node_get_data (node);
351++ if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) {
352++ handle_ply_entry_trigger_type_password (state, entry_trigger);
353++ } else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION) {
354++ ply_boot_splash_display_question (state->boot_splash,
355++ entry_trigger->prompt,
356++ ply_buffer_get_bytes (state->entry_buffer));
357++ ply_boot_splash_display_prompt (state->boot_splash,
358++ entry_trigger->prompt,
359++ ply_buffer_get_bytes (state->entry_buffer),
360++ false);
361++ } else {
362++ ply_trace ("unknown entry type");
363+ }
364+ }
365+
366+@@ -1675,6 +1704,28 @@ on_escape_pressed (state_t *state)
367+ }
368+
369+ static void
370++toggle_between_bullets_and_clear_text (state_t *state)
371++{
372++ ply_trace ("toggling between bullets and clear text");
373++
374++ if (!state->should_show_password_clear_text) {
375++ state->should_show_password_clear_text = true;
376++ } else {
377++ state->should_show_password_clear_text = false;
378++ }
379++ update_display (state);
380++}
381++
382++static void
383++on_tab_pressed (state_t *state)
384++{
385++ ply_trace ("tab key pressed");
386++
387++ if (validate_input (state, "", "\t"))
388++ toggle_between_bullets_and_clear_text (state);
389++}
390++
391++static void
392+ on_keyboard_input (state_t *state,
393+ const char *keyboard_input,
394+ size_t character_size)
395+--- a/src/plugins/splash/two-step/plugin.c
396++++ b/src/plugins/splash/two-step/plugin.c
397+@@ -203,6 +203,7 @@ struct _ply_boot_splash_plugin
398+ uint32_t message_below_animation : 1;
399+ uint32_t transient_progress_bar : 1;
400+ uint32_t in_fsck : 1;
401++ uint32_t allow_password_clear_text_toggle : 1;
402+
403+ char *monospace_font;
404+ uint32_t plugin_console_messages_updating : 1;
405+@@ -710,6 +711,8 @@ view_load (view_t *view)
406+ ply_trace ("loading entry");
407+ if (!ply_entry_load (view->entry))
408+ return false;
409++ else
410++ ply_entry_set_text_color (view->entry, 1.0, 1.0, 1.0, 1.0);
411+
412+ ply_keymap_icon_load (view->keymap_icon);
413+ ply_capslock_icon_load (view->capslock_icon);
414+@@ -1383,6 +1386,9 @@ create_plugin (ply_key_file_t *key_file)
415+ plugin->message_below_animation =
416+ ply_key_file_get_bool (key_file, "two-step", "MessageBelowAnimation");
417+
418++ plugin->allow_password_clear_text_toggle =
419++ ply_key_file_get_bool (key_file, "two-step", "AllowPasswordClearTextToggle");
420++
421+ progress_function = ply_key_file_get_value (key_file, "two-step", "ProgressFunction");
422+
423+ if (progress_function != NULL) {
424+@@ -2354,16 +2360,17 @@ display_normal (ply_boot_splash_plugin_t
425+ }
426+
427+ static void
428+-display_password (ply_boot_splash_plugin_t *plugin,
429+- const char *prompt,
430+- int bullets)
431++display_password_internal (ply_boot_splash_plugin_t *plugin,
432++ const char *prompt,
433++ const char *entry_text,
434++ int bullets)
435+ {
436+ pause_views (plugin);
437+ if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
438+ stop_animation (plugin);
439+
440+ plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
441+- show_prompt (plugin, prompt, NULL, bullets);
442++ show_prompt (plugin, prompt, entry_text, bullets);
443+ redraw_views (plugin);
444+
445+ if (plugin->should_show_console_messages)
446+@@ -2374,6 +2381,31 @@ display_password (ply_boot_splash_plugin
447+ }
448+
449+ static void
450++display_password (ply_boot_splash_plugin_t *plugin,
451++ const char *prompt,
452++ int bullets)
453++{
454++ display_password_internal (plugin, prompt, NULL, bullets);
455++}
456++
457++static void
458++display_password_clear_text (ply_boot_splash_plugin_t *plugin,
459++ const char *prompt,
460++ const char *entry_text)
461++{
462++ if (!plugin->allow_password_clear_text_toggle) {
463++ // if function is disabled, fall back to masked bullet mode,
464++ // as dynamically setting function to NULL is not possible
465++ int bullets = ply_utf8_string_get_length (entry_text,
466++ strlen (entry_text));
467++ bullets = MAX (0, bullets);
468++ display_password_internal (plugin, prompt, NULL, bullets);
469++ return;
470++ }
471++ display_password_internal (plugin, prompt, entry_text, -1);
472++}
473++
474++static void
475+ display_question (ply_boot_splash_plugin_t *plugin,
476+ const char *prompt,
477+ const char *entry_text)
478+@@ -2520,23 +2552,24 @@ ply_boot_splash_plugin_get_interface (vo
479+ {
480+ static ply_boot_splash_plugin_interface_t plugin_interface =
481+ {
482+- .create_plugin = create_plugin,
483+- .destroy_plugin = destroy_plugin,
484+- .add_pixel_display = add_pixel_display,
485+- .remove_pixel_display = remove_pixel_display,
486+- .show_splash_screen = show_splash_screen,
487+- .update_status = update_status,
488+- .on_boot_progress = on_boot_progress,
489+- .hide_splash_screen = hide_splash_screen,
490+- .on_root_mounted = on_root_mounted,
491+- .become_idle = become_idle,
492+- .display_normal = display_normal,
493+- .display_password = display_password,
494+- .display_question = display_question,
495+- .display_message = display_message,
496+- .system_update = system_update,
497+- .on_boot_output = on_boot_output,
498+- .validate_input = validate_input,
499++ .create_plugin = create_plugin,
500++ .destroy_plugin = destroy_plugin,
501++ .add_pixel_display = add_pixel_display,
502++ .remove_pixel_display = remove_pixel_display,
503++ .show_splash_screen = show_splash_screen,
504++ .update_status = update_status,
505++ .on_boot_progress = on_boot_progress,
506++ .hide_splash_screen = hide_splash_screen,
507++ .on_root_mounted = on_root_mounted,
508++ .become_idle = become_idle,
509++ .display_normal = display_normal,
510++ .display_password = display_password,
511++ .display_password_clear_text = display_password_clear_text,
512++ .display_question = display_question,
513++ .display_message = display_message,
514++ .system_update = system_update,
515++ .on_boot_output = on_boot_output,
516++ .validate_input = validate_input,
517+ };
518+
519+ return &plugin_interface;

Subscribers

People subscribed via source and target branches