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