Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package mkdud for openSUSE:Factory checked 
in at 2025-08-28 17:19:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/mkdud (Old)
 and      /work/SRC/openSUSE:Factory/.mkdud.new.1977 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "mkdud"

Thu Aug 28 17:19:58 2025 rev:38 rq:1301793 version:2.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/mkdud/mkdud.changes      2022-09-22 
16:59:29.906226729 +0200
+++ /work/SRC/openSUSE:Factory/.mkdud.new.1977/mkdud.changes    2025-08-28 
17:20:36.996114099 +0200
@@ -1,0 +2,10 @@
+Thu Aug 28 11:40:49 UTC 2025 - wfe...@opensuse.org
+
+- merge gh#openSUSE/mkdud#42
+- make mkdud SLE-16 aware (jsc#PED-13262)
+- update man page
+- documentation update
+- adjust package dependencies
+- 2.0
+
+--------------------------------------------------------------------

Old:
----
  mkdud-1.55.tar.xz

New:
----
  mkdud-2.0.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ mkdud.spec ++++++
--- /var/tmp/diff_new_pack.RIEuZg/_old  2025-08-28 17:20:38.544178978 +0200
+++ /var/tmp/diff_new_pack.RIEuZg/_new  2025-08-28 17:20:38.564179817 +0200
@@ -17,7 +17,6 @@
 
 
 Name:           mkdud
-BuildRequires:  xz
 %if 0%?suse_version >= 1500 || 0%?sle_version >= 120400
 BuildRequires:  rubygem(asciidoctor)
 %else
@@ -26,11 +25,31 @@
 BuildRequires:  libxslt-tools
 %endif
 %endif
+%if %suse_version >= 1500
+Requires:       mkisofs
+%else
+Requires:       genisoimage
+%endif
+Requires:       binutils
+Requires:       coreutils
+Requires:       cpio
+Requires:       file
+Requires:       findutils
 Requires:       gpg2
+Requires:       grep
+Requires:       gzip
+Requires:       kmod
+Requires:       osc
+Requires:       rpm
+Requires:       rpm-build
+Requires:       tar
+Requires:       util-linux
+Requires:       xz
+Requires:       zstd
 Summary:        Create driver update from rpms
 License:        GPL-3.0-or-later
 Group:          Hardware/Other
-Version:        1.55
+Version:        2.0
 Release:        0
 Source:         %{name}-%{version}.tar.xz
 Url:            https://github.com/openSUSE/mkdud

++++++ mkdud-1.55.tar.xz -> mkdud-2.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mkdud-1.55/HOWTO.md new/mkdud-2.0/HOWTO.md
--- old/mkdud-1.55/HOWTO.md     2022-09-22 14:27:13.000000000 +0200
+++ new/mkdud-2.0/HOWTO.md      2025-08-28 13:40:49.000000000 +0200
@@ -11,32 +11,51 @@
 
 ## Use driver updates
 
-1. Use the `dud` boot option to pass a URL pointing to the driver update. For 
example:
+1. Use the `inst.dud` (Agama) or `dud` (YaST) boot option to pass a URL 
pointing to the driver update. For example:
 
-    - `dud=https://example.com/foo.dud`
+    - `inst.dud=https://example.com/foo.dud`
     - `dud=disk:/foo.dud`
 
 2. Driver updates in special places are loaded automatically:
 
-    - a file named `driverupdate` in the root directory of the installation 
medium
-    - a partition (e.g. on a USB stick) with file system label `OEMDRV` 
containing an unpacked driver update
+    - a file named `driverupdate` in the root directory of the installation 
medium (YaST only)
+    - a partition (e.g. on a USB stick) with file system label `OEMDRV` 
containing an unpacked driver update (YaST only)
     - an unpacked driver update in the initrd of the installation medium
 
+3. Apply the driver update directly to the installation medium
+
+For supported URL schemas look at
+
+- https://agama-project.github.io/docs/user/reference/boot_options (Agama)
+- https://en.opensuse.org/SDB:Linuxrc (YaST)
+
 Putting the driver update into the initrd provides a way to seamlessly 
integrate driver updates into otherwise
-unchanged SUSE installation media. The `mksusecd` command has a dedicated 
`--initrd` option to make this easy:
+unchanged SUSE installation media. The `mkmedia` command has a dedicated 
`--initrd` option to make this easy:
+
+```sh
+mkmedia --create new.iso --initrd foo.dud old.iso
+```
+
+To make changes that are otherwise technically not possible - like modifying 
the initrd or changing boot options you
+have to use the `--apply-dud` option of `mkmedia` to modify the installation 
medium directly:
 
 ```sh
-mksusecd --create new.iso --initrd foo.dud old.iso
+mkmedia --create new.iso --apply-dud foo.dud old.iso
 ```
 
+The difference between `--initrd` and `--apply-dud` is that the first makes 
the DUD available during installation
+(without any user-interaction) while the second interpretes the DUD and 
applies the changes it describes to the
+installation medium.
+
+`mkmedia` is part of the [mksusecd](https://github.com/openSUSE/mksusecd) 
package.
 
 ## Create driver updates
 
-To create driver updates use `mkdud`. You have to specify at least the product 
the driver update in intended for but it's
+To create driver updates use `mkdud`. You have to specify at least the product 
the driver update is intended for but it's
 also nice to give it a descriptive name:
 
 ```sh
-mkdud --create foo.dud --dist leap15.0 --name "Support the new bar" bar.ko
+mkdud --create foo.dud --dist leap15.6 --name "Support the new bar" bar.ko
 ```
 
 Driver updates have to be properly signed to be accepted by the installer. If 
they are not the user will
@@ -138,7 +157,7 @@
 ```
 
 
-## Adjust installation workflow
+## Adjust installation workflow (YaST only)
 
 Driver updates also prove hooks into the installation workflow. This is done 
by triggering shell scripts at specific points. They are
 
@@ -156,7 +175,7 @@
 to enable the `foo` service.
 
 
-## Execute commands
+## Execute commands (YaST only)
 
 Sometimes the commands in `update.pre` are run too late for your purpose. It 
is possible to run commands immediately (when the driver update has
 been loaded). For this, the `exec` config option can be used. For example
@@ -180,8 +199,141 @@
 mkdud --create all.dud foo.dud bar.dud zap.dud
 ```
 
+## Examples
+
+Let's look at a few basic examples.
+
+### Example 1
+
+```
+# mkdud --create foo.dud --dist sle16 --name "Test update" \
+  hello.rpm e1000.ko.xz
+===  Update #1  ===
+  [SUSE Linux Enterprise 16 (x86_64)]
+    Name:
+      Test update
+    ID:
+      3c39839e-bf42-49ee-a405-6f97c0732a9f
+    Installer:
+      Agama
+    Packages:
+      - install methods: instsys, repo
+      hello-2.12.2-1.5.x86_64.rpm  (Mon May 19 19:43:32 2025)
+    Modules:
+      e1000.ko.xz (6.12.0-160000.18-default.x86_64)
+    Installation System:
+      - package: hello-2.12.2-1.5.x86_64.rpm
+      /usr/bin/hello
+    How to apply this DUD:
+      [✔] during installation: using boot option inst.dud=URL_TO_DUD_FILE
+      [✘] during installation: unpacked on local file system with label 
'OEMDRV'
+      [✘] during installation: renamed as 'driverupdate' in installation 
repository
+      [✔] rebuilding installation media using 'mkmedia --initrd DUD_FILE ...'
+      [✔] rebuilding installation media using 'mkmedia --apply-dud DUD_FILE 
...'
+```
+
+This DUD
+
+- is intended for Agama (SLE 16)
+- updates the `hello` package in the installed (target) system
+- adds the `hello` package to the installation system
+- updates the `e1000` kernel module
+
+Note that in Agama-based installations the 'OEMDRV' and 'driverupdate' methods 
are not available.
+
+### Example 2
+
+```
+# mkdud --create foo.dud --dist tw --name "Test update" \
+  hello.rpm e1000.ko.xz \
+  --config password=xxx
+===  Update #1  ===
+  [openSUSE Tumbleweed (x86_64)]
+    Name:
+      Test update
+    ID:
+      2deb1bab-d22d-4f93-9574-77905456eaf8
+    Installer:
+      YaST
+    Packages:
+      - install methods: instsys, repo, rpm (repo priority 50)
+      hello-2.12.2-1.5.x86_64.rpm  (Mon May 19 19:43:32 2025)
+    Modules:
+      e1000.ko.xz (6.12.0-160000.18-default.x86_64)
+    Scripts:
+      update.pre, update.post2
+    Installation System:
+      - package: hello-2.12.2-1.5.x86_64.rpm
+      /usr/bin/hello
+    Config Entries:
+      password = xxx
+    How to apply this DUD:
+      [✔] during installation: using boot option dud=URL_TO_DUD_FILE
+      [✔] during installation: unpacked on local file system with label 
'OEMDRV'
+      [✔] during installation: renamed as 'driverupdate' in installation 
repository
+      [✔] rebuilding installation media using 'mkmedia --initrd DUD_FILE ...'
+      [✔] rebuilding installation media using 'mkmedia --apply-dud DUD_FILE 
...'
+```
+
+This DUD
+
+- is intended for YaST (Tumbleweed)
+- updates the `hello` package in the installed (target) system
+- adds the `hello` package to the installation system
+- updates the `e1000` kernel module
+- sets the root password used in the installation system (e.g. for ssh access)
+
+Since in YaST-based installations config setting are possible, the DUD can be 
applied by any method.
+
+Note that `mkdud` automatically generates `update.pre` and `update.post2` 
scripts that handle adding and removing a
+driver update software repository (needed for 'repo' install method) during 
installation.
+
+### Example 3
+
+```
+# mkdud --create foo.dud --dist leap16.0 --name "Test update" \
+  --initrd hello.rpm \
+  e1000.ko.xz \
+  --config live.password=xxx --config boot=nomodeset
+===  Update #1  ===
+  [openSUSE Leap 16.0 (x86_64)]
+    Name:
+      Test update
+    ID:
+      45f627da-b7c4-48ed-94c1-31e25ed92442
+    Installer:
+      YaST
+    Modules:
+      e1000.ko.xz (6.12.0-160000.18-default.x86_64)
+    Initrd:
+      - package: hello-2.12.2-1.5.x86_64.rpm
+      /usr/bin/hello
+    Config Entries:
+      live.password = xxx
+    Boot Options:
+      nomodeset
+    How to apply this DUD:
+      [✘] during installation: using boot option dud=URL_TO_DUD_FILE
+      [✘] during installation: unpacked on local file system with label 
'OEMDRV'
+      [✘] during installation: renamed as 'driverupdate' in installation 
repository
+      [✘] rebuilding installation media using 'mkmedia --initrd DUD_FILE ...'
+      [✔] rebuilding installation media using 'mkmedia --apply-dud DUD_FILE 
...'
+```
+
+This DUD
+
+- is intended for Agama (Leap 16.0)
+- adds the `hello` package to the initrd
+- updates the `e1000` kernel module
+- sets the root password used in the installation system (note the different 
option compared to the last example)
+- sets boot option `nomodeset`
+
+Since boot options can not be changed during an installation (it is too late), 
the
+DUD can only be applied by modifying the installation medium.
+
+
 
-## Troubleshooting
+## Troubleshooting (YaST-based installations)
 
 Sometimes things just don't work as expected. Here is a detailed guide that 
walks you through the entire update process
 and shows what exactly to expect.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mkdud-1.55/README.md new/mkdud-2.0/README.md
--- old/mkdud-1.55/README.md    2022-09-22 14:27:13.000000000 +0200
+++ new/mkdud-2.0/README.md     2025-08-28 13:40:49.000000000 +0200
@@ -28,172 +28,57 @@
 
 ## Usage
 
-### Updating RPMs
+### Overview
 
-If you need to update packages during installation via driver update, either
-in the installation environment or the final installed system, this script
-helps you to setup such a driver update.
+Driver updates (DUDs) are used to apply fixes to the installation process. In 
particular you can:
 
-There are two ways for this:
+- update kernel modules
+- change files in the initrd of the installation medium
+- change files in the installation system / live root of the installation 
medium
+- change boot options
+- change installer config options
+- provide updated packages to be installed
+- add scripts to be run before and after the installer runs
 
-* (a) The old ('rpm') way: place all rpms into the `install` directory and YaST
-  will run `rpm -U install/*.rpm` at the end of the first installation stage.
+The format of DUDs is described in the [Update Media 
Howto](http://ftp.suse.com/pub/people/hvogel/Update-Media-HOWTO/Update-Media-HOWTO.html).
 
-* (b) Since SLE11/openSUSE 12.1 YaST lets you register a repository 
automatically.
-  The repo priority can be set higher (numerically lower) than the default
-  priority (99) to ensure the driver update packages are preferred.
+`mkdud` provides an easy way to create these DUDs.
 
-Method (b) has the advantage that the old packages are never installed and
-used and conflicts and dependencies are automatically resolved (think of
-different kernel flavors).
-
-This script supports both ways.
-
-Examples:
-
-* (1) update perl-Bootloader with method (a) _and_ (b), repo priority is 50:
-
-<pre>
-  # mkdud --dist sle11 --create foo1.dud perl-Bootloader.rpm
-</pre>
-
-* (2) update perl-Bootloader and yast2-bootloader for both i586 and x86_64, 
using
-  only method (b), repo priority is 90:
-
-<pre>
-  # ls perl-Bootloader/binaries/* yast2-bootloader/binaries/*
-  perl-Bootloader/binaries/perl-Bootloader-0.4.89.30-1.10.i586.rpm
-  yast2-bootloader/binaries/yast2-bootloader-2.17.78-1.1.i586.rpm
-  perl-Bootloader/binaries/perl-Bootloader-0.4.89.30-1.10.x86_64.rpm
-  yast2-bootloader/binaries/yast2-bootloader-2.17.78-1.1.x86_64.rpm
-</pre>
-
-<pre>
-  # mkdud --install repo --prio 90 --dist sle11 --create foo2.dud 
perl-Bootloader/binaries/* yast2-bootloader/binaries/*
-</pre>
-
-
-* (3) replace yast2-bootloader only in the installation system, for i586 and 
x86_64:
-
-<pre>
-  # ls yast2-bootloader/binaries/*
-  yast2-bootloader/binaries/yast2-bootloader-2.17.78-1.1.i586.rpm
-  yast2-bootloader/binaries/yast2-bootloader-2.17.78-1.1.x86_64.rpm
-</pre>
-
-<pre>
-  # mkdud --install instsys --dist sle11 --create foo3.dud 
yast2-bootloader/binaries/*
-</pre>
-
-There's still a catch: if you build the RPM yourself or in the openSUSE
-Build Service and so the RPM is probably signed with a key that is not 
included on the
-install media, you'll get a warning that the package could not be verified
-during installation.
-
-For this, `mkdud` can handle public gpg keys. You just add them on the command
-line. For example:
-
-<pre>
-  # mkdud -c foo.dud -d sle12 bar.rpm bar.pub
-</pre>
-
-will integrate bar.pub into the RPM key database so it is used to verify
-bar.rpm.
-
-Note that these keys are not copied into the target system. They are only
-part of the installation environment.
-
-### Adding and running programs
-
-Sometimes you need to include and run a script to fix things. For example
-
-<pre>
-  # mkdud --dist sle11 --exec bar --create foo4.dud bar
-</pre>
-
-adds 'bar' to the 'install' directory and runs it. Unlike the 'update.pre'
-script it is run just after the dud has been read, even _before_ any dud
-modules are loaded.
-
-You can combine this with rpms:
-
-<pre>
-  # mkdud --install instsys --dist sle11 --exec fix_it --create foo5.dud 
yast2-bootloader/binaries/* fix_it
-</pre>
-
-This replaces yast2-bootloader and also adds and runs the `fix_it` script.
-
-### Conditional DUDs
-
-If a DUD must only be applied to certain machines or only to specific
-service packs, you can add a condition script that is run when the DUD
-config file is parsed during installation. This script must exit with 0 to
-indicate that it's ok to continue with the DUD. If the exit code is nonzero
-a message is printed that the update will not be applied and the update is
-deleted.
-
-`mkdud` can generate scripts automatically that check for sle10 and sle11
-service packs. They are used if you name the script `ServicePackN`. If you
-want to use your own scripts with such a name, specify it e.g. as
-`./ServicePack1` on the command line.
+See [HOWTO](HOWTO.md) for detailed instructions.
 
 ### DUD formats
 
 The DUD will be packaged into an archive and optionally compressed. The
-default is a gzipped cpio archive. For SLE12 and later you can also
-create an rpm.
+default is a gzipped cpio archive. You can also create an RPM or ISO image.
 
-Situation prior to SLE12, openSUSE 13.2:
-
-> Due to a limitation in linuxrc you can't use a compressed DUD when you
-> need to sign it. (The verification in linuxrc will fail.) So, if you need
-> to create a signed DUD, don't compress it (use --format=cpio).
-
-SLE12, openSUSE 13.2, and later versions:
-
->  You can use either a cpio or tar archive and can compress it optionally
->  with either gzip or xz. All formats may be used for signed DUDs.
-
-SLE12-SP1, Leap-42.1 and later versions:
-
-> If you create an RPM (use --format=rpm) you can sign the RPM in the usual 
RPM-way
-> to get a signed DUD.
+If you create an RPM (use --format=rpm) you can sign the RPM in the usual 
RPM-way
+to get a signed DUD.
 
 There is an advantage in using cpio instead of tar or rpm: because the Linux 
kernel
 understands cpio archives, you can just append a DUD to the initrd on the
 boot medium to apply it (literally: 'cat my.dud >> initrd'). No need for a
 'dud' boot option in this case.
 
-It is also possible to create a DUD in ISO9660 format. But note that DUDs in
-*compressed* (gzip or xz) ISO9660 format are currently not suitable to be
-used in the installer's 'dud' boot option.
-
 ### DUD directory structure
 
-Please read section 2.1 [Directory structure] in the Update-Media-HOWTO above 
first.
+Please read section 2.1 [Directory structure] in the
+[Update Media 
Howto](http://ftp.suse.com/pub/people/hvogel/Update-Media-HOWTO/Update-Media-HOWTO.html)
 first.
 
-Normally, `mkdud` ensures a correct directory layout. But sometimes you may
-want to specify a directory prefix yourself.
+The DUD directory layout allows for an optional top-level directory consisting 
of a decimal number.
+The intention is to avoid file collisions between different DUDs.
 
 For example, imagine you want to include your driver update directly into
-the `initrd`. You can do this simply by appending an (unsigned) driver update
+the `initrd`. You can do this simply by appending a DUD
 to the `initrd`. But when someone else tries this again, they will get into
 trouble as the directories are just merged. To avoid this, choose a
 directory prefix that's unlikely to conflict with others using the
 `--prefix` option.
 
-If this sounds a bit complicated just try the `--prefix` option and look at
-the unpacked driver update.
-
 ### Signature
 
 When downloading a driver update the installer will verify the integrity of
 the update by checking the (detached) signature.
 
-Note that for sle11 due to a limitation in the installer you can only sign
-an uncompressed update. sle12/openSUSE 13.2 and later don't have this
-limitation.
-
 ## openSUSE Development
 
 To build, simply run `make`. Install with `make install`.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mkdud-1.55/VERSION new/mkdud-2.0/VERSION
--- old/mkdud-1.55/VERSION      2022-09-22 14:27:13.000000000 +0200
+++ new/mkdud-2.0/VERSION       2025-08-28 13:40:49.000000000 +0200
@@ -1 +1 @@
-1.55
+2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mkdud-1.55/changelog new/mkdud-2.0/changelog
--- old/mkdud-1.55/changelog    2022-09-22 14:27:13.000000000 +0200
+++ new/mkdud-2.0/changelog     2025-08-28 13:40:49.000000000 +0200
@@ -1,3 +1,10 @@
+2025-08-28:    2.0
+       - merge gh#openSUSE/mkdud#42
+       - make mkdud SLE-16 aware (jsc#PED-13262)
+       - update man page
+       - documentation update
+       - adjust package dependencies
+
 2022-09-22:    1.55
        - merge gh#openSUSE/mkdud#41
        - work with both mkisofs and genisoimage
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mkdud-1.55/mkdud new/mkdud-2.0/mkdud
--- old/mkdud-1.55/mkdud        2022-09-22 14:27:13.000000000 +0200
+++ new/mkdud-2.0/mkdud 2025-08-28 13:40:49.000000000 +0200
@@ -125,6 +125,11 @@
 sub repack_as_rpm;
 sub sign_rpm;
 sub create_adddir;
+sub installer_from_dist;
+sub installer_from_config;
+sub get_rpm_scripts;
+sub parse_alternatives;
+sub apply_alternatives;
 
 my %config;
 my $opt_create;
@@ -154,6 +159,8 @@
 my $opt_fix_usr_src = 1;
 my $opt_fix_dist = 1;
 my $opt_fix_adddir = 1;
+my @opt_initrd;
+my $opt_installer;
 
 # global variables
 my $dud;
@@ -216,6 +223,8 @@
   'vendor=s'         => \$opt_vendor,
   'preparer=s'       => \$opt_preparer,
   'application=s'    => \$opt_application,
+  'installer=s'      => \$opt_installer,
+  'initrd=s'         => \@opt_initrd,
   'save-temp'        => \$opt_save_temp,
   'version'          => sub { print "$VERSION\n"; exit 0 },
   'help'             => sub { usage 0 },
@@ -229,10 +238,14 @@
   usage 1 unless /^(instsys|repo|rpm|$)/;
 }
 
+usage 1 if $opt_installer !~ /^(|agama|anaconda|yast)$/i;
+
 usage 1 unless $opt_show xor $opt_create;
 
 usage 2 if $opt_show && @ARGV;
 
+$ENV{PATH} = "/usr/bin:/bin:/usr/sbin:/sbin";
+
 @opt_arch = map { /^i.86$/ ? "i386" : $_ } @opt_arch;
 
 if(open my $f, "$ENV{HOME}/.mkdudrc") {
@@ -286,6 +299,7 @@
 
 if($opt_create) {
   file_type $_ for (@ARGV);
+  file_type $_, 1 for (@opt_initrd);
 
   my $need_dist;
   for (@files) {
@@ -315,16 +329,20 @@
       push @dists, "sles12" if grep { /^caasp[123]\./ } @dists;
       push @dists, "sles15" if grep { /^caasp4\./ } @dists;
       push @dists, "13.2" if grep { $_ eq "leap42.1" } @dists;
-      @d{map { /^sle([sd]?)(\d+)/i ? $1 eq "" ? ("sles$2", "sled$2") : 
"sle\L$1$2" : "\L$_" } @dists} = ();
+      @d{map { /^sle([sd]?)(\d+)/i ? $1 eq "" && $2 <= 15 ? ("sles$2", 
"sled$2") : "sle\L$1$2" : "\L$_" } @dists} = ();
       @dists = sort keys %d;
-      @d{map { /^(\d+)\.(\d+)$/ && $1 >= 15 ? ("leap$1.$2", "sles$1", 
"sled$1") : $_ } @dists} = ();
-      @d{map { /^(\d+)$/ && $1 >= 15 ? ("sles$1", "sled$1") : $_ } @dists} = 
();
+      @d{map { /^(\d+)\.(\d+)$/ && $1 == 15 ? ("leap$1.$2", "sles$1", 
"sled$1") : $_ } @dists} = ();
+      @d{map { /^(\d+)$/ && $1 == 15 ? ("sles$1", "sled$1") : $_ } @dists} = 
();
+      @d{map { /^(\d+)\.(\d+)$/ && $1 >= 16 ? ("leap$1.$2", "sles$1") : $_ } 
@dists} = ();
+      @d{map { /^(\d+)$/ && $1 >= 16 ? ("sle$1") : $_ } @dists} = ();
+      @d{map { /^sle[sd](\d+)$/ && $1 >= 16 ? ("sle$1") : $_ } @dists} = ();
+      for (16 .. 19) { delete $d{"sles$_"}; delete $d{"sled$_"}; }
       @dists = sort keys %d;
       @dists = grep { !(/^(\d+)(\.(\d+))?$/ && $1 >= 15) } @dists;
     }
 
     for (@dists) {
-      if(!/^((leap|kubic|casp|caasp|suse-microos)?\d+\.\d+|tw|sle[sd]\d+)$/) {
+      
if(!/^((leap|kubic|casp|caasp|suse-microos)?\d+\.\d+|tw|sle[sd]\d+|sle1[6-9])$/)
 {
         if(!$opt_fix_dist) {
           print STDERR "***  Note: using unsupported dist \"$_\"\n";
         }
@@ -405,7 +423,7 @@
 
 Verify driver update:
 
-  -s, --show DUD                Verify DUD and print short summary.
+  -s, --show DUD                Verify DUD and print summary.
 
 Create driver update:
 
@@ -418,7 +436,11 @@
   -x, --exec COMMAND            Run command just after the driver update has 
been loaded.
   -i, --install METHODS         Package install method. METHODS is a 
comma-separated list
                                 of: instsys, repo, rpm (default: 
'instsys,repo,rpm').
-      --config KEY=VALUE        Set linuxrc config option KEY to VALUE.
+      --initrd RPM|DIR          Add RPM or DIR to initrd instead of instsys 
(option can be repeated).
+      --installer INSTALLER     Set installation program. Either agama or yast
+                                (default: auto-detected based on dist).
+      --config KEY=VALUE        Set initrd config option KEY to VALUE (option 
can be repeated).
+                                You can set boot options using KEY 'boot'.
       --no-docs                 Don't include package documentation (default).
       --keep-docs               Include package documentation.
       --no-fix-yast             Allow driver update to replace /sbin/yast.
@@ -509,6 +531,8 @@
   my $gpg = "gpg --homedir=$sign_key_dir --yes --output - 2>/dev/null";
   my $gpg_sign;
 
+  my $for_initrd = $_[1];
+
   if(!-e $_[0]) {
     print STDERR "$_[0]: error: no such file or directory\n";
     return;
@@ -517,7 +541,7 @@
   $_ = `file -b -k -L $_[0] 2>/dev/null`;
 
   if(/^RPM/) {
-    my $ft = { type => 'rpm', file => $_[0] };
+    my $ft = { type => ($for_initrd ? 'rpm_initrd' : 'rpm'), file => $_[0] };
 
     my $f = `rpm --nosignature -qp --qf 
'%{NAME}\t%{VERSION}\t%{RELEASE}.%{ARCH}' $_[0] 2>$tmp_err`;
     if($f eq "") {
@@ -529,21 +553,28 @@
       exit 1;
     }
 
-    # check if rpm contains a driver update
-    # (a directory /linux/suse/foo-bar or /<NUMBER>/linux/suse/foo-bar exists)
-    for my $line (`rpm --nosignature -qp -lv $_[0] 2>$tmp_err`) {
-      my @field = split ' ', $line;
-      next unless $field[0] =~ /^d/;
-      if($field[8] =~ m#/(\d+/)?linux/suse/\S+-\S+$#) {
-        $dud = 'cpio.rpm';
-        last;
+    my $scripts = get_rpm_scripts $_[0];
+    my $links = parse_alternatives $scripts->{postin};
+
+    $ft->{alternatives} = $links if $links;
+
+    if(!$for_initrd) {
+      # check if rpm contains a driver update
+      # (a directory /linux/suse/foo-bar or /<NUMBER>/linux/suse/foo-bar 
exists)
+      for my $line (`rpm --nosignature -qp -lv $_[0] 2>$tmp_err`) {
+        my @field = split ' ', $line;
+        next unless $field[0] =~ /^d/;
+        if($field[8] =~ m#/(\d+/)?linux/suse/\S+-\S+$#) {
+          $dud = 'cpio.rpm';
+          last;
+        }
       }
-    }
 
-    # Check if yast base package is to be replaced and remember its version:
-    if($f =~ /^yast2\t(.+)\t/) {
-      $yast_version = $1;
-      # print STDERR "yast version: $yast_version\n";
+      # Check if yast base package is to be replaced and remember its version:
+      if($f =~ /^yast2\t(.+)\t/) {
+        $yast_version = $1;
+        # print STDERR "yast version: $yast_version\n";
+      }
     }
 
     ($ft->{canonical_name} = $f) =~ s/\t/-/g;
@@ -573,7 +604,7 @@
       return;
     }
   }
-  elsif($_[0] =~ m#${kext_regexp}$#) {
+  elsif(!$for_initrd && $_[0] =~ m#${kext_regexp}$#) {
     my $ft = { file => $_[0] };
 
     my $ar = get_file_arch $_[0];
@@ -590,7 +621,7 @@
 
     return;
   }
-  elsif(/^ELF/) {
+  elsif(!$for_initrd && /^ELF/) {
     @i = split /\s*,\s*/;
 
     my $ft = { file => $_[0] };
@@ -609,17 +640,17 @@
 
     return;
   }
-  elsif(/ (cpio|tar) archive/) {
+  elsif(!$for_initrd && / (cpio|tar) archive/) {
     $dud = $1;
   }
-  elsif(/^(gzip|XZ) compressed data/) {
+  elsif(!$for_initrd && /^(gzip|XZ) compressed data/) {
     my $cmd = "\L$1";
     my $f = $cmd ne 'gzip' ? $cmd : 'gz';
     my $z = `$cmd -dc $_[0] | file -b -`;
     $dud = "$1.$f" if $z =~ / (cpio|tar) archive/;
     $dud = "iso.$f" if $z =~ / ISO 9660 CD-ROM /;
   }
-  elsif(/ ISO 9660 CD-ROM /) {
+  elsif(!$for_initrd && / ISO 9660 CD-ROM /) {
     if(!$>) {
       system "mount -oro,loop $_[0] $tmp_mnt";
       file_type "$tmp_mnt", 1;
@@ -631,26 +662,28 @@
     $dud = 'dummy';
   }
   elsif(-d $_[0]) {
-    if($_[0] =~ /(^|\/)y2update\/*$/) {
-      push @files, { type => 'y2update', file => $_[0] };
+    if(!$for_initrd) {
+      if($_[0] =~ /(^|\/)y2update\/*$/) {
+        push @files, { type => 'y2update', file => $_[0] };
 
-      return;
-    }
+        return;
+      }
 
-    if(-f "$_[0]/driverupdate") {
-      $dud = 'dummy';
-      file_type "$_[0]/driverupdate";
-    }
+      if(-f "$_[0]/driverupdate") {
+        $dud = 'dummy';
+        file_type "$_[0]/driverupdate";
+      }
 
-    if(-d "$_[0]/linux/suse") {
-      $dud = 'dir';
-    }
-    elsif(grep { m#/\d+/linux/suse$# } glob "$_[0]/[0-9]*/linux/suse") {
-      $dud = 'dir';
+      if(-d "$_[0]/linux/suse") {
+        $dud = 'dir';
+      }
+      elsif(grep { m#/\d+/linux/suse$# } glob "$_[0]/[0-9]*/linux/suse") {
+        $dud = 'dir';
+      }
     }
 
     if(!$dud) {
-      my $ft = { type => 'instsys', file => $_[0] };
+      my $ft = { type => ($for_initrd ? 'initrd' : 'instsys'), file => $_[0] };
 
       File::Find::find(sub {
         if(-f $_) {
@@ -668,17 +701,17 @@
       return;
     }
   }
-  elsif(-f $_[0] && $_[0] =~ 
m#(^|/)(update\.(pre|post|post2)|module\.(order|config))$#) {
+  elsif(!$for_initrd && -f $_[0] && $_[0] =~ 
m#(^|/)(update\.(pre|post|post2)|module\.(order|config))$#) {
     push @files, { type => $2, file => $_[0] };
 
     return;
   }
-  elsif(-f $_[0] && $_[0] =~ m#(^|/)(.*\.(ycp|ybc|rb))$#) {
+  elsif(!$for_initrd && -f $_[0] && $_[0] =~ m#(^|/)(.*\.(ycp|ybc|rb))$#) {
     push @files, { type => $3, file => $_[0] };
 
     return;
   }
-  elsif(-f $_[0] && -s _ && -T _) {
+  elsif(!$for_initrd && -f $_[0] && -s _ && -T _) {
     open my $f, $_[0];
     local $/;  # complete file
     my $l = <$f>;
@@ -696,7 +729,7 @@
       return;
     }
   }
-  else {
+  elsif(!$for_initrd) {
     for (`gpg --homedir=$sign_key_dir --verify $_[0] 2>&1`) {
       chomp;
       $gpg_sign = $1, last if /^gpg: Signature made\s*(.*)$/;
@@ -886,6 +919,8 @@
   chomp($id = `uuidgen 2>/dev/null`);
   $id = sprintf("%06x%06x%04x", rand(1<<24), rand(1<<24), rand(1<<16)) unless 
$id;
 
+  my $installer = installer_from_dist($dist);
+
   for my $arch (sort keys %arch) {
     my $base = "$tmp_dud/linux/suse/$arch-$dist";
 
@@ -906,6 +941,8 @@
       print $cfg "Exec:\t\t/update/*/install/mkdud.$id.if $x\n";
     }
 
+    print $cfg "UpdateInstaller:\t$installer\n";
+
     my $has_update_name = @opt_name;
 
     # special case: allow otherwise empty update if a name was given explicitly
@@ -933,6 +970,12 @@
         system "cp -a '$_->{file}'/* $base/inst-sys";
       }
 
+      if($_->{type} eq 'initrd') {
+        $dud_ok = 1;
+        mkdir "$base/initrd", 0755;
+        system "cp -a '$_->{file}'/* $base/initrd";
+      }
+
       if($_->{type} eq 'rpm') {
         print $cfg "UpdateName:\t$_->{canonical_name}\t$_->{date}\n" if 
!@opt_name;
         $has_update_name = 1;
@@ -949,12 +992,29 @@
           $dud_ok = 1;
           mkdir "$base/inst-sys", 0755;
           open my $f, ">>", "$base/inst-sys/.update.$id";
-          print $f "$_->{canonical_name}\n";
+          print $f "package: $_->{canonical_name}\n";
           close $f;
           system "rpm2cpio $_->{file} | ( cd $base/inst-sys ; cpio --quiet 
--sparse -dimu --no-absolute-filenames )";
+
+          # for agama, go via /etc/alternatives
+          # for yast, link directly
+          my $direct_links = $installer eq 'yast' ? 1 : 0;
+          apply_alternatives "$base/inst-sys", $_->{alternatives}, 
$direct_links;
         }
       }
 
+      if($_->{type} eq 'rpm_initrd') {
+        $dud_ok = 1;
+        mkdir "$base/initrd", 0755;
+        open my $f, ">>", "$base/initrd/.update.initrd.$id";
+        print $f "package: $_->{canonical_name}\n";
+        close $f;
+        system "rpm2cpio $_->{file} | ( cd $base/initrd ; cpio --quiet 
--sparse -dimu --no-absolute-filenames )";
+
+        # link directly, not going via /etc/alternatives
+        apply_alternatives "$base/initrd", $_->{alternatives}, 1;
+      }
+
       if($_->{type} eq 'bin' || $_->{type} eq 'lib') {
         $dud_ok = 1;
         mkdir "$base/install", 0755;
@@ -1017,7 +1077,7 @@
       system "chmod 755 `find $base/inst-sys -type d`";
 
       if($opt_no_docs) {
-        system "rm -rf $base/inst-sys/usr/share/{doc,info,man}";
+        system "rm -rf $base/inst-sys/usr/share/{doc,info,licenses,man}";
         rmdir "$base/inst-sys/usr/share";
         rmdir "$base/inst-sys/usr";
       }
@@ -1027,6 +1087,20 @@
       }
     }
 
+    if(-d "$base/initrd" ) {
+      system "chmod 755 `find $base/initrd -type d`";
+
+      if($opt_no_docs) {
+        system "rm -rf $base/initrd/usr/share/{doc,info,licenses,man}";
+        rmdir "$base/initrd/usr/share";
+        rmdir "$base/initrd/usr";
+      }
+
+      if(glob("$base/initrd/usr/lib/rpm/gnupg/keys/*.asc")) {
+        $has_pubkeys = 1;
+      }
+    }
+
     if($opt_fix_yast) {
       if(lstat "$base/inst-sys/sbin/yast") {
         if(vercmp($yast_version, $REPLACEABLE_YAST) < 0 ) {
@@ -1177,7 +1251,7 @@
       }
     }
 
-    if(@rpms && $opt_install{repo}) {
+    if(@rpms && $opt_install{repo} && $installer =~ /^(yast)$/i) {
       $dud_ok = 1;
       mkdir "$base/install", 0755;
 
@@ -1253,7 +1327,7 @@
       push @{$scripts->{'update.post2'}}, $c;
     }
 
-    if($has_pubkeys) {
+    if($has_pubkeys && $installer eq 'yast') {
       my $c = <<'= = = = = = = =';
 #! /bin/bash
 
@@ -1417,7 +1491,7 @@
   }
 
   $opt_application = $id if !defined $opt_application;
-  $opt_volume = "DriverUpdate" if !defined $opt_volume;
+  $opt_volume = "OEMDRV" if !defined $opt_volume;
   $opt_vendor = "mkdud $VERSION" if !defined $opt_vendor;
   $opt_preparer = "mkdud $VERSION" if !defined $opt_preparer;
 }
@@ -1678,13 +1752,16 @@
 
   my %p1;
   for (@$l) {
-    
if(/^(\S+)-(sle([sd])(\d+)|(leap|kubic|casp|caasp|suse-microos)?(\d+\.\d+)|tw)$/)
 {
+    
if(/^(\S+)-(sle([sd]?)(\d+)|(leap|kubic|casp|caasp|suse-microos)?(\d+\.\d+)|tw)$/)
 {
       if($3 eq 's') {
         push @{$p1{"SUSE Linux Enterprise Server $4"}}, $1;
       }
       elsif($3 eq 'd') {
         push @{$p1{"SUSE Linux Enterprise Desktop $4"}}, $1;
       }
+      elsif($4 ne '') {
+        push @{$p1{"SUSE Linux Enterprise $4"}}, $1;
+      }
       elsif($5 eq 'leap') {
         push @{$p1{"openSUSE Leap $6"}}, $1;
       }
@@ -1758,9 +1835,13 @@
   my (@i, %i);
   my $id;
 
+  my $installer_names = { agama => "Agama", anaconda => "Anaconda", yast => 
"YaST" };
+
   # ----------------------------
   # read config file
 
+  my $installer = "yast";
+
   my %sect;
   open my $f, "$dir/dud.config";
   while(<$f>) {
@@ -1773,9 +1854,15 @@
         $id = $val;
         $sect{id} = "      $val\n";
       }
+      elsif("\L$key" eq 'updateinstaller') {
+        $installer = installer_from_config $val;
+      }
       elsif("\L$key" eq 'updatename') {
         $sect{name} .= "      $val\n";
       }
+      elsif("\L$key" eq 'boot') {
+        $sect{boot} .= "      $val\n";
+      }
       elsif("\L$key" eq 'exec') {
         my $ok = 0;
         if($val =~ m#/update/\*/install/(mkdud\..*\.sh)$#) {
@@ -1804,6 +1891,8 @@
   }
   close $f;
 
+  $sect{installer} = "      $installer_names->{$installer}\n";
+
   # ----------------------------
   # update.* scripts
 
@@ -1913,10 +2002,13 @@
 
     $i{instsys} = 1 if -f "$dir/inst-sys/.update.$id";
 
+    delete $i{rpm} if $installer eq "agama";
+    $i{repo} = 1 if $installer eq "agama";
+
     my $l = "- install methods: " . join(", ", sort keys %i);
     $l .= " (repo priority $prio)" if defined $prio;
 
-    $sect{rpms} .= "      $l\n";
+    $sect{rpms} = "      $l\n" . $sect{rpms};
   }
 
 
@@ -1925,7 +2017,7 @@
 
   if(-d "$dir/y2update") {
     my $max_files = 10;
-  
+
     chomp(my @f = `cd $dir/y2update; find . -type f`);
     @f = map { s#^\./##; $_ } sort @f;
     if(@f > $max_files + 1) {
@@ -1943,18 +2035,17 @@
 
   if(-d "$dir/inst-sys") {
     my $max_files = 10;
-  
+
     chomp(my @f = `cd $dir/inst-sys; find . -type f`);
     @f = map { s#^\.##; $_ } sort @f;
     @f = grep { $_ ne "/.update.$id" } @f;
     @f = grep { ! m#^/usr/lib/rpm/gnupg/keys/[^/]+.asc$# } @f;
 
-    if(-e "$dir/inst-sys/sbin/yast") {
-      $sect{instsys} .= "      ***  Warning: replaces /sbin/yast.  ***\n";
-    }
-
-    if(-e "$dir/inst-sys/usr/src/packages") {
-      $sect{instsys} .= "      ***  Warning: includes /usr/src/packages.  
***\n";
+    if(open my $fd, "$dir/inst-sys/.update.$id") {
+      my @l = <$fd>;
+      close $fd;
+      chomp @l;
+      $sect{instsys} .= "      - $_.rpm\n" for @l;
     }
 
     if(@f > $max_files + 1) {
@@ -1968,9 +2059,37 @@
   }
 
   # ----------------------------
+  # initrd
+
+  if(-d "$dir/initrd") {
+    my $max_files = 10;
+
+    chomp(my @f = `cd $dir/initrd; find . -type f`);
+    @f = map { s#^\.##; $_ } sort @f;
+    @f = grep { $_ ne "/.update.initrd.$id" } @f;
+    @f = grep { ! m#^/usr/lib/rpm/gnupg/keys/[^/]+.asc$# } @f;
+
+    if(open my $fd, "$dir/initrd/.update.initrd.$id") {
+      my @l = <$fd>;
+      close $fd;
+      chomp @l;
+      $sect{initrd} .= "      - $_.rpm\n" for @l;
+    }
+
+    if(@f > $max_files + 1) {
+      $sect{initrd} .= "      $_\n" for (@f[0 .. $max_files - 1]);
+      my $x = @f - $max_files;
+      $sect{initrd} .= "      ... ($x more files)\n";
+    }
+    else {
+      $sect{initrd} .= "      $_\n" for (@f);
+    }
+  }
+
+  # ----------------------------
   # public rpm keys
 
-  for (glob("$dir/inst-sys/usr/lib/rpm/gnupg/keys/*")) {
+  for (glob("$dir/inst-sys/usr/lib/rpm/gnupg/keys/* 
$dir/initrd/usr/lib/rpm/gnupg/keys/*")) {
     s#^.*/##;
     next unless /\.asc$/;
     $sect{pubkeys} .= "      $_\n";
@@ -1989,6 +2108,23 @@
   }
 
   # ----------------------------
+  # howto
+
+  my @is_ok = ( "✔", "✔", "✔", "✔", "✔" );
+
+  $is_ok[0] = $is_ok[3] = "✘" if $sect{initrd} || $sect{boot} || 
($sect{config} && $installer ne "yast");
+  $is_ok[1] = $is_ok[2] = "✘" if $sect{initrd} || $sect{boot} || $installer ne 
"yast";
+
+  my $opt = "dud";
+  $opt = "inst.dud" if $installer eq "agama";
+
+  $sect{howto} .= "      [$is_ok[0]] during installation: using boot option 
$opt=URL_TO_DUD_FILE\n";
+  $sect{howto} .= "      [$is_ok[1]] during installation: unpacked on local 
file system with label 'OEMDRV'\n";
+  $sect{howto} .= "      [$is_ok[2]] during installation: renamed as 
'driverupdate' in installation repository\n";
+  $sect{howto} .= "      [$is_ok[3]] rebuilding installation media using 
'mkmedia --initrd DUD_FILE ...'\n";
+  $sect{howto} .= "      [$is_ok[4]] rebuilding installation media using 
'mkmedia --apply-dud DUD_FILE ...'\n";
+
+  # ----------------------------
   # generate summary
 
   my $log;
@@ -2005,6 +2141,10 @@
     $log .= "    ID:\n$sect{id}";
   }
 
+  if($sect{installer}) {
+    $log .= "    Installer:\n$sect{installer}";
+  }
+
   if($sect{rpms}) {
     $log .= "    Packages:\n$sect{rpms}";
   }
@@ -2029,6 +2169,10 @@
     $log .= "    Installation System:\n$sect{instsys}";
   }
 
+  if($sect{initrd}) {
+    $log .= "    Initrd:\n$sect{initrd}";
+  }
+
   if($sect{other}) {
     $log .= "    Other Files:\n$sect{other}";
   }
@@ -2041,6 +2185,14 @@
     $log .= "    Config Entries:\n$sect{config}";
   }
 
+  if($sect{boot}) {
+    $log .= "    Boot Options:\n$sect{boot}";
+  }
+
+  if($sect{howto}) {
+    $log .= "    How to apply this DUD:\n$sect{howto}";
+  }
+
   return $log;
 }
 
@@ -2436,3 +2588,128 @@
 
   chmod 0755, $file;
 }
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get installer name for dist, taking mkdud options into account.
+#
+# installer_from_dist(dist)
+#
+sub installer_from_dist
+{
+  my $dist = $_[0];
+
+  return "\L$opt_installer" if $opt_installer =~ /^(agama|anaconda|yast)$/i;
+
+  my $installer = "yast";
+
+  $installer = "agama" if $dist =~ /^(sle[sd]?|leap)(\d+)$/ && $2 >= 16;
+
+  return $installer;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Get installer name from dud.config setting.
+#
+# installer_from_config(config_val)
+#
+sub installer_from_config
+{
+  my $val = $_[0];
+
+  my $installer = "yast";
+
+  $installer = "\L$val" if $val =~ /^(agama|anaconda|yast)$/i;
+
+  return $installer;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Read scripts from RPM archive.
+#
+# Return hash with scripts;
+#
+# get_rpm_scripts(file)
+#
+sub get_rpm_scripts
+{
+  my $file = $_[0];
+  my $scripts = {};
+
+  for my $script (`rpm --nosignature -qp --qf 
'%|PREIN?{PREIN\n}:{}|%|POSTIN?{POSTIN\n}:{}|%|PREUN?{PREUN\n}:{}|%|POSTUN?{POSTUN\n}:{}|'
 $file 2>/dev/null`) {
+    chomp $script;
+    $script = "\L$script";
+    $scripts->{$script} = `rpm --nosignature -qp --qf '%{\U$script\E}' $file 
2>/dev/null`;
+    # join continuation lines
+    $scripts->{$script} =~ s/\\\n//g;
+  }
+
+  return $scripts;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Parse postin script for update-alternative calls.
+#
+# Return hash with symlinks or undef if update-alternative was not used.
+#
+# parse_alternatives(script)
+#
+sub parse_alternatives
+{
+  my $script= $_[0];
+
+  my $update_links;
+
+  for (split /\n/, $script) {
+    next unless /update-alternatives\s/;
+    while(/--(?:install|slave)\s+(\S+)\s+(\S+)\s+(\S+)/g) {
+      # link: general name (full path)
+      # name: symlink name in /etc/alternatives/
+      # path: full path /etc/alternatives/$name links to
+      my $link = $1;
+      my $name = $2;
+      my $path = $3;
+      $link =~ s/^(["'])(.*)\1$/$2/;
+      $name =~ s/^(["'])(.*)\1$/$2/;
+      $path =~ s/^(["'])(.*)\1$/$2/;
+      $update_links->{$link} = { name => $name, path => $path };
+    }
+  }
+
+  return $update_links;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub apply_alternatives
+{
+  my $dir = $_[0];
+  my $alternatives = $_[1];
+  my $direct_links = $_[2];
+
+  for my $alt (sort keys %$alternatives) {
+    my $etc_alt = "/etc/alternatives";
+    File::Path::mkpath("$dir/$etc_alt") if !$direct_links;
+    my $alt_dir = $alt;
+    $alt_dir =~ s#[^/]*$##;
+    my $d = "$dir/$alt_dir";
+    File::Path::mkpath($d);
+    if(-d $d) {
+      unlink "$dir/$alt";
+      if($direct_links) {
+        symlink $alternatives->{$alt}{path}, "$dir/$alt";
+      }
+      else {
+        symlink "$etc_alt/$alternatives->{$alt}{name}", "$dir/$alt";
+        unlink "$dir/$etc_alt/$alternatives->{$alt}{name}";
+        symlink $alternatives->{$alt}{path}, 
"$dir/$etc_alt/$alternatives->{$alt}{name}";
+      }
+    }
+    else {
+      die "$d: failed to create directory\n";
+    }
+  }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mkdud-1.55/mkdud_man.adoc 
new/mkdud-2.0/mkdud_man.adoc
--- old/mkdud-1.55/mkdud_man.adoc       2022-09-22 14:27:13.000000000 +0200
+++ new/mkdud-2.0/mkdud_man.adoc        2025-08-28 13:40:49.000000000 +0200
@@ -34,7 +34,7 @@
 === Verify Driver Update
 
 *-s, --show*=_DUD_::
-Verify _DUD_ and print short summary. _DUD_ may be a file or directory or an 
ISO image.
+Verify _DUD_ and print a summary. _DUD_ may be a file or directory or an ISO 
image.
 
 
 === Create Driver Update
@@ -51,12 +51,15 @@
 
 *-d, --dist*=_DIST_::
 Specify the product the DUD is for. Possible values for _DIST_ include:
-`13.2`, `sle15`, `leap15.1`, `caasp1.0`, 'micro5.0', `tw` standing for
-openSUSE 13.2, SLE 15, Leap 15.1, CaaSP 1.0, SLE Micro 5.0, Tumbleweed, 
respectively. +
-*Note 1*: `sle15` is a short hand for specifying both `sles15` and `sled15`. +
-*Note 2*: There are no separate names for service packs.
+`13.2`, `sle15`, `leap16.1`, `caasp1.0`, 'micro5.0', `tw` standing for
+openSUSE 13.2, SLE 15, Leap 16.1, CaaSP 1.0, SLE Micro 5.0, Tumbleweed, 
respectively. +
+*Note 1*: Since SLE 16 / Leap 16.0 Agama replaces YaST as installer. +
+See *Agama vs. YaST* below for more details. +
+*Note 2*: `sle15` is a short hand for specifying both `sles15` and `sled15`. +
+*Note 3*: There are no separate names for service packs.
 So `sles15-sp1` is the same as `sles15`. But see *--condition*
 below for a way to target specific service packs. +
+*Note 4*: `sle16` is used for SLE 16. There are no service packs for the SLE 
16 product line. +
 See *Distribution (Product) Names* below for more details. +
 Option can be repeated to specify several distribution targets.
 
@@ -82,22 +85,39 @@
 *-x, --exec*=_COMMAND_::
 Run _COMMAND_ right after the driver update has been loaded.
 Option can be repeated to specify several commands. +
-*Note*: The commands are run just before kernel modules
+*Note 1*: This option only works for YaST-based installations. +
+*Note 2*: The commands are run just before kernel modules
 are updated.
 
 *-i, --install*=_METHODS_::
 Package install method. _METHODS_ is a comma-separated list
-of: `instsys`, `repo`, `rpm` (default: `instsys,repo,rpm`). +
-- `instsys`: unpack packages in installation system +
+of: `instsys`, `repo`, `rpm` (default (Agama): `instsys,repo`, default (YaST): 
`instsys,repo,rpm`). +
+- `instsys`: unpack packages in installation system / live root +
 - `repo`: create repo with all packages and register with
-  yast before starting installation; repo will be removed
+  Agama or YaST before starting installation; repo will be removed
   after the installation +
 - `rpm`: install packages at the end of the installation
-  using rpm (that is, not via repo & zypper) +
+  using rpm (that is, not via repo & zypper) - this method is
+  only available for YaST +
+
+*--initrd*=_RPM|DIR_::
+Add RPM or content of DIR to initrd instead of instsys. +
+Option can be repeated to add several packages or directories. +
+This requires applying the driver update with *mkmedia* to work. +
+See *How to apply driver updates* below for details.
+
+*--installer*=_INSTALLER_::
+Set installation program. Either agama or yast (default: auto-detected based 
on dist). +
+It is usually not necessary to use this option. There are minor differences in 
handling driver updates
+between Agama and YaST, though. mkdud takes these into account.
 
 *--config*=_KEY_=_VALUE_::
-Set linuxrc config option _KEY_ to _VALUE_. The options are changed
+Set initrd config option _KEY_ to _VALUE_. The options are changed
 just after the driver update has been loaded. +
+You can set boot options using KEY 'boot'.
+Setting boot options accepts the same semantics as *mkmedia* (see *mkmedia* 
docs); in particular, prefixing a
+boot option with '-' removes it. +
+See *How to apply driver updates* below for limitations. +
 Option can be repeated to set several options.
 
 *--no-docs*::
@@ -130,7 +150,9 @@
 *--format*=_FORMAT_::
 Specify archive format for DUD. _FORMAT_=`((cpio|tar|iso)[.(gz|xz)])|rpm`. +
 Default _FORMAT_ is `cpio.gz` (gzip compressed cpio archive). +
-*Note*: please check `README` before changing the default.
+Using _FORMAT_ 'iso' produces an ISO image with label 'OEMDRV' -
+see *How to apply driver updates* below for more information. +
+*Note*: please check `README.md` before changing the default.
 
 *--prefix*=_NUM_::
 First directory prefix of driver update. +
@@ -248,6 +270,7 @@
 you must configure the build service access via `$HOME/.oscrc` for this to 
work.
 --
 
+
 == Distribution (Product) Names:
 
 The *--dist* option accepts these values (case-insensitive; X, Y: decimal 
numbers):
@@ -259,6 +282,7 @@
 - sleX (e.g. sle15) = SUSE Linux Enterprise (Server + Desktop) X
 - slesX (e.g. sles15) = SUSE Linux Enterprise Server X
 - sledX (e.g. sled15) = SUSE Linux Enterprise Desktop X - but see notes below
+- sle16, sles16 = SUSE Linux Enterprise 16
 - caaspX.Y (e.g. caasp1.0) = SUSE Container as a Service Platform X.Y - see 
notes below
 - microX.Y (e.g. micro5.0) = SUSE Linux Enterprise Micro X.Y
 
@@ -304,6 +328,20 @@
 You can specify several *--condition* options. They must all be fulfilled 
(logical *and*).
 
 
+== Agama vs. YaST
+
+Starting with SLE 16 and Leap 16.0, the installer changes from YaST to Agama. 
With this, the installation
+system setup changes substantially and there are a few differences in driver 
update handling.
+
+With Agama:
+
+- dracut replaces linuxrc for initial setup steps in the initrd; this results 
in different boot and config options
+- the *--install=rpm* package install method is not available; all package 
updates intended
+for the target system are done by creating a software repository with all 
packages
+- there are no update.pre or update.post scripts
+- the *--exec* option is not available
+
+
 == Consistency Checks
 
 It is possible to create driver updates that will predictably not work
@@ -337,6 +375,40 @@
 includes an update for this script if it detects a need for it.
 
 
+== How to apply driver updates
+
+There are several ways to apply driver updates:
+
+1. During installation
+
+- using boot option *inst.dud=URL_TO_DUD_FILE* (Agama) resp. 
*dud=URL_TO_DUD_FILE* (YaST)
+- unpack the driver update to a local file system with label *OEMDRV* (YaST)
+- rename the driver update to *driverupdate* and place it into the root of the 
installation repository (at the
+same level where the *repodata* directory is) (YaST)
+
+2. By preparing patched installation media
+
+- using *mkmedia --create new.iso --initrd DUD_FILE orig.iso*
+- using *mkmedia --create new.iso --apply-dud DUD_FILE orig.iso*
+
+The difference between *--apply-dud* and *--initrd* is that *--apply-dud* 
applies the driver update directly to the
+installation medium while *--initrd* only adds the driver update to the initrd 
where it will be found and applied at
+installation time (equivalent to using the *inst.dud* or *dud* boot options).
+
+Only with *--apply-dud* you can apply changes to the initrd or boot options.
+
+*mkdud --show DUD_FILE* tells you which ways are available for a specific 
driver update.
+
+Using *mkdud --format=iso ...* produces an ISO9660 file system with label 
*OEMDRV* - ready to be used in the OEMDRV method
+described above (no unpacking needed).
+
+*Note*: If you have package updates for the live root file system (using 
*--install=instsys*) the updated packages
+are added to the installation system / live root - but rpm scripts are not run 
and the live root rpm database is not updated.
+
+*Hint*: If it simplifies your workflow, combine several driver updates into a 
single update; e.g.: +
+*mkdud --create foo_all.dud foo1.dud foo2.dud foo3.dud ...*
+
+
 == Examples
 
 ----
@@ -377,4 +449,5 @@
 - more documentation: `/usr/share/doc/packages/mkdud` +
 - mkdud web site: https://github.com/openSUSE/mkdud +
 - Update Media HOWTO: 
http://ftp.suse.com/pub/people/hvogel/Update-Media-HOWTO/index.html
+- mkmedia / mksusecd web site: https://github.com/openSUSE/mksusecd
 - openSUSE Build Service: https://build.opensuse.org
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mkdud-1.55/obs/mkdud.spec 
new/mkdud-2.0/obs/mkdud.spec
--- old/mkdud-1.55/obs/mkdud.spec       2022-09-22 14:27:13.000000000 +0200
+++ new/mkdud-2.0/obs/mkdud.spec        2025-08-28 13:40:49.000000000 +0200
@@ -17,7 +17,6 @@
 
 
 Name:           mkdud
-BuildRequires:  xz
 %if 0%?suse_version >= 1500 || 0%?sle_version >= 120400
 BuildRequires:  rubygem(asciidoctor)
 %else
@@ -26,7 +25,27 @@
 BuildRequires:  libxslt-tools
 %endif
 %endif
+%if %suse_version >= 1500
+Requires:       mkisofs
+%else
+Requires:       genisoimage
+%endif
+Requires:       binutils
+Requires:       coreutils
+Requires:       cpio
+Requires:       file
+Requires:       findutils
 Requires:       gpg2
+Requires:       grep
+Requires:       gzip
+Requires:       kmod
+Requires:       osc
+Requires:       rpm
+Requires:       rpm-build
+Requires:       tar
+Requires:       util-linux
+Requires:       xz
+Requires:       zstd
 Summary:        Create driver update from rpms
 License:        GPL-3.0-or-later
 Group:          Hardware/Other

Reply via email to