From 8a1dfbe91c1b309d361b4053e05bd5e01056fd41 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 3 Mar 2014 17:55:59 -0500 Subject: [PATCH 1/4] device-manager: ignore udev if only console is serial console Right now we use the heuristic, "more than one entry in /sys/class/tty/console/active" to mean "has serial consoles". We used to use the heuristic "file has more than tty0 in it". The older heuristic is more accurate because a user may have console=ttyS0 without console=tty0 on the kernel command line. --- src/libply-splash-core/ply-device-manager.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c index d06e1b5..098fd85 100644 --- a/src/libply-splash-core/ply-device-manager.c +++ b/src/libply-splash-core/ply-device-manager.c @@ -514,204 +514,203 @@ ply_device_manager_new (const char *default_tty, return manager; } void ply_device_manager_free (ply_device_manager_t *manager) { ply_trace ("freeing device manager"); if (manager == NULL) return; ply_event_loop_stop_watching_for_exit (manager->loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, manager); free_seats (manager); ply_list_free (manager->seats); free_terminals (manager); ply_hashtable_free (manager->terminals); if (manager->udev_monitor != NULL) udev_monitor_unref (manager->udev_monitor); if (manager->udev_context != NULL) udev_unref (manager->udev_context); free (manager); } -static int +static bool add_consoles_from_file (ply_device_manager_t *manager, const char *path) { int fd; char contents[512] = ""; ssize_t contents_length; - int num_consoles; + bool has_serial_consoles; const char *remaining_file_contents; ply_trace ("opening %s", path); fd = open (path, O_RDONLY); if (fd < 0) { ply_trace ("couldn't open it: %m"); - return 0; + return false; } ply_trace ("reading file"); contents_length = read (fd, contents, sizeof (contents) - 1); if (contents_length <= 0) { ply_trace ("couldn't read it: %m"); close (fd); - return 0; + return false; } close (fd); remaining_file_contents = contents; - num_consoles = 0; + has_serial_consoles = false; while (remaining_file_contents < contents + contents_length) { char *console; size_t console_length; const char *console_device; ply_terminal_t *terminal; /* Advance past any leading whitespace */ remaining_file_contents += strspn (remaining_file_contents, " \n\t\v"); if (*remaining_file_contents == '\0') { /* There's nothing left after the whitespace, we're done */ break; } /* Find trailing whitespace and NUL terminate. If strcspn * doesn't find whitespace, it gives us the length of the string * until the next NUL byte, which we'll just overwrite with * another NUL byte anyway. */ console_length = strcspn (remaining_file_contents, " \n\t\v"); console = strndup (remaining_file_contents, console_length); terminal = get_terminal (manager, console); console_device = ply_terminal_get_name (terminal); free (console); ply_trace ("console %s found!", console_device); - num_consoles++; + + if (terminal != manager->local_console_terminal) + has_serial_consoles = true; /* Move past the parsed console string, and the whitespace we * may have found above. If we found a NUL above and not whitespace, * then we're going to jump past the end of the buffer and the loop * will terminate */ remaining_file_contents += console_length + 1; } - return num_consoles; + return has_serial_consoles; } static void create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager, const char *device_path, ply_terminal_t *terminal, ply_renderer_type_t renderer_type) { ply_seat_t *seat; bool is_local_terminal = false; if (terminal != NULL && manager->local_console_terminal == terminal) is_local_terminal = true; if (is_local_terminal && manager->local_console_seat != NULL) { ply_trace ("trying to create seat for local console when one already exists"); return; } ply_trace ("creating seat for %s (renderer type: %u) (terminal: %s)", device_path? : "", renderer_type, terminal? ply_terminal_get_name (terminal): "none"); seat = ply_seat_new (terminal); if (!ply_seat_open (seat, renderer_type, device_path)) { ply_trace ("could not create seat"); ply_seat_free (seat); return; } ply_list_append_data (manager->seats, seat); if (is_local_terminal) manager->local_console_seat = seat; if (manager->seat_added_handler != NULL) manager->seat_added_handler (manager->seat_event_handler_data, seat); } static void create_seat_for_terminal (const char *device_path, ply_terminal_t *terminal, ply_device_manager_t *manager) { create_seat_for_terminal_and_renderer_type (manager, device_path, terminal, PLY_RENDERER_TYPE_NONE); } static bool create_seats_from_terminals (ply_device_manager_t *manager) { - int num_consoles; + bool has_serial_consoles; ply_trace ("checking for consoles"); if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES) { - num_consoles = 0; + has_serial_consoles = false; ply_trace ("ignoring all consoles but default console because explicitly told to."); } else { - num_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active"); - - if (num_consoles == 0) - ply_trace ("ignoring all consoles but default console because /sys/class/tty/console/active could not be read"); + has_serial_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active"); } - if (num_consoles > 1) + if (has_serial_consoles) { ply_trace ("serial consoles detected, managing them with details forced"); ply_hashtable_foreach (manager->terminals, (ply_hashtable_foreach_func_t *) create_seat_for_terminal, manager); return true; } return false; } static void create_seats_from_udev (ply_device_manager_t *manager) { bool found_drm_device, found_fb_device; ply_trace ("Looking for devices from udev"); found_drm_device = create_seats_for_subsystem (manager, SUBSYSTEM_DRM); found_fb_device = create_seats_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER); if (found_drm_device || found_fb_device) return; ply_trace ("Creating non-graphical seat, since there's no suitable graphics hardware"); create_seat_for_terminal_and_renderer_type (manager, ply_terminal_get_name (manager->local_console_terminal), manager->local_console_terminal, PLY_RENDERER_TYPE_NONE); -- 1.8.3.1 From 5fbfc8d1ec9da9060ebeaf0938afe8e2e0102b3d Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 3 Mar 2014 18:00:19 -0500 Subject: [PATCH 2/4] device-manager: be more tolerant of tty active console value Some kernels mistakenly put tty1 instead of tty0 in the file, so try to cope with them for maximium compatibility. --- src/libply-splash-core/ply-device-manager.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c index 098fd85..dbc203d 100644 --- a/src/libply-splash-core/ply-device-manager.c +++ b/src/libply-splash-core/ply-device-manager.c @@ -441,61 +441,62 @@ free_terminal (char *device, ply_device_manager_t *manager) { ply_hashtable_remove (manager->terminals, device); ply_terminal_close (terminal); ply_terminal_free (terminal); } static void free_terminals (ply_device_manager_t *manager) { ply_hashtable_foreach (manager->terminals, (ply_hashtable_foreach_func_t *) free_terminal, manager); } static ply_terminal_t * get_terminal (ply_device_manager_t *manager, const char *device_name) { char *full_name = NULL; ply_terminal_t *terminal; if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0) full_name = strdup (device_name); else asprintf (&full_name, "/dev/%s", device_name); if (strcmp (full_name, "/dev/tty0") == 0 || - strcmp (full_name, "/dev/tty") == 0) + strcmp (full_name, "/dev/tty") == 0 || + strcmp (full_name, ply_terminal_get_name (manager->local_console_terminal)) == 0) { terminal = manager->local_console_terminal; goto done; } terminal = ply_hashtable_lookup (manager->terminals, full_name); if (terminal == NULL) { terminal = ply_terminal_new (full_name); ply_hashtable_insert (manager->terminals, (void *) ply_terminal_get_name (terminal), terminal); } done: free (full_name); return terminal; } ply_device_manager_t * ply_device_manager_new (const char *default_tty, ply_device_manager_flags_t flags) { ply_device_manager_t *manager; manager = calloc (1, sizeof (ply_device_manager_t)); manager->loop = NULL; manager->terminals = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare); -- 1.8.3.1 From 0d5fae7feb3c2fb462f124940e91fea16298eb1f Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 6 Mar 2014 14:42:16 -0500 Subject: [PATCH 3/4] seat: make sure to open terminal when adding text displays If we have a pixel display, the renderer will handle opening the associated terminal. but if we don't have a pixel display, something needs to open the terminal. This commit adds code to do that. --- src/libply-splash-core/ply-seat.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c index 541b29e..2ac8bf7 100644 --- a/src/libply-splash-core/ply-seat.c +++ b/src/libply-splash-core/ply-seat.c @@ -75,60 +75,73 @@ add_pixel_displays (ply_seat_t *seat) ply_list_node_t *node; heads = ply_renderer_get_heads (seat->renderer); ply_trace ("Adding displays for %d heads", ply_list_get_length (heads)); node = ply_list_get_first_node (heads); while (node != NULL) { ply_list_node_t *next_node; ply_renderer_head_t *head; ply_pixel_display_t *display; head = ply_list_node_get_data (node); next_node = ply_list_get_next_node (heads, node); display = ply_pixel_display_new (seat->renderer, head); ply_list_append_data (seat->pixel_displays, display); node = next_node; } } static void add_text_displays (ply_seat_t *seat) { ply_text_display_t *display; + if (!ply_terminal_is_open (seat->terminal)) + { + if (!ply_terminal_open (seat->terminal)) + { + ply_trace ("could not add terminal %s: %m", + ply_terminal_get_name (seat->terminal)); + return; + } + } + + ply_trace ("adding text display for terminal %s", + ply_terminal_get_name (seat->terminal)); + display = ply_text_display_new (seat->terminal); ply_list_append_data (seat->text_displays, display); } bool ply_seat_open (ply_seat_t *seat, ply_renderer_type_t renderer_type, const char *device) { if (renderer_type != PLY_RENDERER_TYPE_NONE) { ply_renderer_t *renderer; renderer = ply_renderer_new (renderer_type, device, seat->terminal); if (!ply_renderer_open (renderer)) { ply_trace ("could not open renderer for %s", device); ply_renderer_free (renderer); seat->renderer = NULL; seat->renderer_active = false; if (renderer_type != PLY_RENDERER_TYPE_AUTO) return false; } else { seat->renderer = renderer; seat->renderer_active = true; -- 1.8.3.1 From aa2f5ac95c7cc0f4eb5f61465ecaf22247c7047c Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 6 Mar 2014 15:31:20 -0500 Subject: [PATCH 4/4] device-manager: Don't add local console to terminals hash table unless passed on cmdline it's unexpected for plymouth to show boot messages on the local console if there is not console=tty0 on the kernel command line. This commit fixes that. --- src/libply-splash-core/ply-device-manager.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c index dbc203d..8f5360c 100644 --- a/src/libply-splash-core/ply-device-manager.c +++ b/src/libply-splash-core/ply-device-manager.c @@ -445,92 +445,93 @@ free_terminal (char *device, ply_terminal_close (terminal); ply_terminal_free (terminal); } static void free_terminals (ply_device_manager_t *manager) { ply_hashtable_foreach (manager->terminals, (ply_hashtable_foreach_func_t *) free_terminal, manager); } static ply_terminal_t * get_terminal (ply_device_manager_t *manager, const char *device_name) { char *full_name = NULL; ply_terminal_t *terminal; if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0) full_name = strdup (device_name); else asprintf (&full_name, "/dev/%s", device_name); if (strcmp (full_name, "/dev/tty0") == 0 || strcmp (full_name, "/dev/tty") == 0 || strcmp (full_name, ply_terminal_get_name (manager->local_console_terminal)) == 0) { terminal = manager->local_console_terminal; + + ply_hashtable_insert (manager->terminals, + (void *) ply_terminal_get_name (terminal), + terminal); goto done; } terminal = ply_hashtable_lookup (manager->terminals, full_name); if (terminal == NULL) { terminal = ply_terminal_new (full_name); ply_hashtable_insert (manager->terminals, (void *) ply_terminal_get_name (terminal), terminal); } done: free (full_name); return terminal; } ply_device_manager_t * ply_device_manager_new (const char *default_tty, ply_device_manager_flags_t flags) { ply_device_manager_t *manager; manager = calloc (1, sizeof (ply_device_manager_t)); manager->loop = NULL; manager->terminals = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare); manager->local_console_terminal = ply_terminal_new (default_tty); - ply_hashtable_insert (manager->terminals, - (void *) ply_terminal_get_name (manager->local_console_terminal), - manager->local_console_terminal); manager->seats = ply_list_new (); manager->flags = flags; if (!(flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV)) manager->udev_context = udev_new (); attach_to_event_loop (manager, ply_event_loop_get_default ()); return manager; } void ply_device_manager_free (ply_device_manager_t *manager) { ply_trace ("freeing device manager"); if (manager == NULL) return; ply_event_loop_stop_watching_for_exit (manager->loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, manager); free_seats (manager); ply_list_free (manager->seats); free_terminals (manager); ply_hashtable_free (manager->terminals); if (manager->udev_monitor != NULL) -- 1.8.3.1