All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] term/serial: Add PCI-serial device support
@ 2023-05-13  7:54 Glenn Washburn
  2023-05-13  7:54 ` [PATCH v3 1/2] term/serial: Add support for PCI serial devices Glenn Washburn
  2023-05-13  7:54 ` [PATCH v3 2/2] pci: Rename GRUB_PCI_CLASS_* Glenn Washburn
  0 siblings, 2 replies; 4+ messages in thread
From: Glenn Washburn @ 2023-05-13  7:54 UTC (permalink / raw)
  To: grub-devel, Daniel Kiper; +Cc: Peter Zijlstra, Glenn Washburn

This series adds support for discovering serial devices on the PCI bus.
I've modified Peter's v2 patches to include feedback from Daniel. I've
also added a changes suggested by Peter to expose serial devices on the
PCI bus as "pci,XX:XX.X" instead of "pciN". This is less likely to change
due to a hardware reconfiguration. For instance, if there is one PCI serial
device at 02:00.0, with the pciN naming, there will exist a pci0 serial
device. If later, the hardware configuration is changed such that a PCI
serial device is added at 01:00.0, then GRUB will set pci0 to the newly
added serial device and pci1 will be the old one. This could cause
for the user as to why adding another serial device makes the previous
device "stop working". I have tested these additional changes in QEMU by
adding a virtual PCI serial device and verified that GRUB does show
additional serial devices to choose for the output terminal. The changes
from v2 are below and pretty minimal.

Glenn

peterz@infradead.org (2):
  term/serial: Add support for PCI serial devices
  pci: Rename GRUB_PCI_CLASS_*

 docs/grub.texi                      | 13 ++++-
 grub-core/Makefile.core.def         |  1 +
 grub-core/kern/i386/qemu/init.c     |  4 +-
 grub-core/term/pci/serial.c         | 91 +++++++++++++++++++++++++++++
 grub-core/term/serial.c             |  6 +-
 grub-core/video/efi_uga.c           |  2 +-
 grub-core/video/radeon_fuloong2e.c  |  2 +-
 grub-core/video/radeon_yeeloong3a.c |  2 +-
 grub-core/video/sis315pro.c         |  2 +-
 grub-core/video/sm712.c             |  2 +-
 include/grub/pci.h                  |  9 ++-
 include/grub/serial.h               |  4 ++
 12 files changed, 125 insertions(+), 13 deletions(-)
 create mode 100644 grub-core/term/pci/serial.c

Range-diff against v2:
1:  c186d56bf7ff ! 1:  17bb8f10447a term/serial: Add support for PCI serial devices
    @@ Commit message
         GRUB_SERIAL_COMMAND="serial --port=0x40a0 --speed=115200"
         GRUB_TERMINAL="serial console"
     
    +    Documentation is added to note that serial devices found on the PCI bus will
    +    be exposed as "pci,XX:XX.X" and how to find serial terminal logical names.
    +    Also, some minor documentation improvements were added.
    +
    +    This can be tested in QEMU by adding a pci-serial device, eg. using the option
    +    "-device pci-serial".
    +
         Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    +    Tested-by: Glenn Washburn <development@efficientek.com>
    +
    + ## docs/grub.texi ##
    +@@ docs/grub.texi: grub> @kbd{terminal_input serial; terminal_output serial}
    + The command @command{serial} initializes the serial unit 0 with the
    + speed 9600bps. The serial unit 0 is usually called @samp{COM1}, so, if
    + you want to use COM2, you must specify @samp{--unit=1} instead. This
    +-command accepts many other options, so please refer to @ref{serial},
    +-for more details.
    ++command accepts many other options, @pxref{serial} for more details.
    + 
    + Without argument or with @samp{--port=auto}, GRUB will attempt to use
    + ACPI when available to auto-detect the default serial port and its
    +@@ docs/grub.texi: Additionally, an MMIO address can be suffixed with:
    + @samp{.q} for 64-bit long long word access
    + @end itemize
    + 
    ++Also, @var{port} can be of the form @samp{pci,XX:XX.X} to indicate a serial
    ++device exposed on the PCI bus.
    ++
    + @var{speed} is the transmission speed; default is 9600. @var{word} and
    + @var{stop} are the number of data bits and stop bits. Data bits must
    + be in the range 5-8 and stop bits must be 1 or 2. Default is 8 data
    +@@ docs/grub.texi: The serial port is not used as a communication channel unless the
    + @command{terminal_input} or @command{terminal_output} command is used
    + (@pxref{terminal_input}, @pxref{terminal_output}).
    + 
    ++Note, valid @var{port} values, excluding IO port addresses, can be found
    ++by listing terminals with @command{terminal_output}, selecting all names
    ++prefixed by @samp{serial_} and removing that prefix.
    ++
    + Examples:
    + @example
    +-serial --port=3f8 --speed=9600
    ++serial --port=0x3f8 --speed=9600
    + serial --port=mmio,fefb0000.l --speed=115200
    ++serial --port=pci,00:16.3 --speed=115200
    + @end example
    + 
    + See also @ref{Serial terminal}.
     
      ## grub-core/Makefile.core.def ##
     @@ grub-core/Makefile.core.def: module = {
        ieee1275 = term/ieee1275/serial.c;
        mips_arc = term/arc/serial.c;
        efi = term/efi/serial.c;
    -+  pci = term/pci/serial.c;
    ++  x86 = term/pci/serial.c;
      
        enable = terminfomodule;
        enable = ieee1275;
    @@ grub-core/term/pci/serial.c (new)
     @@
     +/*
     + *  GRUB  --  GRand Unified Bootloader
    -+ *  Copyright (C) 2022  Free Software Foundation, Inc.
    ++ *  Copyright (C) 2023  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
    @@ grub-core/term/pci/serial.c (new)
     +#include <grub/misc.h>
     +
     +static int
    -+find_pciserial (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
    ++find_pciserial (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)), void *data __attribute__ ((unused)))
     +{
     +  grub_pci_address_t cmd_addr, class_addr, bar_addr;
     +  struct grub_serial_port *port;
     +  grub_uint32_t class, bar;
     +  grub_uint16_t cmdreg;
    -+  int *port_num = data;
     +  grub_err_t err;
     +
    -+  (void)pciid;
    -+
     +  cmd_addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
     +  cmdreg = grub_pci_read (cmd_addr);
     +
    @@ grub-core/term/pci/serial.c (new)
     +  if (port == NULL)
     +    return 0;
     +
    -+  port->name = grub_xasprintf ("pci%d", (*port_num));
    ++  port->name = grub_xasprintf ("pci,%02x:%02x.%x",
    ++			       grub_pci_get_bus (dev),
    ++			       grub_pci_get_device (dev),
    ++			       grub_pci_get_function (dev));
     +  if (port->name == NULL)
    -+    goto error;
    ++    goto fail;
     +
     +  grub_pci_write (cmd_addr, cmdreg | GRUB_PCI_COMMAND_IO_ENABLED);
     +
    @@ grub-core/term/pci/serial.c (new)
     +  if (err != GRUB_ERR_NONE)
     +    {
     +      grub_print_error ();
    -+      goto error;
    ++      goto fail;
     +    }
     +
     +  err = grub_serial_register (port);
     +  if (err != GRUB_ERR_NONE)
    -+    goto error;
    -+
    -+  (*port_num)++;
    ++    goto fail;
     +
     +  return 0;
     +
    -+error:
    ++ fail:
     +  grub_free (port->name);
     +  grub_free (port);
     +  return 0;
    @@ grub-core/term/pci/serial.c (new)
     +void
     +grub_pciserial_init (void)
     +{
    -+  int port_num;
    -+
    -+  grub_pci_iterate (find_pciserial, &port_num);
    ++  grub_pci_iterate (find_pciserial, NULL);
     +}
     
      ## grub-core/term/serial.c ##
    +@@ grub-core/term/serial.c: grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
    + 
    +   if (state[OPTION_PORT].set)
    +     {
    +-      if (grub_strncmp (state[OPTION_PORT].arg, "mmio,", sizeof ("mmio,") - 1) == 0)
    ++      if (grub_strncmp (state[OPTION_PORT].arg, "mmio,", sizeof ("mmio,") - 1) == 0 ||
    ++	  grub_strncmp (state[OPTION_PORT].arg, "pci,", sizeof ("pci,") - 1) == 0)
    +           grub_snprintf (pname, sizeof (pname), "%s", state[1].arg);
    +       else
    +           grub_snprintf (pname, sizeof (pname), "port%lx",
     @@ grub-core/term/serial.c: GRUB_MOD_INIT(serial)
      #ifdef GRUB_MACHINE_ARC
        grub_arcserial_init ();
2:  4aa0e0db57a8 = 2:  0eb2d7c01d9b pci: Rename GRUB_PCI_CLASS_*
-- 
2.34.1



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v3 1/2] term/serial: Add support for PCI serial devices
  2023-05-13  7:54 [PATCH v3 0/2] term/serial: Add PCI-serial device support Glenn Washburn
@ 2023-05-13  7:54 ` Glenn Washburn
  2023-05-19 14:34   ` Daniel Kiper
  2023-05-13  7:54 ` [PATCH v3 2/2] pci: Rename GRUB_PCI_CLASS_* Glenn Washburn
  1 sibling, 1 reply; 4+ messages in thread
From: Glenn Washburn @ 2023-05-13  7:54 UTC (permalink / raw)
  To: grub-devel, Daniel Kiper; +Cc: Peter Zijlstra, Glenn Washburn

From: "peterz@infradead.org" <peterz@infradead.org>

Loosely based on early_pci_serial_init() from Linux, allow GRUB to make
use of PCI serial devices.

Specifically, my Alderlake NUC exposes the Intel AMT SoL UART as a PCI
enumerated device but doesn't include it in the EFI tables.

Tested and confirmed working on a "Lenovo P360 Tiny" with Intel AMT
enabled. This specific machine has (from lspci -vv):

00:16.3 Serial controller: Intel Corporation Device 7aeb (rev 11) (prog-if 02 [16550])
        DeviceName: Onboard - Other
        Subsystem: Lenovo Device 330e
        Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Interrupt: pin D routed to IRQ 19
        Region 0: I/O ports at 40a0 [size=8]
        Region 1: Memory at b4224000 (32-bit, non-prefetchable) [size=4K]
        Capabilities: [40] MSI: Enable- Count=1/1 Maskable- 64bit+
                Address: 0000000000000000  Data: 0000
        Capabilities: [50] Power Management version 3
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Kernel driver in use: serial

>>From which the following config (/etc/default/grub) gets a working
serial setup:

GRUB_CMDLINE_LINUX="console=tty0 earlyprintk=pciserial,00:16.3,115200 console=ttyS0,115200"
GRUB_SERIAL_COMMAND="serial --port=0x40a0 --speed=115200"
GRUB_TERMINAL="serial console"

Documentation is added to note that serial devices found on the PCI bus will
be exposed as "pci,XX:XX.X" and how to find serial terminal logical names.
Also, some minor documentation improvements were added.

This can be tested in QEMU by adding a pci-serial device, eg. using the option
"-device pci-serial".

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Glenn Washburn <development@efficientek.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 docs/grub.texi              | 13 ++++--
 grub-core/Makefile.core.def |  1 +
 grub-core/term/pci/serial.c | 91 +++++++++++++++++++++++++++++++++++++
 grub-core/term/serial.c     |  6 ++-
 include/grub/pci.h          |  5 ++
 include/grub/serial.h       |  4 ++
 6 files changed, 116 insertions(+), 4 deletions(-)
 create mode 100644 grub-core/term/pci/serial.c

diff --git a/docs/grub.texi b/docs/grub.texi
index a3e9ce2d1ac7..477919ee901b 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -2716,8 +2716,7 @@ grub> @kbd{terminal_input serial; terminal_output serial}
 The command @command{serial} initializes the serial unit 0 with the
 speed 9600bps. The serial unit 0 is usually called @samp{COM1}, so, if
 you want to use COM2, you must specify @samp{--unit=1} instead. This
-command accepts many other options, so please refer to @ref{serial},
-for more details.
+command accepts many other options, @pxref{serial} for more details.
 
 Without argument or with @samp{--port=auto}, GRUB will attempt to use
 ACPI when available to auto-detect the default serial port and its
@@ -4186,6 +4185,9 @@ Additionally, an MMIO address can be suffixed with:
 @samp{.q} for 64-bit long long word access
 @end itemize
 
+Also, @var{port} can be of the form @samp{pci,XX:XX.X} to indicate a serial
+device exposed on the PCI bus.
+
 @var{speed} is the transmission speed; default is 9600. @var{word} and
 @var{stop} are the number of data bits and stop bits. Data bits must
 be in the range 5-8 and stop bits must be 1 or 2. Default is 8 data
@@ -4201,10 +4203,15 @@ The serial port is not used as a communication channel unless the
 @command{terminal_input} or @command{terminal_output} command is used
 (@pxref{terminal_input}, @pxref{terminal_output}).
 
+Note, valid @var{port} values, excluding IO port addresses, can be found
+by listing terminals with @command{terminal_output}, selecting all names
+prefixed by @samp{serial_} and removing that prefix.
+
 Examples:
 @example
-serial --port=3f8 --speed=9600
+serial --port=0x3f8 --speed=9600
 serial --port=mmio,fefb0000.l --speed=115200
+serial --port=pci,00:16.3 --speed=115200
 @end example
 
 See also @ref{Serial terminal}.
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 801df7c21de6..fb4cc066c526 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2064,6 +2064,7 @@ module = {
   ieee1275 = term/ieee1275/serial.c;
   mips_arc = term/arc/serial.c;
   efi = term/efi/serial.c;
+  x86 = term/pci/serial.c;
 
   enable = terminfomodule;
   enable = ieee1275;
diff --git a/grub-core/term/pci/serial.c b/grub-core/term/pci/serial.c
new file mode 100644
index 000000000000..0b8fe815f5ca
--- /dev/null
+++ b/grub-core/term/pci/serial.c
@@ -0,0 +1,91 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2023  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/term.h>
+#include <grub/types.h>
+#include <grub/pci.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+static int
+find_pciserial (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)), void *data __attribute__ ((unused)))
+{
+  grub_pci_address_t cmd_addr, class_addr, bar_addr;
+  struct grub_serial_port *port;
+  grub_uint32_t class, bar;
+  grub_uint16_t cmdreg;
+  grub_err_t err;
+
+  cmd_addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+  cmdreg = grub_pci_read (cmd_addr);
+
+  class_addr = grub_pci_make_address (dev, GRUB_PCI_REG_REVISION);
+  class = grub_pci_read (class_addr);
+
+  bar_addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
+  bar = grub_pci_read (bar_addr);
+
+  /* 16550 compattible MODEM or SERIAL */
+  if (((class >> 16) != GRUB_PCI_CLASS_COMMUNICATION_MODEM &&
+       (class >> 16) != GRUB_PCI_CLASS_COMMUNICATION_SERIAL) ||
+      ((class >> 8) & 0xff) != GRUB_PCI_SERIAL_16550_COMPATIBLE)
+    return 0;
+
+  if ((bar & GRUB_PCI_ADDR_SPACE_MASK) != GRUB_PCI_ADDR_SPACE_IO)
+    return 0;
+
+  port = grub_zalloc (sizeof (*port));
+  if (port == NULL)
+    return 0;
+
+  port->name = grub_xasprintf ("pci,%02x:%02x.%x",
+			       grub_pci_get_bus (dev),
+			       grub_pci_get_device (dev),
+			       grub_pci_get_function (dev));
+  if (port->name == NULL)
+    goto fail;
+
+  grub_pci_write (cmd_addr, cmdreg | GRUB_PCI_COMMAND_IO_ENABLED);
+
+  port->driver = &grub_ns8250_driver;
+  port->port = bar & GRUB_PCI_ADDR_IO_MASK;
+  err = grub_serial_config_defaults (port);
+  if (err != GRUB_ERR_NONE)
+    {
+      grub_print_error ();
+      goto fail;
+    }
+
+  err = grub_serial_register (port);
+  if (err != GRUB_ERR_NONE)
+    goto fail;
+
+  return 0;
+
+ fail:
+  grub_free (port->name);
+  grub_free (port);
+  return 0;
+}
+
+void
+grub_pciserial_init (void)
+{
+  grub_pci_iterate (find_pciserial, NULL);
+}
diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c
index c65ffc63cecb..05db4cf177c2 100644
--- a/grub-core/term/serial.c
+++ b/grub-core/term/serial.c
@@ -255,7 +255,8 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
 
   if (state[OPTION_PORT].set)
     {
-      if (grub_strncmp (state[OPTION_PORT].arg, "mmio,", sizeof ("mmio,") - 1) == 0)
+      if (grub_strncmp (state[OPTION_PORT].arg, "mmio,", sizeof ("mmio,") - 1) == 0 ||
+	  grub_strncmp (state[OPTION_PORT].arg, "pci,", sizeof ("pci,") - 1) == 0)
           grub_snprintf (pname, sizeof (pname), "%s", state[1].arg);
       else
           grub_snprintf (pname, sizeof (pname), "port%lx",
@@ -505,6 +506,9 @@ GRUB_MOD_INIT(serial)
 #ifdef GRUB_MACHINE_ARC
   grub_arcserial_init ();
 #endif
+#ifdef GRUB_HAS_PCI
+  grub_pciserial_init ();
+#endif
 }
 
 GRUB_MOD_FINI(serial)
diff --git a/include/grub/pci.h b/include/grub/pci.h
index 262c89b748bb..b228bb1b71fd 100644
--- a/include/grub/pci.h
+++ b/include/grub/pci.h
@@ -80,8 +80,13 @@
 
 #define  GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9
 #define  GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600
+
 #define  GRUB_PCI_CLASS_SUBCLASS_VGA  0x0300
 #define  GRUB_PCI_CLASS_SUBCLASS_USB  0x0c03
+#define  GRUB_PCI_CLASS_COMMUNICATION_SERIAL  0x0700
+#define  GRUB_PCI_CLASS_COMMUNICATION_MODEM   0x0703
+
+#define  GRUB_PCI_SERIAL_16550_COMPATIBLE 0x02
 
 #ifndef ASM_FILE
 
diff --git a/include/grub/serial.h b/include/grub/serial.h
index a955c076d892..9226d51f5831 100644
--- a/include/grub/serial.h
+++ b/include/grub/serial.h
@@ -210,6 +210,10 @@ grub_arcserial_init (void);
 struct grub_serial_port *grub_arcserial_add_port (const char *path);
 #endif
 
+#ifdef GRUB_HAS_PCI
+void grub_pciserial_init (void);
+#endif
+
 struct grub_serial_port *grub_serial_find (const char *name);
 extern struct grub_serial_driver grub_ns8250_driver;
 void EXPORT_FUNC(grub_serial_unregister_driver) (struct grub_serial_driver *driver);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v3 2/2] pci: Rename GRUB_PCI_CLASS_*
  2023-05-13  7:54 [PATCH v3 0/2] term/serial: Add PCI-serial device support Glenn Washburn
  2023-05-13  7:54 ` [PATCH v3 1/2] term/serial: Add support for PCI serial devices Glenn Washburn
@ 2023-05-13  7:54 ` Glenn Washburn
  1 sibling, 0 replies; 4+ messages in thread
From: Glenn Washburn @ 2023-05-13  7:54 UTC (permalink / raw)
  To: grub-devel, Daniel Kiper; +Cc: Peter Zijlstra, Glenn Washburn

From: "peterz@infradead.org" <peterz@infradead.org>

Glenn suggested to rename the existing PCI_CLASS defines to have
explicit class and subclass names.

Suggested-by: Glenn Washburn <development@efficientek.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 grub-core/kern/i386/qemu/init.c     | 4 ++--
 grub-core/video/efi_uga.c           | 2 +-
 grub-core/video/radeon_fuloong2e.c  | 2 +-
 grub-core/video/radeon_yeeloong3a.c | 2 +-
 grub-core/video/sis315pro.c         | 2 +-
 grub-core/video/sm712.c             | 2 +-
 include/grub/pci.h                  | 4 ++--
 7 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c
index 4e84d3ba1e35..08f81d25e686 100644
--- a/grub-core/kern/i386/qemu/init.c
+++ b/grub-core/kern/i386/qemu/init.c
@@ -168,11 +168,11 @@ enable_cards (grub_pci_device_t dev,
 
   class = (grub_pci_read (addr) >> 16) & 0xffff;
 
-  if (class == GRUB_PCI_CLASS_SUBCLASS_VGA)
+  if (class == GRUB_PCI_CLASS_DISPLAY_VGA)
     cmd |= GRUB_PCI_COMMAND_IO_ENABLED
       | GRUB_PCI_COMMAND_MEM_ENABLED;
 
-  if (class == GRUB_PCI_CLASS_SUBCLASS_USB)
+  if (class == GRUB_PCI_CLASS_SERIAL_USB)
     return 0;
 
   addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c
index e74d6c235000..ac636caa28fc 100644
--- a/grub-core/video/efi_uga.c
+++ b/grub-core/video/efi_uga.c
@@ -100,7 +100,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
   addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
   subclass = (grub_pci_read (addr) >> 16) & 0xffff;
 
-  if (subclass != GRUB_PCI_CLASS_SUBCLASS_VGA)
+  if (subclass != GRUB_PCI_CLASS_DISPLAY_VGA)
     return 0;
 
   /* Enable MEM address spaces */
diff --git a/grub-core/video/radeon_fuloong2e.c b/grub-core/video/radeon_fuloong2e.c
index 40917acb765d..f1b4c591bbf3 100644
--- a/grub-core/video/radeon_fuloong2e.c
+++ b/grub-core/video/radeon_fuloong2e.c
@@ -72,7 +72,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
   addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
   class = grub_pci_read (addr);
 
-  if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
+  if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_DISPLAY_VGA
       || pciid != 0x515a1002)
     return 0;
 
diff --git a/grub-core/video/radeon_yeeloong3a.c b/grub-core/video/radeon_yeeloong3a.c
index 48631c1815df..61b70ef26b43 100644
--- a/grub-core/video/radeon_yeeloong3a.c
+++ b/grub-core/video/radeon_yeeloong3a.c
@@ -71,7 +71,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
   addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
   class = grub_pci_read (addr);
 
-  if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
+  if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_DISPLAY_VGA
       || pciid != 0x96151002)
     return 0;
 
diff --git a/grub-core/video/sis315pro.c b/grub-core/video/sis315pro.c
index 4d2f9999a9a7..ad3bb4dc7bd2 100644
--- a/grub-core/video/sis315pro.c
+++ b/grub-core/video/sis315pro.c
@@ -100,7 +100,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
   addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
   class = grub_pci_read (addr);
 
-  if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
+  if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_DISPLAY_VGA
       || pciid != GRUB_SIS315PRO_PCIID)
     return 0;
 
diff --git a/grub-core/video/sm712.c b/grub-core/video/sm712.c
index 65f59f84b11a..e8967308d54c 100644
--- a/grub-core/video/sm712.c
+++ b/grub-core/video/sm712.c
@@ -372,7 +372,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
   addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
   class = grub_pci_read (addr);
 
-  if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
+  if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_DISPLAY_VGA
       || pciid != GRUB_SM712_PCIID)
     return 0;
 
diff --git a/include/grub/pci.h b/include/grub/pci.h
index b228bb1b71fd..d4ce92b2d5f0 100644
--- a/include/grub/pci.h
+++ b/include/grub/pci.h
@@ -81,8 +81,8 @@
 #define  GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9
 #define  GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600
 
-#define  GRUB_PCI_CLASS_SUBCLASS_VGA  0x0300
-#define  GRUB_PCI_CLASS_SUBCLASS_USB  0x0c03
+#define  GRUB_PCI_CLASS_DISPLAY_VGA           0x0300
+#define  GRUB_PCI_CLASS_SERIAL_USB            0x0c03
 #define  GRUB_PCI_CLASS_COMMUNICATION_SERIAL  0x0700
 #define  GRUB_PCI_CLASS_COMMUNICATION_MODEM   0x0703
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v3 1/2] term/serial: Add support for PCI serial devices
  2023-05-13  7:54 ` [PATCH v3 1/2] term/serial: Add support for PCI serial devices Glenn Washburn
@ 2023-05-19 14:34   ` Daniel Kiper
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Kiper @ 2023-05-19 14:34 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Peter Zijlstra

On Sat, May 13, 2023 at 02:54:51AM -0500, Glenn Washburn wrote:
> From: "peterz@infradead.org" <peterz@infradead.org>
>
> Loosely based on early_pci_serial_init() from Linux, allow GRUB to make
> use of PCI serial devices.
>
> Specifically, my Alderlake NUC exposes the Intel AMT SoL UART as a PCI
> enumerated device but doesn't include it in the EFI tables.
>
> Tested and confirmed working on a "Lenovo P360 Tiny" with Intel AMT
> enabled. This specific machine has (from lspci -vv):
>
> 00:16.3 Serial controller: Intel Corporation Device 7aeb (rev 11) (prog-if 02 [16550])
>         DeviceName: Onboard - Other
>         Subsystem: Lenovo Device 330e
>         Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Interrupt: pin D routed to IRQ 19
>         Region 0: I/O ports at 40a0 [size=8]
>         Region 1: Memory at b4224000 (32-bit, non-prefetchable) [size=4K]
>         Capabilities: [40] MSI: Enable- Count=1/1 Maskable- 64bit+
>                 Address: 0000000000000000  Data: 0000
>         Capabilities: [50] Power Management version 3
>                 Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
>                 Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
>         Kernel driver in use: serial
>
> >>From which the following config (/etc/default/grub) gets a working
> serial setup:
>
> GRUB_CMDLINE_LINUX="console=tty0 earlyprintk=pciserial,00:16.3,115200 console=ttyS0,115200"
> GRUB_SERIAL_COMMAND="serial --port=0x40a0 --speed=115200"
> GRUB_TERMINAL="serial console"
>
> Documentation is added to note that serial devices found on the PCI bus will
> be exposed as "pci,XX:XX.X" and how to find serial terminal logical names.
> Also, some minor documentation improvements were added.
>
> This can be tested in QEMU by adding a pci-serial device, eg. using the option
> "-device pci-serial".
>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Tested-by: Glenn Washburn <development@efficientek.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  docs/grub.texi              | 13 ++++--
>  grub-core/Makefile.core.def |  1 +
>  grub-core/term/pci/serial.c | 91 +++++++++++++++++++++++++++++++++++++
>  grub-core/term/serial.c     |  6 ++-
>  include/grub/pci.h          |  5 ++
>  include/grub/serial.h       |  4 ++
>  6 files changed, 116 insertions(+), 4 deletions(-)
>  create mode 100644 grub-core/term/pci/serial.c
>
> diff --git a/docs/grub.texi b/docs/grub.texi
> index a3e9ce2d1ac7..477919ee901b 100644
> --- a/docs/grub.texi
> +++ b/docs/grub.texi
> @@ -2716,8 +2716,7 @@ grub> @kbd{terminal_input serial; terminal_output serial}
>  The command @command{serial} initializes the serial unit 0 with the
>  speed 9600bps. The serial unit 0 is usually called @samp{COM1}, so, if
>  you want to use COM2, you must specify @samp{--unit=1} instead. This
> -command accepts many other options, so please refer to @ref{serial},
> -for more details.
> +command accepts many other options, @pxref{serial} for more details.
>
>  Without argument or with @samp{--port=auto}, GRUB will attempt to use
>  ACPI when available to auto-detect the default serial port and its
> @@ -4186,6 +4185,9 @@ Additionally, an MMIO address can be suffixed with:
>  @samp{.q} for 64-bit long long word access
>  @end itemize
>
> +Also, @var{port} can be of the form @samp{pci,XX:XX.X} to indicate a serial
> +device exposed on the PCI bus.
> +
>  @var{speed} is the transmission speed; default is 9600. @var{word} and
>  @var{stop} are the number of data bits and stop bits. Data bits must
>  be in the range 5-8 and stop bits must be 1 or 2. Default is 8 data
> @@ -4201,10 +4203,15 @@ The serial port is not used as a communication channel unless the
>  @command{terminal_input} or @command{terminal_output} command is used
>  (@pxref{terminal_input}, @pxref{terminal_output}).
>
> +Note, valid @var{port} values, excluding IO port addresses, can be found
> +by listing terminals with @command{terminal_output}, selecting all names
> +prefixed by @samp{serial_} and removing that prefix.
> +
>  Examples:
>  @example
> -serial --port=3f8 --speed=9600
> +serial --port=0x3f8 --speed=9600
>  serial --port=mmio,fefb0000.l --speed=115200
> +serial --port=pci,00:16.3 --speed=115200
>  @end example
>
>  See also @ref{Serial terminal}.
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index 801df7c21de6..fb4cc066c526 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -2064,6 +2064,7 @@ module = {
>    ieee1275 = term/ieee1275/serial.c;
>    mips_arc = term/arc/serial.c;
>    efi = term/efi/serial.c;
> +  x86 = term/pci/serial.c;
>
>    enable = terminfomodule;
>    enable = ieee1275;
> diff --git a/grub-core/term/pci/serial.c b/grub-core/term/pci/serial.c
> new file mode 100644
> index 000000000000..0b8fe815f5ca
> --- /dev/null
> +++ b/grub-core/term/pci/serial.c
> @@ -0,0 +1,91 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2023  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/term.h>
> +#include <grub/types.h>
> +#include <grub/pci.h>
> +#include <grub/mm.h>
> +#include <grub/misc.h>
> +
> +static int
> +find_pciserial (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)), void *data __attribute__ ((unused)))
> +{
> +  grub_pci_address_t cmd_addr, class_addr, bar_addr;
> +  struct grub_serial_port *port;
> +  grub_uint32_t class, bar;
> +  grub_uint16_t cmdreg;
> +  grub_err_t err;
> +
> +  cmd_addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
> +  cmdreg = grub_pci_read (cmd_addr);
> +
> +  class_addr = grub_pci_make_address (dev, GRUB_PCI_REG_REVISION);
> +  class = grub_pci_read (class_addr);
> +
> +  bar_addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
> +  bar = grub_pci_read (bar_addr);
> +
> +  /* 16550 compattible MODEM or SERIAL */
> +  if (((class >> 16) != GRUB_PCI_CLASS_COMMUNICATION_MODEM &&
> +       (class >> 16) != GRUB_PCI_CLASS_COMMUNICATION_SERIAL) ||
> +      ((class >> 8) & 0xff) != GRUB_PCI_SERIAL_16550_COMPATIBLE)
> +    return 0;
> +
> +  if ((bar & GRUB_PCI_ADDR_SPACE_MASK) != GRUB_PCI_ADDR_SPACE_IO)
> +    return 0;
> +
> +  port = grub_zalloc (sizeof (*port));
> +  if (port == NULL)
> +    return 0;
> +
> +  port->name = grub_xasprintf ("pci,%02x:%02x.%x",
> +			       grub_pci_get_bus (dev),
> +			       grub_pci_get_device (dev),
> +			       grub_pci_get_function (dev));
> +  if (port->name == NULL)
> +    goto fail;
> +
> +  grub_pci_write (cmd_addr, cmdreg | GRUB_PCI_COMMAND_IO_ENABLED);
> +
> +  port->driver = &grub_ns8250_driver;
> +  port->port = bar & GRUB_PCI_ADDR_IO_MASK;
> +  err = grub_serial_config_defaults (port);
> +  if (err != GRUB_ERR_NONE)
> +    {
> +      grub_print_error ();
> +      goto fail;
> +    }
> +
> +  err = grub_serial_register (port);
> +  if (err != GRUB_ERR_NONE)
> +    goto fail;
> +
> +  return 0;
> +
> + fail:
> +  grub_free (port->name);
> +  grub_free (port);
> +  return 0;
> +}
> +
> +void
> +grub_pciserial_init (void)
> +{
> +  grub_pci_iterate (find_pciserial, NULL);
> +}
> diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c
> index c65ffc63cecb..05db4cf177c2 100644
> --- a/grub-core/term/serial.c
> +++ b/grub-core/term/serial.c
> @@ -255,7 +255,8 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
>
>    if (state[OPTION_PORT].set)
>      {
> -      if (grub_strncmp (state[OPTION_PORT].arg, "mmio,", sizeof ("mmio,") - 1) == 0)
> +      if (grub_strncmp (state[OPTION_PORT].arg, "mmio,", sizeof ("mmio,") - 1) == 0 ||
> +	  grub_strncmp (state[OPTION_PORT].arg, "pci,", sizeof ("pci,") - 1) == 0)
>            grub_snprintf (pname, sizeof (pname), "%s", state[1].arg);
>        else
>            grub_snprintf (pname, sizeof (pname), "port%lx",
> @@ -505,6 +506,9 @@ GRUB_MOD_INIT(serial)
>  #ifdef GRUB_MACHINE_ARC
>    grub_arcserial_init ();
>  #endif
> +#ifdef GRUB_HAS_PCI

I think this...

> +  grub_pciserial_init ();
> +#endif
>  }
>
>  GRUB_MOD_FINI(serial)
> diff --git a/include/grub/pci.h b/include/grub/pci.h
> index 262c89b748bb..b228bb1b71fd 100644
> --- a/include/grub/pci.h
> +++ b/include/grub/pci.h
> @@ -80,8 +80,13 @@
>
>  #define  GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9
>  #define  GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600
> +
>  #define  GRUB_PCI_CLASS_SUBCLASS_VGA  0x0300
>  #define  GRUB_PCI_CLASS_SUBCLASS_USB  0x0c03
> +#define  GRUB_PCI_CLASS_COMMUNICATION_SERIAL  0x0700
> +#define  GRUB_PCI_CLASS_COMMUNICATION_MODEM   0x0703
> +
> +#define  GRUB_PCI_SERIAL_16550_COMPATIBLE 0x02
>
>  #ifndef ASM_FILE
>
> diff --git a/include/grub/serial.h b/include/grub/serial.h
> index a955c076d892..9226d51f5831 100644
> --- a/include/grub/serial.h
> +++ b/include/grub/serial.h
> @@ -210,6 +210,10 @@ grub_arcserial_init (void);
>  struct grub_serial_port *grub_arcserial_add_port (const char *path);
>  #endif
>
> +#ifdef GRUB_HAS_PCI

... and this should be changed to

  #if defined(__i386__) && defined(__x86_64__)

Otherwise Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>...

I can do the changes mentioned above before push.

Peter, Glenn, thank you for adding this feature.

> +void grub_pciserial_init (void);
> +#endif
> +
>  struct grub_serial_port *grub_serial_find (const char *name);
>  extern struct grub_serial_driver grub_ns8250_driver;
>  void EXPORT_FUNC(grub_serial_unregister_driver) (struct grub_serial_driver *driver);

Daniel


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-05-19 14:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-13  7:54 [PATCH v3 0/2] term/serial: Add PCI-serial device support Glenn Washburn
2023-05-13  7:54 ` [PATCH v3 1/2] term/serial: Add support for PCI serial devices Glenn Washburn
2023-05-19 14:34   ` Daniel Kiper
2023-05-13  7:54 ` [PATCH v3 2/2] pci: Rename GRUB_PCI_CLASS_* Glenn Washburn

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.