Your message dated Thu, 26 Mar 2026 11:35:49 +0000
with message-id <[email protected]>
and subject line Bug#1064620: fixed in firmware-nonfree 20260309-1
has caused the Debian Bug report #1064620,
regarding firmware-nonfree: suggestions for the packaging, gencontrol.py and 
debian/rules
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1064620: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1064620
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Source: firmware-nonfree
Version: 20230210-5
Severity: wishlist
Tags: patch

Hello.

The source package builds with the attached changes (2 to 10), and
debdiff finds no difference in the resulting debs for
firmware-{linux,linux-nonfree,qcom-media} (testing do_extra in gencontrol.py)
firmware-realtek (testing an example of do_main in gencontrol.py)

Commit 2 to 9 are cosmetic.

Commit 10 simplifies the build system in my opinion, and may improve
the handling of spaces in file names (1#1035505).

This is a complex package and I miss context, so I may of course split
10 in separate commits or revert parts of it depending on your answer.
>From 798e5b247db70dc24ce6736a4eba7b5ae17ca41d Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Fri, 23 Feb 2024 17:10:17 +0100
Subject: [PATCH 02/10] d/README.Debian: typo

---
 debian/README.source | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/debian/README.source b/debian/README.source
index 15c11bf..43e897a 100644
--- a/debian/README.source
+++ b/debian/README.source
@@ -85,7 +85,7 @@ Optional per-file metadata:
 
 [<filename>_base] desc: One-line description for this file, used in
                         package description
-[<filename>_base] version: Verson number for this file, used in package
+[<filename>_base] version: Version number for this file, used in package
                            description
 
 To re-generate debian/control (and other files) based on these
-- 
2.39.2

>From c525da983a782b3d58e7ba4f793930e197fc05d7 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Fri, 23 Feb 2024 17:11:31 +0100
Subject: [PATCH 03/10] d/clean: instead of complexity in d/rules

---
 debian/clean | 2 ++
 debian/rules | 1 -
 2 files changed, 2 insertions(+), 1 deletion(-)
 create mode 100644 debian/clean

diff --git a/debian/clean b/debian/clean
new file mode 100644
index 0000000..b0bff90
--- /dev/null
+++ b/debian/clean
@@ -0,0 +1,2 @@
+debian/build/
+debian/lib/python/__pycache__/
diff --git a/debian/rules b/debian/rules
index 5867d9f..ccd41a7 100755
--- a/debian/rules
+++ b/debian/rules
@@ -15,7 +15,6 @@ build-indep build-arch build: debian/control
 
 clean: debian/control
 	dh_testdir
-	rm -rf debian/build debian/lib/python/__pycache__
 	dh_clean
 
 binary-indep: build-indep
-- 
2.39.2

>From d193cb90f02e2c669c1ad2fb91759f4d9c3591e8 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Fri, 23 Feb 2024 17:28:04 +0100
Subject: [PATCH 04/10] d/rules: use dpkg pkg-info.mk snippet instead of
 reinventing it

---
 debian/rules | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/debian/rules b/debian/rules
index ccd41a7..d9a2d38 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,10 +1,9 @@
 #!/usr/bin/make -f
 SHELL := sh -e
-SOURCE := $(shell dpkg-parsechangelog -SSource)
-VERSION := $(shell dpkg-parsechangelog -SVersion)
-VERSION_UPSTREAM := $(shell echo "$(VERSION)" | sed -e 's,-[^-]*$$,,')
-VERSION_BINNMU := $(shell echo "$(VERSION)" | sed -rne 's,.*\+b([0-9]+)$$,\1,p')
-VERSION_SOURCE := $(patsubst %+b$(VERSION_BINNMU),%,$(VERSION))
+
+include /usr/share/dpkg/pkg-info.mk
+VERSION_BINNMU := $(shell echo "$(DEB_VERSION)" | sed -rne 's,.*\+b([0-9]+)$$,\1,p')
+VERSION_SOURCE := $(patsubst %+b$(VERSION_BINNMU),%,$(DEB_VERSION))
 
 include debian/rules.defs
 
@@ -35,7 +34,7 @@ CONTROL_FILES += debian/bin/gencontrol.py debian/config/defines $(wildcard debia
 # in the checksum.
 debian/build/version-info: debian/changelog
 	mkdir -p $(@D)
-	printf >$@ 'Source: %s\nVersion: %s\n' $(SOURCE) $(VERSION_SOURCE)
+	printf >$@ 'Source: %s\nVersion: %s\n' $(DEB_SOURCE) $(VERSION_SOURCE)
 
 debian/control debian/rules.gen: $(GENCONTROL) $(CONTROL_FILES)
 ifeq ($(wildcard debian/control.md5sum),)
@@ -59,8 +58,8 @@ debian/control-real: $(GENCONTROL) $(CONTROL_FILES)
 	@echo
 	exit 1
 
-DIR_ORIG = ../orig/$(SOURCE)-$(VERSION_UPSTREAM)
-TAR_ORIG_NAME = $(SOURCE)_$(VERSION_UPSTREAM).orig.tar.xz
+DIR_ORIG = ../orig/$(DEB_SOURCE)-$(DEB_VERSION_UPSTREAM)
+TAR_ORIG_NAME = $(DEB_SOURCE)_$(DEB_VERSION_UPSTREAM).orig.tar.xz
 TAR_ORIG = $(firstword $(wildcard ../$(TAR_ORIG_NAME)) $(wildcard ../orig/$(TAR_ORIG_NAME)))
 
 orig: $(DIR_ORIG)
-- 
2.39.2

>From 1327a9f8e15b602e7f3df768758f478b548dbd50 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Fri, 23 Feb 2024 17:28:38 +0100
Subject: [PATCH 05/10] d/rules: expand GENCONTROL instead of duplicating its
 contents

---
 debian/rules | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/debian/rules b/debian/rules
index d9a2d38..f455e5e 100755
--- a/debian/rules
+++ b/debian/rules
@@ -26,9 +26,9 @@ binary-arch: build-arch
 binary:	binary-indep binary-arch
 
 CONTROL_FILES = debian/build/version-info $(wildcard debian/templates/*.in)
-CONTROL_FILES += debian/bin/gencontrol.py debian/config/defines $(wildcard debian/config/*/defines) debian/modinfo.json
+CONTROL_FILES += $(GENCONTROL) debian/config/defines $(wildcard debian/config/*/defines) debian/modinfo.json
 
-# debian/bin/gencontrol.py uses debian/changelog as input, but the
+# GENCONTROL uses debian/changelog as input, but the
 # output only depends on the source name and version.  To avoid
 # frequent changes to debian/control.md5sum, include only those fields
 # in the checksum.
-- 
2.39.2

>From 568294221c5a8ba01a92952744ea96b6eda464db Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Fri, 23 Feb 2024 17:36:45 +0100
Subject: [PATCH 06/10] d/watch: update format to version 4, add spaces for
 readability

---
 debian/watch | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/debian/watch b/debian/watch
index f09afbf..1e4102e 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,4 +1,10 @@
-version=3
-opts="mode=git, gitmode=shallow, pgpmode=gittag" \
+version=4
+
+opts="\
+  mode=git,\
+  gitmode=shallow,\
+  pgpmode=gittag,\
+" \
 https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git \
-refs/tags/(.*) debian
+refs/tags/(.*) \
+debian
-- 
2.39.2

>From 94edbc25117933a9e71db715333f29be54f110bf Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Fri, 23 Feb 2024 17:22:19 +0100
Subject: [PATCH 07/10] gencontrol.py: open files with context managers

---
 debian/bin/gencontrol.py | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py
index 293432b..11249d0 100755
--- a/debian/bin/gencontrol.py
+++ b/debian/bin/gencontrol.py
@@ -258,18 +258,21 @@ class GenControl(debian_linux.gencontrol.Gencontrol):
 
         if 'initramfs-tools' in config_entry.get('support', []):
             postinst = self.templates.get('postinst.initramfs-tools')
-            open("debian/firmware-%s.postinst" % package, 'w').write(self.substitute(postinst, vars))
+            with open(f'debian/firmware-{package}.postinst', 'w') as postint_f:
+                postint_f.write(self.substitute(postinst, vars))
 
         if 'license-accept' in config_entry:
-            license = open("%s/LICENSE.install" % package_dir, 'r').read()
+            with open(f'{package_dir}/LICENSE.install', 'r') as license_f:
+                license = license_f.read()
             preinst = self.templates.get('preinst.license')
             preinst_filename = "debian/firmware-%s.preinst" % package
-            open(preinst_filename, 'w').write(self.substitute(preinst, vars))
+            with open(preinst_filename, 'w') as preinst_f:
+                preinst_f.write(self.substitute(preinst, vars))
 
             templates = self.templates.get_templates_control('templates.license', vars)
             templates[0]['Description'].append(re.sub('\n\n', '\n.\n', license))
             templates_filename = "debian/firmware-%s.templates" % package
-            self.write_rfc822(open(templates_filename, 'w'), templates)
+            self.write_rfc822(templates_filename, templates)
 
             desc = packages_binary[0]['Description']
             desc.append(
@@ -290,7 +293,8 @@ You must agree to the terms of this license before it is installed."""
         vars['longdesc-metainfo'] = re.sub(r'\s+', ' ', vars['longdesc'])
         package_meta_temp = self.templates.get("metainfo.xml", {})
         # XXX Might need to escape some characters
-        open("debian/firmware-%s.metainfo.xml" % package, 'w').write(self.substitute(package_meta_temp, vars))
+        with open(f'debian/firmware-{package}.metainfo.xml', 'w') as meta_f:
+            meta_f.write(self.substitute(package_meta_temp, vars))
 
     def process_template(self, in_entry, vars):
         e = Template()
@@ -324,18 +328,18 @@ You must agree to the terms of this license before it is installed."""
         self.write_makefile(makefile)
 
     def write_control(self, list):
-        self.write_rfc822(open("debian/control", 'w'), list)
+        self.write_rfc822('debian/control', list)
 
     def write_makefile(self, makefile):
-        f = open("debian/rules.gen", 'w')
-        makefile.write(f)
-        f.close()
-
-    def write_rfc822(self, f, list):
-        for entry in list:
-            for key, value in entry.items():
-                f.write("%s: %s\n" % (key, value))
-            f.write('\n')
+        with open('debian/rules.gen', 'w') as f:
+            makefile.write(f)
+
+    def write_rfc822(self, path, list):
+        with open(path, 'w') as f:
+            for entry in list:
+                for key, value in entry.items():
+                    f.write("%s: %s\n" % (key, value))
+                f.write('\n')
 
 if __name__ == '__main__':
     GenControl()()
-- 
2.39.2

>From ab600a244f3ca4b12c124c01c04f775a77adc699 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Sun, 25 Feb 2024 01:07:44 +0100
Subject: [PATCH 08/10] gencontrol.py: import standard library before local
 modules

---
 debian/bin/gencontrol.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py
index 11249d0..1f5b574 100755
--- a/debian/bin/gencontrol.py
+++ b/debian/bin/gencontrol.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 
+from collections import OrderedDict
 import io
 import json
 import locale
@@ -18,7 +19,6 @@ import debian_linux.gencontrol
 from debian_linux.gencontrol import Makefile, MakeFlags, PackagesList
 from debian_linux.utils import TextWrapper
 from debian_linux.utils import Templates as TemplatesBase
-from collections import OrderedDict
 
 class PackageDescription(PackageDescriptionBase):
     __slots__ = ()
-- 
2.39.2

>From fdadbaf724a06a554ee19da02bf8d6434aa516d6 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Sun, 25 Feb 2024 01:16:09 +0100
Subject: [PATCH 09/10] gencontrol.py: remove unused process_template methods

---
 debian/bin/gencontrol.py | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py
index 1f5b574..fdaaf6b 100755
--- a/debian/bin/gencontrol.py
+++ b/debian/bin/gencontrol.py
@@ -296,23 +296,6 @@ You must agree to the terms of this license before it is installed."""
         with open(f'debian/firmware-{package}.metainfo.xml', 'w') as meta_f:
             meta_f.write(self.substitute(package_meta_temp, vars))
 
-    def process_template(self, in_entry, vars):
-        e = Template()
-        for key, value in in_entry.items():
-            if isinstance(value, PackageDescription):
-                e[key] = self.process_description(value, vars)
-            elif key[:2] == 'X-':
-                pass
-            else:
-                e[key] = self.substitute(value, vars)
-        return e
-
-    def process_templates(self, in_entries, vars):
-        entries = []
-        for i in in_entries:
-            entries.append(self.process_template(i, vars))
-        return entries
-
     def substitute(self, s, vars):
         if isinstance(s, (list, tuple)):
             return [self.substitute(i, vars) for i in s]
-- 
2.39.2

>From e9ac0ac9976f9c05206f492c3cfcece7981887b9 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <[email protected]>
Date: Sun, 25 Feb 2024 01:26:35 +0100
Subject: [PATCH 10/10] Simplify gencontrol.py and its interaction with
 debian/rules

Before:
  d/bin/gencontrol.py
    encodes a list of files and links to install as Make variables
    generates d/rules.gen as a Makefile running d/rules.real
  d/rules
    invokes 'make -f d/rules.gen' recursively
  d/rules.real
    installs things (and displays its actions)
    runs debhelper tools
After:
  d/bin/gencontrol.py
    generates d/rules.gen as a shell script installing files and links
  d/rules:
    uses the dh driver and debhelper overrides in the usual way
    (displays and) executes d/rules.gen

In gencontrol.py
 * remove the GenControl class.
   The ancestor class was unused, and the attributes are more explicit
   as parameters in procedure calls.
 * Move modinfo and firmware_modules from main() to the more specific
   do_main().
 * Rename the templates local variable to avoid a clash with the
   argument.
 * Add a append_to_rules_gen procedure in charge of the generation.
---
 debian/bin/gencontrol.py | 469 +++++++++++++++++++--------------------
 debian/rules             |  29 ++-
 debian/rules.real        |  45 ----
 3 files changed, 251 insertions(+), 292 deletions(-)
 delete mode 100644 debian/rules.real

diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py
index fdaaf6b..162ae9a 100755
--- a/debian/bin/gencontrol.py
+++ b/debian/bin/gencontrol.py
@@ -15,8 +15,7 @@ locale.setlocale(locale.LC_CTYPE, "C.UTF-8")
 from config import Config
 from debian_linux.debian import BinaryPackage, PackageRelation, _ControlFileDict
 from debian_linux.debian import PackageDescription as PackageDescriptionBase
-import debian_linux.gencontrol
-from debian_linux.gencontrol import Makefile, MakeFlags, PackagesList
+from debian_linux.gencontrol import PackagesList
 from debian_linux.utils import TextWrapper
 from debian_linux.utils import Templates as TemplatesBase
 
@@ -70,259 +69,259 @@ class Templates(TemplatesBase):
         return Template.read_rfc822(io.StringIO(self.get(key, context)))
 
 
-class GenControl(debian_linux.gencontrol.Gencontrol):
-    def __init__(self):
-        self.config = Config()
-        self.templates = Templates()
+def main():
+    config = Config()
+    templates = Templates()
+    packages = PackagesList()
+    do_source(templates, packages)
+    do_extra(config, templates, packages)
+    do_main(config, templates, packages)
+    write_rfc822('debian/control', packages.values())
 
-        with open('debian/modinfo.json', 'r') as f:
-            self.modinfo = json.load(f)
 
-        # Make another dict keyed by firmware names
-        self.firmware_modules = {}
-        for name, info  in self.modinfo.items():
-            for firmware_filename in info['firmware']:
-                self.firmware_modules.setdefault(firmware_filename, []) \
-                                     .append(name)
+def do_source(templates, packages):
+    packages['source'] = templates.get_source_control("control.source", {})[0]
 
-    def __call__(self):
-        packages = PackagesList()
-        makefile = Makefile()
 
-        self.do_source(packages)
-        self.do_extra(packages, makefile)
-        self.do_main(packages, makefile)
+def do_extra(config, templates, packages):
+    config_entry = config['base',]
+    vars = {}
+    vars.update(config_entry)
 
-        self.write(packages, makefile)
+    for package_binary in templates.get_control("control.extra", {}):
+        assert package_binary['Package'].startswith('firmware-')
 
-    def do_source(self, packages):
-        packages['source'] = self.templates.get_source_control("control.source", {})[0]
+        packages.append(package_binary)
 
-    def do_extra(self, packages, makefile):
-        config_entry = self.config['base',]
-        vars = {}
-        vars.update(config_entry)
 
-        for package_binary in self.templates.get_control("control.extra", {}):
-            assert package_binary['Package'].startswith('firmware-')
-            package = package_binary['Package'].replace('firmware-', '')
+def do_main(config, templates, packages):
 
-            makeflags = MakeFlags()
-            makeflags['FILES'] = ''
-            makeflags['PACKAGE'] = package
-            makefile.add_cmds('binary-indep', ["$(MAKE) -f debian/rules.real binary-indep %s" % makeflags])
+    with open('debian/modinfo.json', 'r') as f:
+        modinfo: dict[str, dict[str, list[str]]] = json.load(f)
 
-            packages.append(package_binary)
+    # Make another dict keyed by firmware names
+    firmware_modules: dict[str, list[str]] = {}
+    for name, info in modinfo.items():
+        for firmware_filename in info['firmware']:
+            firmware_modules.setdefault(firmware_filename, []) \
+                            .append(name)
 
-    def do_main(self, packages, makefile):
-        config_entry = self.config['base',]
-        vars = {}
-        vars.update(config_entry)
-
-        makeflags = MakeFlags()
-
-        for i in ('build', 'binary-arch', 'setup'):
-            makefile.add_cmds("%s_%%" % i, ["@true"])
+    config_entry = config['base',]
+    vars = {}
+    vars.update(config_entry)
 
+    with open('debian/rules.gen', 'w') as rules_gen:
         for package in config_entry['packages']:
-            self.do_package(packages, makefile, package, vars.copy(), makeflags.copy())
-
-    def do_package(self, packages, makefile, package, vars, makeflags):
-        config_entry = self.config['base', package]
-        vars.update(config_entry)
-        vars['package'] = package
-        vars['package-env-prefix'] = 'FIRMWARE_' + package.upper().replace('-', '_')
-
-        makeflags['PACKAGE'] = package
-
-        # Those might be absent, set them to empty string for replacement to work:
-        empty_list = ['replaces', 'conflicts', 'breaks', 'provides', 'recommends']
-        for optional in ['replaces', 'conflicts', 'breaks', 'provides', 'recommends']:
-            if optional not in vars:
-                vars[optional] = ''
-
-        package_dir = "debian/config/%s" % package
-
+            do_package(config, templates, modinfo, firmware_modules,
+                       packages, rules_gen, package, vars.copy())
+
+
+def do_package(config, templates, modinfo, firmware_modules,
+               packages, rules_gen, package, vars):
+    config_entry = config['base', package]
+    vars.update(config_entry)
+    vars['package'] = package
+    vars['package-env-prefix'] = 'FIRMWARE_' + package.upper().replace('-', '_')
+
+    # Those might be absent, set them to empty string for replacement to work:
+    for optional in ['replaces', 'conflicts', 'breaks', 'provides', 'recommends']:
+        if optional not in vars:
+            vars[optional] = ''
+
+    package_dir = "debian/config/%s" % package
+
+    try:
+        os.unlink('debian/firmware-%s.bug-presubj' % package)
+    except OSError:
+        pass
+    os.symlink('bug-presubj', 'debian/firmware-%s.bug-presubj' % package)
+
+    files_orig = config_entry['files']
+    files_real = {}
+    files_unused = []
+    links = {}
+    links_rev = {}
+
+    # Look for additional and replacement files in binary package config
+    for root, dirs, files in os.walk(package_dir):
         try:
-            os.unlink('debian/firmware-%s.bug-presubj' % package)
-        except OSError:
+            dirs.remove('.svn')
+        except ValueError:
             pass
-        os.symlink('bug-presubj', 'debian/firmware-%s.bug-presubj' % package)
-
-        files_orig = config_entry['files']
-        files_real = {}
-        files_unused = []
-        links = {}
-        links_rev = {}
-
-        # Look for additional and replacement files in binary package config
-        for root, dirs, files in os.walk(package_dir):
-            try:
-                dirs.remove('.svn')
-            except ValueError:
-                pass
-            for f in files:
-                cur_path = root + '/' + f
-                if root != package_dir:
-                    f = root[len(package_dir) + 1 : ] + '/' + f
-                if os.path.islink(cur_path):
-                    if f in files_orig:
-                        links[f] = os.readlink(cur_path)
-                    continue
-                f1 = f.rsplit('-', 1)
+        for f in files:
+            cur_path = root + '/' + f
+            if root != package_dir:
+                f = root[len(package_dir) + 1 : ] + '/' + f
+            if os.path.islink(cur_path):
                 if f in files_orig:
-                    files_real[f] = f, cur_path, None
-                    continue
-                if len(f1) > 1:
-                    f_base, f_version = f1
-                    if f_base in files_orig:
-                        if f_base in files_real:
-                            raise RuntimeError("Multiple files for %s" % f_base)
-                        files_real[f_base] = f_base, package_dir + '/' + f, \
-                                             f_version
-                        continue
-                # Whitelist files not expected to be installed as firmware
-                if f in ['defines', 'LICENSE.install',
-                         'update.py', 'update.sh']:
+                    links[f] = os.readlink(cur_path)
+                continue
+            f1 = f.rsplit('-', 1)
+            if f in files_orig:
+                files_real[f] = f, cur_path, None
+                continue
+            if len(f1) > 1:
+                f_base, f_version = f1
+                if f_base in files_orig:
+                    if f_base in files_real:
+                        raise RuntimeError("Multiple files for %s" % f_base)
+                    files_real[f_base] = f_base, package_dir + '/' + f, \
+                                         f_version
                     continue
-                files_unused.append(f)
-
-        # Take all the other files from upstream
-        for f in files_orig:
-            if f not in files_real and f not in links:
-                f_upstream = os.path.join('debian/build/install', f)
-                if os.path.islink(f_upstream):
-                    links[f] = os.readlink(f_upstream)
-                elif os.path.isfile(f_upstream):
-                    files_real[f] = f, f_upstream, None
-
-        for f in links:
-            link_target = os.path.normpath(os.path.join(f, '..', links[f]))
-            links_rev.setdefault(link_target, []).append(f)
-
-        if files_unused:
-            print('W: %s: unused files:' % package, ' '.join(files_unused),
-                  file=sys.stderr)
-
-        makeflags['FILES'] = ' '.join(["%s:%s" % (i[1], i[0]) for i in sorted(files_real.values())])
-        vars['files_real'] = ' '.join(["/lib/firmware/%s" % i for i in config_entry['files']])
-
-        makeflags['LINKS'] = ' '.join(["%s:%s" % (link, target)
-                                       for link, target in sorted(links.items())])
-
-        files_desc = ["Contents:"]
-        firmware_meta_temp = self.templates.get("metainfo.xml.firmware")
-        firmware_meta_list = []
-        module_names = set()
-
-        wrap = TextWrapper(width = 71, fix_sentence_endings = True,
-                           initial_indent = ' * ',
-                           subsequent_indent = '   ').wrap
-        for f in config_entry['files']:
-            firmware_meta_list.append(self.substitute(firmware_meta_temp,
-                                                      {'filename': f}))
-            for module_name in self.firmware_modules.get(f, []):
-                module_names.add(module_name)
-            if f in links:
+            # Whitelist files not expected to be installed as firmware
+            if f in ['defines', 'LICENSE.install',
+                     'update.py', 'update.sh']:
                 continue
-            f, f_real, version = files_real[f]
-            c = self.config.get(('base', package, f), {})
-            desc = c.get('desc')
-            if version is None:
-                version = c.get('version')
-            try:
-                f = f + ', ' + ', '.join(sorted(links_rev[f]))
-            except KeyError:
-                pass
-            if desc and version:
-                desc = "%s, version %s (%s)" % (desc, version, f)
-            elif desc:
-                desc = "%s (%s)" % (desc, f)
-            else:
-                desc = "%s" % f
-            files_desc.extend(wrap(desc))
-
-        modaliases = set()
-        for module_name in module_names:
-            for modalias in self.modinfo[module_name]['alias']:
-                modaliases.add(modalias)
-        modalias_meta_list = [
-            self.substitute(self.templates.get("metainfo.xml.modalias"),
-                            {'alias': alias})
-            for alias in sorted(list(modaliases))
-        ]
-
-        packages_binary = self.templates.get_control("control.binary", vars)
-
-        packages_binary[0]['Description'].append_pre(files_desc)
-
-        if 'initramfs-tools' in config_entry.get('support', []):
-            postinst = self.templates.get('postinst.initramfs-tools')
-            with open(f'debian/firmware-{package}.postinst', 'w') as postint_f:
-                postint_f.write(self.substitute(postinst, vars))
-
-        if 'license-accept' in config_entry:
-            with open(f'{package_dir}/LICENSE.install', 'r') as license_f:
-                license = license_f.read()
-            preinst = self.templates.get('preinst.license')
-            preinst_filename = "debian/firmware-%s.preinst" % package
-            with open(preinst_filename, 'w') as preinst_f:
-                preinst_f.write(self.substitute(preinst, vars))
-
-            templates = self.templates.get_templates_control('templates.license', vars)
-            templates[0]['Description'].append(re.sub('\n\n', '\n.\n', license))
-            templates_filename = "debian/firmware-%s.templates" % package
-            self.write_rfc822(templates_filename, templates)
-
-            desc = packages_binary[0]['Description']
-            desc.append(
+            files_unused.append(f)
+
+    # Take all the other files from upstream
+    for f in files_orig:
+        if f not in files_real and f not in links:
+            f_upstream = os.path.join('debian/build/install', f)
+            if os.path.islink(f_upstream):
+                links[f] = os.readlink(f_upstream)
+            elif os.path.isfile(f_upstream):
+                files_real[f] = f, f_upstream, None
+
+    for f in links:
+        link_target = os.path.normpath(os.path.join(f, '..', links[f]))
+        links_rev.setdefault(link_target, []).append(f)
+
+    if files_unused:
+        print('W: %s: unused files:' % package, ' '.join(files_unused),
+              file=sys.stderr)
+
+    vars['files_real'] = ' '.join(["/lib/firmware/%s" % i for i in config_entry['files']])
+
+    append_to_rules_gen(rules_gen, package, files_real, links)
+
+    files_desc = ["Contents:"]
+    firmware_meta_temp = templates.get("metainfo.xml.firmware")
+    firmware_meta_list = []
+    module_names = set()
+
+    wrap = TextWrapper(width = 71, fix_sentence_endings = True,
+                       initial_indent = ' * ',
+                       subsequent_indent = '   ').wrap
+    for f in config_entry['files']:
+        firmware_meta_list.append(substitute(firmware_meta_temp,
+                                             {'filename': f}))
+        for module_name in firmware_modules.get(f, []):
+            module_names.add(module_name)
+        if f in links:
+            continue
+        f, f_real, version = files_real[f]
+        c = config.get(('base', package, f), {})
+        desc = c.get('desc')
+        if version is None:
+            version = c.get('version')
+        try:
+            f = f + ', ' + ', '.join(sorted(links_rev[f]))
+        except KeyError:
+            pass
+        if desc and version:
+            desc = "%s, version %s (%s)" % (desc, version, f)
+        elif desc:
+            desc = "%s (%s)" % (desc, f)
+        else:
+            desc = "%s" % f
+        files_desc.extend(wrap(desc))
+
+    modaliases = set()
+    for module_name in module_names:
+        for modalias in modinfo[module_name]['alias']:
+            modaliases.add(modalias)
+    modalias_meta_list = [
+        substitute(templates.get("metainfo.xml.modalias"),
+                   {'alias': alias})
+        for alias in sorted(list(modaliases))
+    ]
+
+    packages_binary = templates.get_control("control.binary", vars)
+
+    packages_binary[0]['Description'].append_pre(files_desc)
+
+    if 'initramfs-tools' in config_entry.get('support', []):
+        postinst = templates.get('postinst.initramfs-tools')
+        with open(f'debian/firmware-{package}.postinst', 'w') as postint_f:
+            postint_f.write(substitute(postinst, vars))
+
+    if 'license-accept' in config_entry:
+        with open(f'{package_dir}/LICENSE.install', 'r') as license_f:
+            license = license_f.read()
+        preinst = templates.get('preinst.license')
+        preinst_filename = "debian/firmware-%s.preinst" % package
+        with open(preinst_filename, 'w') as preinst_f:
+            preinst_f.write(substitute(preinst, vars))
+
+        templates_license = templates.get_templates_control('templates.license', vars)
+        templates_license[0]['Description'].append(re.sub('\n\n', '\n.\n', license))
+        templates_filename = "debian/firmware-%s.templates" % package
+        write_rfc822(templates_filename, templates_license)
+
+        desc = packages_binary[0]['Description']
+        desc.append(
 """This firmware is covered by the %s.
 You must agree to the terms of this license before it is installed."""
 % vars['license-title'])
-            packages_binary[0]['Pre-Depends'] = PackageRelation('debconf | debconf-2.0')
-
-        packages.extend(packages_binary)
-
-        makefile.add_cmds('binary-indep', ["$(MAKE) -f debian/rules.real binary-indep %s" % makeflags])
-
-        vars['firmware-list'] = ''.join(firmware_meta_list)
-        vars['modalias-list'] = ''.join(modalias_meta_list)
-        # Underscores are preferred to hyphens
-        vars['package-metainfo'] = package.replace('-', '_')
-        # Summary must not contain line breaks
-        vars['longdesc-metainfo'] = re.sub(r'\s+', ' ', vars['longdesc'])
-        package_meta_temp = self.templates.get("metainfo.xml", {})
-        # XXX Might need to escape some characters
-        with open(f'debian/firmware-{package}.metainfo.xml', 'w') as meta_f:
-            meta_f.write(self.substitute(package_meta_temp, vars))
-
-    def substitute(self, s, vars):
-        if isinstance(s, (list, tuple)):
-            return [self.substitute(i, vars) for i in s]
-        def subst(match):
-            if match.group(1):
-                return vars.get(match.group(2), '')
-            else:
-                return vars[match.group(2)]
-        return re.sub(r'@(\??)([-_a-z]+)@', subst, str(s))
-
-    def write(self, packages, makefile):
-        self.write_control(packages.values())
-        self.write_makefile(makefile)
-
-    def write_control(self, list):
-        self.write_rfc822('debian/control', list)
-
-    def write_makefile(self, makefile):
-        with open('debian/rules.gen', 'w') as f:
-            makefile.write(f)
-
-    def write_rfc822(self, path, list):
-        with open(path, 'w') as f:
-            for entry in list:
-                for key, value in entry.items():
-                    f.write("%s: %s\n" % (key, value))
-                f.write('\n')
+        packages_binary[0]['Pre-Depends'] = PackageRelation('debconf | debconf-2.0')
+
+    packages.extend(packages_binary)
+
+    vars['firmware-list'] = ''.join(firmware_meta_list)
+    vars['modalias-list'] = ''.join(modalias_meta_list)
+    # Underscores are preferred to hyphens
+    vars['package-metainfo'] = package.replace('-', '_')
+    # Summary must not contain line breaks
+    vars['longdesc-metainfo'] = re.sub(r'\s+', ' ', vars['longdesc'])
+    package_meta_temp = templates.get("metainfo.xml", {})
+    # XXX Might need to escape some characters
+    with open(f'debian/firmware-{package}.metainfo.xml', 'w') as meta_f:
+        meta_f.write(substitute(package_meta_temp, vars))
+
+
+def append_to_rules_gen(rules_gen, package, files_real, links):
+    deb_pkg = f'firmware-{package}'
+    pkg_dir = f'debian/{deb_pkg}'
+    firmware_dir = f'{pkg_dir}/lib/firmware'
+
+    for dst, src, _vsn in files_real.values():
+        rules_gen.write(f"install -m644 -D '{src}' '{firmware_dir}/{dst}'\n")
+
+    # Avoid flooding the build log with redundant 'install -d'.
+    seen_dirnames = set()
+    for link, target in links.items():
+        link_path = f'{firmware_dir}/{link}'
+        link_dirname = os.path.dirname(link_path)
+
+        if link_dirname not in seen_dirnames:
+            seen_dirnames.add(link_dirname)
+            rules_gen.write(f"install -d '{link_dirname}'\n")
+
+        rules_gen.write(f"ln -s '{target}' '{link_path}'\n")
+
+    rules_gen.write(
+        f'dh_install -p{deb_pkg} {pkg_dir}.metainfo.xml usr/share/metainfo\n')
+
+
+def substitute(s, vars):
+    if isinstance(s, (list, tuple)):
+        return [substitute(i, vars) for i in s]
+    def subst(match):
+        if match.group(1):
+            return vars.get(match.group(2), '')
+        else:
+            return vars[match.group(2)]
+    return re.sub(r'@(\??)([-_a-z]+)@', subst, str(s))
+
+
+def write_rfc822(path, list):
+    with open(path, 'w') as f:
+        for entry in list:
+            for key, value in entry.items():
+                f.write("%s: %s\n" % (key, value))
+            f.write('\n')
+
 
 if __name__ == '__main__':
-    GenControl()()
+    main()
diff --git a/debian/rules b/debian/rules
index f455e5e..503d6b6 100755
--- a/debian/rules
+++ b/debian/rules
@@ -9,21 +9,26 @@ include debian/rules.defs
 
 GENCONTROL = debian/bin/gencontrol.py
 
-# Nothing to build
-build-indep build-arch build: debian/control
-
-clean: debian/control
-	dh_testdir
-	dh_clean
-
-binary-indep: build-indep
-	dh_testdir
+binary binary-arch binary-indep build build-arch build-indep clean: \
+                                                             debian/control
+	dh $@
+
+# Tell debhelper to ignore ./configure and Makefile.
+override_dh_auto_configure:
+override_dh_auto_build:
+override_dh_auto_install:
 	./copy-firmware.sh -v debian/build/install
-	$(MAKE) -f debian/rules.gen binary-indep
+override_dh_auto_test:
+
+execute_before_dh_install: debian/rules.gen
+	cat $<
+	sh -e $<
 
-binary-arch: build-arch
+override_dh_installdocs:
+	dh_installdocs -XTODO
 
-binary:	binary-indep binary-arch
+execute_after_dh_installdeb:
+	if command -v dh_movetousr >/dev/null; then dh_movetousr; fi
 
 CONTROL_FILES = debian/build/version-info $(wildcard debian/templates/*.in)
 CONTROL_FILES += $(GENCONTROL) debian/config/defines $(wildcard debian/config/*/defines) debian/modinfo.json
diff --git a/debian/rules.real b/debian/rules.real
deleted file mode 100644
index 3fa602f..0000000
--- a/debian/rules.real
+++ /dev/null
@@ -1,45 +0,0 @@
-SHELL  := sh -e
-
-export DH_OPTIONS
-
-#
-# Targets
-#
-binary-indep: install
-
-install: PACKAGE_NAME = firmware-$(PACKAGE)
-install: DH_OPTIONS = -p$(PACKAGE_NAME)
-install:
-	dh_testdir
-	dh_testroot
-	dh_prep
-	@for i in $(FILES); do \
-	  s="$${i%:*}"; \
-	  d=/lib/firmware/"$${i#*:}"; \
-	  echo install -m644 -D "$$s" debian/$(PACKAGE_NAME)"$$d"; \
-	  install -m644 -D "$$s" debian/$(PACKAGE_NAME)"$$d"; \
-	done
-	@for i in $(LINKS); do \
-	  link=debian/$(PACKAGE_NAME)/lib/firmware/"$${i%:*}"; \
-	  target="$${i#*:}"; \
-	  install -d "$${link%/*}"; \
-	  echo ln -s "$$target" "$$link"; \
-	  ln -s "$$target" "$$link"; \
-	done
-ifneq ($(FILES),)
-	dh_installdirs /usr/share/metainfo
-	dh_install debian/$(PACKAGE_NAME).metainfo.xml /usr/share/metainfo
-endif
-	dh_bugfiles
-	dh_installchangelogs
-	dh_installdocs -XTODO
-	dh_installdebconf
-	dh_lintian
-	dh_link
-	dh_compress
-	dh_fixperms
-	dh_installdeb
-	if command -v dh_movetousr >/dev/null; then dh_movetousr; fi
-	dh_gencontrol
-	dh_md5sums
-	dh_builddeb
-- 
2.39.2


--- End Message ---
--- Begin Message ---
Source: firmware-nonfree
Source-Version: 20260309-1
Done: Ben Hutchings <[email protected]>

We believe that the bug you reported is fixed in the latest version of
firmware-nonfree, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Ben Hutchings <[email protected]> (supplier of updated firmware-nonfree package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Thu, 26 Mar 2026 12:05:50 +0100
Source: firmware-nonfree
Architecture: source
Version: 20260309-1
Distribution: unstable
Urgency: medium
Maintainer: Debian Kernel Team <[email protected]>
Changed-By: Ben Hutchings <[email protected]>
Closes: 1064620 1131751
Changes:
 firmware-nonfree (20260309-1) unstable; urgency=medium
 .
   [ Ben Hutchings ]
   * New upstream version:
     - Add firmware file for Intel BlazarIGfp2 core
     - amdgpu: DMCUB updates for various ASICs
     - amdgpu: update beige goby firmware
     - amdgpu: update dimgrey cavefish firmware
     - amdgpu: update GC 10.3.6 firmware
     - amdgpu: update GC 11.0.0 firmware
     - amdgpu: update GC 11.0.1 firmware
     - amdgpu: update GC 11.0.2 firmware
     - amdgpu: update GC 11.0.3 firmware
     - amdgpu: update GC 11.0.4 firmware
     - amdgpu: update GC 11.5.0 firmware
     - amdgpu: update GC 11.5.1 firmware
     - amdgpu: update GC 11.5.2 firmware
     - amdgpu: update GC 11.5.3 firmware
     - amdgpu: update GC 12.0.0 firmware
     - amdgpu: update GC 12.0.1 firmware
     - amdgpu: update GC 9.4.3 firmware
     - amdgpu: update GC 9.4.4 firmware
     - amdgpu: update GC 9.5.0 firmware
     - amdgpu: update green sardine firmware
     - amdgpu: update navi10 firmware
     - amdgpu: update navi12 firmware
     - amdgpu: update navi14 firmware
     - amdgpu: update navy flounder firmware
     - amdgpu: update PSP 13.0.0 firmware
     - amdgpu: update PSP 13.0.0 kicker firmware
     - amdgpu: update PSP 13.0.10 firmware
     - amdgpu: update PSP 13.0.11 firmware
     - amdgpu: update PSP 13.0.12 firmware
     - amdgpu: update PSP 13.0.14 firmware
     - amdgpu: update PSP 13.0.4 firmware
     - amdgpu: update PSP 13.0.5 firmware
     - amdgpu: update PSP 13.0.6 firmware
     - amdgpu: update PSP 13.0.7 firmware
     - amdgpu: update PSP 14.0.0 firmware
     - amdgpu: update PSP 14.0.1 firmware
     - amdgpu: update PSP 14.0.2 firmware
     - amdgpu: update PSP 14.0.3 firmware
     - amdgpu: update PSP 14.0.4 firmware
     - amdgpu: update PSP 14.0.5 firmware
     - amdgpu: update renoir firmware
     - amdgpu: update SDMA 6.0.1 firmware
     - amdgpu: update SDMA 6.0.2 firmware
     - amdgpu: update SDMA 6.1.0 firmware
     - amdgpu: update SDMA 6.1.1 firmware
     - amdgpu: update SDMA 6.1.2 firmware
     - amdgpu: update SDMA 6.1.3 firmware
     - amdgpu: update sienna cichlid firmware
     - amdgpu: update SMU 14.0.2 firmware
     - amdgpu: update SMU 14.0.3 firmware
     - amdgpu: update vangogh firmware
     - amdgpu: update VCN 4.0.0 firmware
     - amdgpu: update VCN 4.0.2 firmware
     - amdgpu: update VCN 4.0.3 firmware
     - amdgpu: update VCN 4.0.4 firmware
     - amdgpu: update VCN 4.0.5 firmware
     - amdgpu: update VCN 4.0.6 firmware
     - amdgpu: update VCN 5.0.0 firmware
     - amdgpu: update VCN 5.0.1 firmware
     - amdgpu: update VPE 6.1.0 firmware
     - amdgpu: update yellow carp firmware
     - amdnpu: Restore old NPU firmware for compatibility (Closes: #1131751)
     - cirrus: cs35l63: Add firmware for Cirrus CS35L63 for various Dell laptops
     - lenovo: remove obsolete ish_lnlm_53c4ffad_2a17559f.bin firmware
     - mediatek MT7922: update bluetooth firmware to 20260224103448
     - QCA: Update Bluetooth QCA6698 firmware to 2.1.2-00069
     - QCA: Update Bluetooth WCN6856 firmware 2.1.0-00659 to 2.1.0-00665
     - qca: Update Bluetooth WCN6750 1.1.3-00105 firmware to 1.1.3-00106
     - qcom: sync audioreach firmwares from v1.0.2 build
     - qcom: update ADSP dtb.mbn for glymur platform
     - qcom: update ADSP, CDSP firmware for sm8750  platform
     - qcom: Update CDSP firmware for QCM6490 platform
     - Remove duplicate fw and Rename Lenovo ISH LNLM firmware files accordingly
     - Renaming the file back for HP EliteBook X Flip G1i
     - update firmware for MT7902 BT device
     - update firmware for MT7902 WiFi device
     - update firmware for MT7922 WiFi device
   * d/salsa-ci.yml: Disable piuparts job which fails due to common pipeline bug
   * d/copyright: Tighten filename pattern for Cirrus SDCA firmware
   * cirrus: Include Cirrus SDCA firmware
   * d/README.source: Delete obsolete description of per-file metadata
 .
   [ Nicolas Boulenguez ]
   * Clean up packaging (Closes: #1064620):
     - d/rules: include /usr/share/dpkg/pkg-info.mk
     - gencontrol.py: remove unused process_template methods
     - gencontrol.py: open files with context managers
     - d/rules: remove gencontrol.py from GENCONTROL
Checksums-Sha1:
 85fedb417eb14a4f856fe797638d4c4945d760d0 4645 firmware-nonfree_20260309-1.dsc
 7296edcf8637e3f32a96e47647e0dbec14d4d25f 335133296 
firmware-nonfree_20260309.orig.tar.xz
 097958627218575fc097424efe5b229e571e6f81 871576 
firmware-nonfree_20260309-1.debian.tar.xz
 d26aa9ab586c32756ff02a4cbf2a2657dc9d5eec 6436 
firmware-nonfree_20260309-1_source.buildinfo
Checksums-Sha256:
 ca551d95fb282fdc45b9e569fc2749a64d601b0b0491d881594606a3053962be 4645 
firmware-nonfree_20260309-1.dsc
 783e150a763561005eade386d1f6cb9f465529bed9f20a040eebaaa82fc80397 335133296 
firmware-nonfree_20260309.orig.tar.xz
 ec419913a2bfbd737ff34f05c21980839d713a88bacb50ef8fee2d90fce9361f 871576 
firmware-nonfree_20260309-1.debian.tar.xz
 026bcc494d1bce1612427fd0599b3c2a489738fe6617f89c0441239a5304bea1 6436 
firmware-nonfree_20260309-1_source.buildinfo
Files:
 0596318dd6477a4f7a87bbfe1248be5e 4645 non-free-firmware/kernel optional 
firmware-nonfree_20260309-1.dsc
 dbee5b234ec5b00dba42140871518607 335133296 non-free-firmware/kernel optional 
firmware-nonfree_20260309.orig.tar.xz
 3e0b235653fd4c91bc0e9128b326f13e 871576 non-free-firmware/kernel optional 
firmware-nonfree_20260309-1.debian.tar.xz
 c7bbcd52cb814e98745d11740725b06d 6436 non-free-firmware/kernel optional 
firmware-nonfree_20260309-1_source.buildinfo

-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEErCspvTSmr92z9o8157/I7JWGEQkFAmnFFrYACgkQ57/I7JWG
EQnmdQ//ZwxOH7GI9egofcu94slqpuQ1q5YBuneX1MSaTq3oQ9kg04EqOINL9ut/
jBoXfdgko5uSlodIJJAC6D29XGp+jN7QCLPastw08jd1zm+nMNQ79fH8S0pH3xp1
rv6Id1obUldtooKuWbHCNxcXU5Tvp0kNuUk3UWktHKXbNDLbChVplpgl1xniui/3
EWI/HIW+L5O7JFKAV8HXxHPs8urGkiSFp/Vd4iDxfhBOdQFkhK0TSJ0aQVGS3SBr
/vRNn91AL4qdb6qNcZjoj5K7r4r3gFJwZxgGsSylstmpC0c5unehBx+18tejGNs4
qYMBpO/vjrbUqEH1UhmmqYHKei3/5R+PTPx+k2uIaDl7BChet+szEGG360+ddtZn
pLyl2F/NMQ23245HwongI4hl+RKPTF60SHBJesTVYt3iveBmknAStCEujUKACF6n
UUhZpsfpCdiTsB782N95nzgOQ1/HCTGmHQMaYzgAYPkRtVEPw2uOnyu4oKeb93gQ
La6q5J5whzCANYfJn0tkTRMLnuOQk8mE2PGbZn7mPl9I+jBKD4pU4uzkqjM1mTaa
kpf9IRyK2AfB9kAL1rohAGKE9/08msTbQUdTmZIIIe7MiEldXcLpR5qwV3Q1Qvj2
rPO2QSTy3thJedsfhrHKDLn5wVqTVkz0nGGreg9k5yy2n9Fg/QE=
=R5q9
-----END PGP SIGNATURE-----

Attachment: pgpy0nbH3eANm.pgp
Description: PGP signature


--- End Message ---

Reply via email to