Blame SOURCES/serial-console-fixes.patch

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