Hi,

efiboot is using ACPI UID to determine the minor number of comX.

In sys/arch/amd64/stand/efiboot/efiboot.c:
 646         for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) {
 647                 /*
 648                  * Identify port number of the handle.  This assumes ACPI
 649                  * UID 0-3 map to legacy COM[1-4] and they use the legacy
 650                  * port address.
 651                  */
 652                 status = EFI_CALL(BS->HandleProtocol, handles[i], 
&devp_guid,
 653                     (void **)&dp0);
 654                 if (EFI_ERROR(status))
 655                         continue;
 656                 uid = -1;
 657                 for (dp = dp0; !IsDevicePathEnd(dp);
 658                     dp = NextDevicePathNode(dp)) {
 659                         dpp = (EFI_DEV_PATH_PTR)dp;
 660                         if (DevicePathType(dp) == ACPI_DEVICE_PATH &&
 661                             DevicePathSubType(dp) == ACPI_DP)
 662                                 if (dpp.Acpi->HID == EFI_PNP_ID(0x0501)) {
 663                                         uid = dpp.Acpi->UID;
 664                                         break;
 665                                 }
 666                 }
 667                 if (uid < 0 || nitems(serios) <= uid)
 668                         continue;
 669 
 670                 /* Prepare SERIAL_IO_INTERFACE */
 671                 status = EFI_CALL(BS->HandleProtocol, handles[i], 
&serio_guid,
 672                     (void **)&serio);
 673                 if (EFI_ERROR(status))
 674                         continue;
 675                 serios[uid] = serio;
 676         }
 677         free(handles, sz);
 678 
 679         for (i = 0; i < nitems(serios); i++) {
 680                 if (serios[i] != NULL)
 681                         printf(" com%d", i);
 682         }

I originally wrote this code, because I thought ACPI UID enumeration
is better than the order of handles by EFI.

On qemu or vmware, 2 serials mappped like the following:

  EFI handle  ACPI UID  I/O addr  efiboot  kernel
  0           0         0x3f8     com0     com0
  1           1         0x2f8     com1     com1

EFI handle order and ACPI UID enumeration are same and they also match
I/O address assignment.

But on "HPE DL20 Gen10", 2 serials mappped like the following:

  EFI handle  ACPI UID  I/O addr  efiboot  kernel
  0           1         0x3f8     com1     com0
  1           0         0x2f8     com0     com1

Note that EFI handle order and ACPI UID enumeration is different and
ACPI UID enumeration doesn't match the order in I/O address
assignment.  In this case, since com0 or com1 are mixed up between
efiboot and kernel, if serial is usable on efiboot, it becomes not
usable on kernel.

Fortunately we can use "machine comaddr" to fix up the problem.


Also I don't know any actual case such that EFI handle order is wrong
but ACPI UID is correct.  If using ACPI UID is useless, we can apply
the diff attached at last.

comment?

Index: sys/arch/amd64/stand/efiboot/efiboot.c
===================================================================
RCS file: /disk/cvs/openbsd/src/sys/arch/amd64/stand/efiboot/efiboot.c,v
retrieving revision 1.34
diff -u -p -r1.34 efiboot.c
--- sys/arch/amd64/stand/efiboot/efiboot.c      29 Nov 2019 16:16:19 -0000      
1.34
+++ sys/arch/amd64/stand/efiboot/efiboot.c      22 Feb 2020 01:34:59 -0000
@@ -631,10 +631,8 @@ efi_com_probe(struct consdev *cn)
        EFI_HANDLE              *handles = NULL;
        SERIAL_IO_INTERFACE     *serio;
        EFI_STATUS               status;
-       EFI_DEVICE_PATH         *dp, *dp0;
-       EFI_DEV_PATH_PTR         dpp;
        UINTN                    sz;
-       int                      i, uid = -1;
+       int                      i;
 
        cn->cn_pri = CN_LOWPRI;
        cn->cn_dev = makedev(8, 0);
@@ -651,36 +649,12 @@ efi_com_probe(struct consdev *cn)
                return;
        }
 
-       for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) {
-               /*
-                * Identify port number of the handle.  This assumes ACPI
-                * UID 0-3 map to legacy COM[1-4] and they use the legacy
-                * port address.
-                */
-               status = EFI_CALL(BS->HandleProtocol, handles[i], &devp_guid,
-                   (void **)&dp0);
-               if (EFI_ERROR(status))
-                       continue;
-               uid = -1;
-               for (dp = dp0; !IsDevicePathEnd(dp);
-                   dp = NextDevicePathNode(dp)) {
-                       dpp = (EFI_DEV_PATH_PTR)dp;
-                       if (DevicePathType(dp) == ACPI_DEVICE_PATH &&
-                           DevicePathSubType(dp) == ACPI_DP)
-                               if (dpp.Acpi->HID == EFI_PNP_ID(0x0501)) {
-                                       uid = dpp.Acpi->UID;
-                                       break;
-                               }
-               }
-               if (uid < 0 || nitems(serios) <= uid)
-                       continue;
-
-               /* Prepare SERIAL_IO_INTERFACE */
+       for (i = 0; i < sz / sizeof(EFI_HANDLE) && i < nitems(serios); i++) {
                status = EFI_CALL(BS->HandleProtocol, handles[i], &serio_guid,
                    (void **)&serio);
                if (EFI_ERROR(status))
                        continue;
-               serios[uid] = serio;
+               serios[i] = serio;
        }
        free(handles, sz);
 

Reply via email to