grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 5/5] ns8250: Use ACPI SPCR table when available to configure seri


From: Benjamin Herrenschmidt
Subject: [PATCH 5/5] ns8250: Use ACPI SPCR table when available to configure serial
Date: Fri, 19 Mar 2021 09:07:28 +1100

"serial auto" is now equivalent to just "serial" and will use the
SPCR to discover the port if present, otherwise defaults to "com0"
as before.

This allows to support MMIO ports specified by ACPI which is needed
on AWS EC2 "metal" instances, and will enable grub to pickup the
port configuration specified by ACPI in other cases.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 grub-core/Makefile.core.def  |  1 +
 grub-core/term/ns8250-spcr.c | 82 ++++++++++++++++++++++++++++++++++++
 grub-core/term/serial.c      | 14 +++++-
 include/grub/serial.h        |  1 +
 4 files changed, 96 insertions(+), 2 deletions(-)
 create mode 100644 grub-core/term/ns8250-spcr.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 8022e1c0a..2830a1e85 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2033,6 +2033,7 @@ module = {
   name = serial;
   common = term/serial.c;
   x86 = term/ns8250.c;
+  x86 = term/ns8250-spcr.c;
   ieee1275 = term/ieee1275/serial.c;
   mips_arc = term/arc/serial.c;
   efi = term/efi/serial.c;
diff --git a/grub-core/term/ns8250-spcr.c b/grub-core/term/ns8250-spcr.c
new file mode 100644
index 000000000..63a67d07c
--- /dev/null
+++ b/grub-core/term/ns8250-spcr.c
@@ -0,0 +1,82 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010  Free 
Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/serial.h>
+#include <grub/ns8250.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/acpi.h>
+
+char *
+grub_ns8250_spcr_init (void)
+{
+  struct grub_acpi_spcr *spcr;
+  struct grub_serial_config config;
+
+  spcr = grub_acpi_find_table (GRUB_ACPI_SPCR_SIGNATURE);
+  if (!spcr)
+    return 0;
+  if (spcr->hdr.revision < 2)
+    return 0;
+  if (spcr->intf_type != GRUB_ACPI_SPCR_INTF_TYPE_16550 &&
+      spcr->intf_type != GRUB_ACPI_SPCR_INTF_TYPE_16550X)
+    return 0;
+  /* For now, we only support byte accesses */
+  if (spcr->base_addr.access_size != GRUB_ACPI_GENADDR_SIZE_BYTE &&
+      spcr->base_addr.access_size != GRUB_ACPI_GENADDR_SIZE_LGCY)
+    return 0;
+  config.word_len = 8;
+  config.parity = GRUB_SERIAL_PARITY_NONE;
+  config.stop_bits = GRUB_SERIAL_STOP_BITS_1;
+  config.base_clock = 1843200;
+  if (spcr->flow_control & GRUB_ACPI_SPCR_FC_RTSCTS)
+    config.rtscts = 1;
+  else
+    config.rtscts = 0;
+  switch (spcr->baud_rate)
+    {
+      case GRUB_ACPI_SPCR_BAUD_9600:
+        config.speed = 9600;
+       break;
+      case GRUB_ACPI_SPCR_BAUD_19200:
+        config.speed = 19200;
+       break;
+      case GRUB_ACPI_SPCR_BAUD_57600:
+        config.speed = 57600;
+       break;
+      case GRUB_ACPI_SPCR_BAUD_115200:
+        config.speed = 115200;
+       break;
+      case GRUB_ACPI_SPCR_BAUD_CURRENT:
+      default:
+       /* We don't (yet) have a way to read the currently
+       * configured speed in HW, so let's use a sane default
+       */
+        config.speed = 115200;
+       break;
+    };
+  switch (spcr->base_addr.space_id)
+    {
+      case GRUB_ACPI_GENADDR_MEM_SPACE:
+        return grub_serial_ns8250_add_mmio(spcr->base_addr.addr, &config);
+      case GRUB_ACPI_GENADDR_IO_SPACE:
+        return grub_serial_ns8250_add_port(spcr->base_addr.addr, &config);
+      default:
+       return 0;
+    };
+}
diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c
index 313341f53..b966b1854 100644
--- a/grub-core/term/serial.c
+++ b/grub-core/term/serial.c
@@ -171,11 +171,21 @@ grub_serial_find (const char *name)
                                                        0, 16), NULL);
       if (!name)
        return NULL;
-
       FOR_SERIAL_PORTS (port)
        if (grub_strcmp (port->name, name) == 0)
          break;
     }
+  if (!port && grub_strcmp (name, "auto") == 0)
+    {
+      /* Look for an SPCR if any. If not, default to com0 */
+      name = grub_ns8250_spcr_init();
+      if (!name)
+        name = "com0";
+
+      FOR_SERIAL_PORTS (port)
+        if (grub_strcmp (port->name, name) == 0)
+          break;
+    }
 #endif
 
 #ifdef GRUB_MACHINE_IEEE1275
@@ -226,7 +236,7 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char 
**args)
     name = args[0];
 
   if (!name)
-    name = "com0";
+    name = "auto";
 
   port = grub_serial_find (name);
   if (!port)
diff --git a/include/grub/serial.h b/include/grub/serial.h
index 5677dae33..0fbda220f 100644
--- a/include/grub/serial.h
+++ b/include/grub/serial.h
@@ -184,6 +184,7 @@ grub_serial_config_defaults (struct grub_serial_port *port)
 
 #if defined(__mips__) || defined (__i386__) || defined (__x86_64__)
 void grub_ns8250_init (void);
+char * grub_ns8250_spcr_init (void);
 char *grub_serial_ns8250_add_port (grub_port_t port, struct grub_serial_config 
*config);
 char *grub_serial_ns8250_add_mmio(grub_addr_t addr, struct grub_serial_config 
*config);
 #endif
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]