diff mbox series

[bug#59003,6/7] installer: Report known-unsupported PCI devices.

Message ID 20221103191935.16336-6-ludo@gnu.org
State New
Headers show
Series Warn about unsupported devices | expand

Checks

Context Check Description
cbaines/comparison success View comparision
cbaines/git-branch success View Git branch
cbaines/applying patch fail
cbaines/issue success View issue

Commit Message

Ludovic Courtès Nov. 3, 2022, 7:19 p.m. UTC
* gnu/installer.scm (installer-steps): Pass #:pci-database to the
'welcome' step procedure.
* gnu/installer/newt.scm (welcome-page): Add #:pci-database and pass it
to 'run-welcome-page'.
* gnu/installer/newt/welcome.scm (%unsupported-linux-modules): New
variable.
(unsupported-pci-device?, pci-device-description): New procedures.
(check-hardware-support): Add #:pci-database.  Enumerate unsupported PCI
devices and run an error page when unsupported devices are found.
(run-welcome-page): Add #:pci-database and pass it to
'check-hardware-support'.
* gnu/installer/record.scm (<installer>)[welcome-page]: Adjust comment.
---
 gnu/installer.scm              |  6 ++-
 gnu/installer/newt.scm         |  4 +-
 gnu/installer/newt/welcome.scm | 78 +++++++++++++++++++++++++++++++---
 gnu/installer/record.scm       |  2 +-
 4 files changed, 80 insertions(+), 10 deletions(-)

Comments

pelzflorian (Florian Pelz) Nov. 5, 2022, 5:55 p.m. UTC | #1
This is great work.

To test, I reverted the (current-guix) patch and instead pointed the
guix package source to (url "/home/florian/src/guix") and doing

GUIX_ALLOW_ME_TO_USE_PRIVATE_COMMIT=y make update-guix-package

so I could test the patch.  I also had to guix pull from a channel with
this local checkout, because

./pre-inst-env guix system image -t iso9660 gnu/system/install.scm

still insists on authenticating

florian@floriandesktop ~/src/guix [env]$ ./pre-inst-env guix system image -t iso9660 gnu/system/install.scm 
;;; compiling /home/florian/src/guix/gnu/system/examples/bare-bones.tmpl
;;; compiled /home/florian/.cache/guile/ccache/3.0-LE-8-4.6/home/florian/src/guix/gnu/system/examples/bare-bones.tmpl.go
;;; compiling /home/florian/src/guix/gnu/system/examples/bare-bones.tmpl
;;; compiled /home/florian/.cache/guile/ccache/3.0-LE-8-4.6/home/florian/src/guix/gnu/system/examples/bare-bones.tmpl.go
;;; compiling /home/florian/src/guix/gnu/system/examples/bare-bones.tmpl
;;; compiled /home/florian/.cache/guile/ccache/3.0-LE-8-4.6/home/florian/src/guix/gnu/system/examples/bare-bones.tmpl.go
Updating channel 'guix' from Git repository at '/home/florian/src/guix/'...
Authenticating channel 'guix', commits 9edb3f6 to 8d31a8c (977 new commits)...
[                                                                              ]guix system: error: commit 8d31a8c042bcedf34d911047c628ee4290f0b3cd lacks a signature


Why does it authenticate?  This is a strange antifeature, but I can’t
tell where in the code the authentication is called.

Anyway, after `guix pull`ing a guix channel with the local checkout,
`guix system image -t iso9660 gnu/system/install.scm` went fine.

I digress.  About the patch:

Ludovic Courtès <ludo@gnu.org> writes:
> Newer laptops are known to require
> non-free firmware a range of devices¹ and it would be nice to
> cover the important ones.
> 
> Thoughts?
> 
> Ludo’.
> 
> ¹ https://blog.einval.com/2022/04/19#firmware-what-do-we-do

In my limited experience, much hardware was always broken.
I don’t have modern hardware with iwlwifi, but my ancient laptop has
broken hardware, namely a SiS 191 Gigabit Ethernet Adapter.

While the adapter can download things with wget, when I use this
Ethernet controller to guix system init, Guix gets stuck immediately,
even though
<https://h-node.org/ethernetcards/catalogue/en/1/1/Silicon-Integrated-Systems-SiS/undef/undef/undef/ethernet-works/undef>
makes the dubitable claim that this Ethernet controller works fine.
Note that I have no issues with USB Ethernet adapters.  Therefore,

> +(define %unsupported-linux-modules
> +  ;; List of Linux modules that are useless without non-free firmware.
> +  '("iwlwifi"))

I added "sis190".  The patch works!  The install image prints:

Devices not supported by free software were found on your computer:

  - Silicon Integrated Systems [SiS] 191 Gigabit Ethernet Adapter
(networking device)


Yay!  Maybe you could add "sis190", maybe it doesn’t matter because it
is so old, maybe it is even just my laptop’s SiS that is broken.

By the way, looking for modern, working consumer wi-fi hardware (I
believe it does not exist), I find Realtek devices on h-node that it
claims are working with aircrack-ng, but recently there was a commit

commit b8f2eb286ec52c97048e23d326d94ae5772797e8
Author: Tobias Geerinckx-Rice <me@tobias.gr>
Date:   Sun Aug 14 02:00:00 2022 +0200

    gnu: Remove Realtek WiFi drivers with firmware blobs.
    
    rtl8821ce-linux-module contains, e.g., halhwimg8821c_fw.c and
    hal8821c_fw.c.  rtl8812au-aircrack-ng-linux-module has, e.g.,
    hal8814a_fw.c, hal8812a_fw.c, and hal8821a_fw.c.  Each of these
    examples contains non-free firmware blobs disguised as C arrays.
    
    * gnu/packages/linux.scm (rtl8821ce-linux-module)
    (rtl8812au-aircrack-ng-linux-module): Remove variables.
    
    Reported by Jacob K <jacobk@disroot.org>


But a warning for these Realtek devices can be added later when someone
actually has such hardware.  That would have been an external module
though.  Anyway, without realtek hardware I cannot judge.

Now, back to the patch:

> +(define unsupported-pci-device?
> +  ;; Arrange to load the module alias database only once.
> +  (let ((aliases (delay (known-module-aliases))))
> +    (lambda (device)
> +      "Return true if DEVICE is known to not be supported by free software."
> […]
> +(define (check-hardware-support pci-database)
> […]
> +  (let ((devices (pci-devices)))
> +    (match (filter unsupported-pci-device? devices)
> +      (()                                         ;no unsupported device
> +       #t)
> +      (unsupported
> +       (run-error-page (format #f (G_ "\
> +Devices not supported by free software were found on your computer:

In my view it would be better to lay the blame on the hardware
manufacturers, because they are the ones who should distribute free
drivers.  That is to turn it around and maybe say:

Devices with no support for free software were found on your computer:

or maybe at least “with” instead of “by”:

"Return true if DEVICE is known to not be supported with free software.


Either way, thank you!

Regards,
Florian
Mathieu Othacehe Nov. 5, 2022, 8:51 p.m. UTC | #2
Hey Ludo,

Overall, this is a very welcomed improvement :)

> -(define (check-hardware-support)
> +(define %unsupported-linux-modules
> +  ;; List of Linux modules that are useless without non-free firmware.
> +  '("iwlwifi"))
> +
> +(define unsupported-pci-device?
> +  ;; Arrange to load the module alias database only once.
> +  (let ((aliases (delay (known-module-aliases))))
> +    (lambda (device)
> +      "Return true if DEVICE is known to not be supported by free software."
> +      (any (lambda (module)
> +             (member module %unsupported-linux-modules))
> +           (matching-modules (pci-device-module-alias device)
> +                             (force aliases))))))
> +

I feel like all the hardware related part should not be part of the
gnu/installer/newt/ directory which is intended to contain mostly
Newt/GUI related stuff.

It would also be more logical for the contributors to browse the
gnu/installer/hardware.scm file for the %unsupported-linux-modules list
than the gnu/installer/newt/welcome.scm file. This can be done as a
follow up though.

I'm currently testing this patchset on a few machines with unsupported
hardware and will report back.

Thanks for this patchset,

Mathieu
Mathieu Othacehe Nov. 5, 2022, 9:11 p.m. UTC | #3
On a laptop with a non-free WiFi chip, the warning message is displayed,
as expected, nice :).

Mathieu
Ludovic Courtès Nov. 6, 2022, 11:20 a.m. UTC | #4
Hi,

"pelzflorian (Florian Pelz)" <pelzflorian@pelzflorian.de> skribis:

> ./pre-inst-env guix system image -t iso9660 gnu/system/install.scm
>
> still insists on authenticating

Ah, for that you need to replace (current-guix) in (gnu system install)
with just ‘guix’.

This is annoying; we should allow users to skip authentication of
‘current-guix’ through an environment variable.

Ludo’.
pelzflorian (Florian Pelz) Nov. 6, 2022, 7:06 p.m. UTC | #5
Ludovic Courtès <ludo@gnu.org> writes:
> Ah, for that you need to replace (current-guix) in (gnu system install)
> with just ‘guix’.

Ahh indeed, now it goes well.

> This is annoying; we should allow users to skip authentication of
> ‘current-guix’ through an environment variable.

That would be good.  Then patch 4 “installer: Use 'current-guix' for
extensions.” would not be bad anymore, because non-commiters would no
longer be left behind by it.

Regards,
Florian
Ludovic Courtès Nov. 9, 2022, 8:26 p.m. UTC | #6
Mathieu Othacehe <othacehe@gnu.org> skribis:

> On a laptop with a non-free WiFi chip, the warning message is displayed,
> as expected, nice :).

Great, thanks for testing!

Ludo’.
diff mbox series

Patch

diff --git a/gnu/installer.scm b/gnu/installer.scm
index df7625e05c..e1b040088b 100644
--- a/gnu/installer.scm
+++ b/gnu/installer.scm
@@ -46,6 +46,7 @@  (define-module (gnu installer)
   #:use-module (gnu packages nano)
   #:use-module (gnu packages ncurses)
   #:use-module (gnu packages package-management)
+  #:use-module (gnu packages pciutils)
   #:use-module (gnu packages tls)
   #:use-module (gnu packages xorg)
   #:use-module (gnu system locale)
@@ -226,7 +227,9 @@  (define (installer-steps)
           (id 'welcome)
           (compute (lambda _
                      ((installer-welcome-page current-installer)
-                      #$(local-file "installer/aux-files/logo.txt")))))
+                      #$(local-file "installer/aux-files/logo.txt")
+                      #:pci-database
+                      #$(file-append pciutils "/share/hwdata/pci.ids.gz")))))
 
          ;; Ask the user to select a timezone under glibc format.
          (installer-step
@@ -358,6 +361,7 @@  (define installer-builder
     (with-extensions (list guile-gcrypt guile-newt
                            guile-parted guile-bytestructures
                            guile-json-3 guile-git guile-webutils
+                           guile-zlib           ;for (gnu build linux-modules)
                            (current-guix) gnutls)
       (with-imported-modules `(,@(source-module-closure
                                   `(,@modules
diff --git a/gnu/installer/newt.scm b/gnu/installer/newt.scm
index 0bd0856219..60f9e75b81 100644
--- a/gnu/installer/newt.scm
+++ b/gnu/installer/newt.scm
@@ -176,8 +176,8 @@  (define* (locale-page #:key
 (define (timezone-page zonetab)
   (run-timezone-page zonetab))
 
-(define (welcome-page logo)
-  (run-welcome-page logo))
+(define* (welcome-page logo #:key pci-database)
+  (run-welcome-page logo #:pci-database pci-database))
 
 (define (menu-page steps)
   (run-menu-page steps))
diff --git a/gnu/installer/newt/welcome.scm b/gnu/installer/newt/welcome.scm
index 1c7372b3be..e9a4e0bbb4 100644
--- a/gnu/installer/newt/welcome.scm
+++ b/gnu/installer/newt/welcome.scm
@@ -19,7 +19,15 @@ 
 
 (define-module (gnu installer newt welcome)
   #:use-module ((gnu build linux-modules)
-                #:select (modules-loaded))
+                #:select (modules-loaded
+                          known-module-aliases
+                          matching-modules
+                          pci-devices
+                          pci-device-id
+                          pci-device-vendor
+                          pci-device-module-alias
+                          network-pci-device?
+                          load-pci-device-database))
   #:use-module (gnu installer dump)
   #:use-module (gnu installer steps)
   #:use-module (gnu installer utils)
@@ -30,6 +38,8 @@  (define-module (gnu installer newt welcome)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-34)
   #:use-module (srfi srfi-35)
+  #:use-module (srfi srfi-71)
+  #:use-module (ice-9 format)
   #:use-module (ice-9 match)
   #:use-module (ice-9 receive)
   #:use-module (newt)
@@ -121,7 +131,43 @@  (define (choice->item str)
         (lambda ()
           (destroy-form-and-pop form))))))
 
-(define (check-hardware-support)
+(define %unsupported-linux-modules
+  ;; List of Linux modules that are useless without non-free firmware.
+  '("iwlwifi"))
+
+(define unsupported-pci-device?
+  ;; Arrange to load the module alias database only once.
+  (let ((aliases (delay (known-module-aliases))))
+    (lambda (device)
+      "Return true if DEVICE is known to not be supported by free software."
+      (any (lambda (module)
+             (member module %unsupported-linux-modules))
+           (matching-modules (pci-device-module-alias device)
+                             (force aliases))))))
+
+(define (pci-device-description pci-database)
+  "Return a procedure that, given a PCI device, returns a string describing
+it."
+  (define (with-fallback lookup)
+    (lambda (vendor-id id)
+      (let ((vendor name (lookup vendor-id id)))
+        (values (or vendor (number->string vendor-id 16))
+                (or name (number->string id 16))))))
+
+  (define pci-lookup
+    (with-fallback (load-pci-device-database pci-database)))
+
+  (lambda (device)
+    (let ((vendor name (pci-lookup (pci-device-vendor device)
+                                   (pci-device-id device))))
+      (if (network-pci-device? device)
+          ;; TRANSLATORS: The two placeholders are the manufacturer
+          ;; and name of a PCI device.
+          (format #f (G_ "~a ~a (networking device)")
+                  vendor name)
+          (string-append vendor " " name)))))
+
+(define (check-hardware-support pci-database)
   "Warn about unsupported devices."
   (when (member "uvesafb" (modules-loaded))
     (run-error-page (G_ "\
@@ -129,9 +175,28 @@  (define (check-hardware-support)
 work well with only free software.  Expect trouble.  If after installation,
 the system does not boot, perhaps you will need to add nomodeset to the
 kernel arguments and need to configure the uvesafb kernel module.")
-                    (G_ "Pre-install warning"))))
+                    (G_ "Pre-install warning")))
 
-(define (run-welcome-page logo)
+  (let ((devices (pci-devices)))
+    (match (filter unsupported-pci-device? devices)
+      (()                                         ;no unsupported device
+       #t)
+      (unsupported
+       (run-error-page (format #f (G_ "\
+Devices not supported by free software were found on your computer:
+
+~{  - ~a~%~}
+Unfortunately, it means those devices will not be usable.
+
+To address it, we recommend choosing hardware that respects your freedom as a \
+user--hardware for which free drivers and firmware exist.  See \"Hardware \
+Considerations\" in the manual for more information.")
+                               (map (pci-device-description pci-database)
+                                    unsupported))
+                       (G_ "Hardware support warning")
+                       #:width 76)))))
+
+(define* (run-welcome-page logo #:key pci-database)
   "Run a welcome page with the given textual LOGO displayed at the center of
 the page. Ask the user to choose between manual installation, graphical
 installation and reboot."
@@ -161,11 +226,12 @@  (define (run-welcome-page logo)
    #:listbox-items
    `((,(G_ "Graphical install using a terminal based interface")
       .
-      ,check-hardware-support)
+      ,(lambda ()
+         (check-hardware-support pci-database)))
      (,(G_ "Install using the shell based process")
       .
       ,(lambda ()
-         (check-hardware-support)
+         (check-hardware-support pci-database)
          ;; Switch to TTY3, where a root shell is available for shell based
          ;; install. The other root TTY's would have been ok too.
          (system* "chvt" "3")
diff --git a/gnu/installer/record.scm b/gnu/installer/record.scm
index 20519a26c3..5e0264682f 100644
--- a/gnu/installer/record.scm
+++ b/gnu/installer/record.scm
@@ -89,7 +89,7 @@  (define-record-type* <installer>
   (partition-page installer-partition-page)
   ;; procedure void -> void
   (services-page installer-services-page)
-  ;; procedure (logo) -> void
+  ;; procedure (logo #:pci-database) -> void
   (welcome-page installer-welcome-page)
   ;; procedure (menu-proc) -> void
   (parameters-menu installer-parameters-menu)