summaryrefslogtreecommitdiffstats
path: root/rules.d
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rules.d/50-udev-default.rules.in133
-rw-r--r--rules.d/60-autosuspend.rules22
-rw-r--r--rules.d/60-block.rules13
-rw-r--r--rules.d/60-cdrom_id.rules29
-rw-r--r--rules.d/60-drm.rules8
-rw-r--r--rules.d/60-evdev.rules30
-rw-r--r--rules.d/60-fido-id.rules14
-rw-r--r--rules.d/60-infiniband.rules12
-rw-r--r--rules.d/60-input-id.rules8
-rw-r--r--rules.d/60-persistent-alsa.rules14
-rw-r--r--rules.d/60-persistent-input.rules42
-rw-r--r--rules.d/60-persistent-storage-tape.rules36
-rw-r--r--rules.d/60-persistent-storage.rules149
-rw-r--r--rules.d/60-persistent-v4l.rules20
-rw-r--r--rules.d/60-sensor.rules34
-rw-r--r--rules.d/60-serial.rules26
-rw-r--r--rules.d/64-btrfs.rules.in17
-rw-r--r--rules.d/70-camera.rules9
-rw-r--r--rules.d/70-joystick.rules12
-rw-r--r--rules.d/70-memory.rules8
-rw-r--r--rules.d/70-mouse.rules18
-rw-r--r--rules.d/70-power-switch.rules15
-rw-r--r--rules.d/70-touchpad.rules13
-rw-r--r--rules.d/70-uaccess.rules.in100
-rw-r--r--rules.d/71-seat.rules.in81
-rw-r--r--rules.d/73-seat-late.rules.in20
-rw-r--r--rules.d/75-net-description.rules14
-rw-r--r--rules.d/75-probe_mtd.rules7
-rw-r--r--rules.d/78-sound-card.rules96
-rw-r--r--rules.d/80-drivers.rules13
-rw-r--r--rules.d/80-net-setup-link.rules13
-rw-r--r--rules.d/81-net-dhcp.rules14
-rw-r--r--rules.d/90-vconsole.rules.in12
-rw-r--r--rules.d/99-systemd.rules.in88
-rw-r--r--rules.d/README8
-rw-r--r--rules.d/meson.build80
36 files changed, 1228 insertions, 0 deletions
diff --git a/rules.d/50-udev-default.rules.in b/rules.d/50-udev-default.rules.in
new file mode 100644
index 0000000..7ff6225
--- /dev/null
+++ b/rules.d/50-udev-default.rules.in
@@ -0,0 +1,133 @@
+# do not edit this file, it will be overwritten on update
+
+# run a command on remove events
+ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}"
+ACTION=="remove", GOTO="default_end"
+
+# The md driver increments diskseq *after* emitting 'change' uevent.
+# Drop the line below if it is fixed on the kernel side.
+SUBSYSTEM=="block", KERNEL=="md*", ENV{ID_IGNORE_DISKSEQ}="1"
+
+SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-ports/$attr{name}"
+
+# select "system RTC" or just use the first one
+SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc"
+SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100"
+
+SUBSYSTEM=="hidraw", IMPORT{builtin}="hwdb"
+
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
+ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}"
+
+# Before c43ff248f94266cfc93e300a2d3d163ed805e55b, the following line in
+# 60-drm.rules also sets ID_PATH for all pci, usb, and platform devices:
+####
+# ACTION!="remove", SUBSYSTEM=="drm", SUBSYSTEMS=="pci|usb|platform", IMPORT{builtin}="path_id"
+####
+# Unfortunately, some existing rules already rely on the unexpected behavior.
+# To keep the backward compatibility, let's set ID_PATH for them.
+SUBSYSTEM=="pci|usb|platform", IMPORT{builtin}="path_id"
+
+ACTION!="add", GOTO="default_end"
+
+SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666"
+SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666"
+SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="tty", KERNEL=="sclp_line[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="tty", KERNEL=="ttysclp[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="tty", KERNEL=="3270/tty[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty"
+KERNEL=="tty[A-Z]*[0-9]|ttymxc[0-9]*|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout"
+
+SUBSYSTEM=="mem", KERNEL=="mem|kmem|port", GROUP="kmem", MODE="0640"
+
+SUBSYSTEM=="input", GROUP="input"
+SUBSYSTEM=="input", KERNEL=="js[0-9]*", MODE="0664"
+
+SUBSYSTEM=="video4linux", GROUP="video"
+SUBSYSTEM=="graphics", GROUP="video"
+SUBSYSTEM=="drm", KERNEL!="renderD*", GROUP="video"
+SUBSYSTEM=="dvb", GROUP="video"
+SUBSYSTEM=="media", GROUP="video"
+SUBSYSTEM=="cec", GROUP="video"
+
+SUBSYSTEM=="drm", KERNEL=="renderD*", GROUP="render", MODE="{{GROUP_RENDER_MODE}}"
+SUBSYSTEM=="kfd", GROUP="render", MODE="{{GROUP_RENDER_MODE}}"
+
+SUBSYSTEM=="misc", KERNEL=="sgx_enclave", GROUP="sgx", MODE="0660"
+SUBSYSTEM=="misc", KERNEL=="sgx_vepc", GROUP="sgx", MODE="0660"
+
+# When using static_node= with non-default permissions, also update
+# tmpfiles.d/static-nodes-permissions.conf.in to keep permissions synchronized.
+
+SUBSYSTEM=="sound", GROUP="audio", \
+ OPTIONS+="static_node=snd/seq", OPTIONS+="static_node=snd/timer"
+
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664"
+
+SUBSYSTEM=="firewire", TEST=="units", TEST=="model", \
+ IMPORT{builtin}="hwdb 'ieee1394:node:ven$attr{vendor}mo$attr{model}units$attr{units}'"
+
+SUBSYSTEM=="firewire", TEST=="units", TEST!="model", \
+ IMPORT{builtin}="hwdb 'ieee1394:node:ven$attr{vendor}units$attr{units}'"
+
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_MIDI}=="1", GROUP="audio"
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_AUDIO}=="1", GROUP="audio"
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_VIDEO}=="1", GROUP="video"
+
+KERNEL=="parport[0-9]*", GROUP="lp"
+SUBSYSTEM=="printer", KERNEL=="lp*", GROUP="lp"
+SUBSYSTEM=="ppdev", GROUP="lp"
+KERNEL=="lp[0-9]*", GROUP="lp"
+KERNEL=="irlpt[0-9]*", GROUP="lp"
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", GROUP="lp"
+
+SUBSYSTEM=="block", GROUP="disk"
+SUBSYSTEM=="block", KERNEL=="sr[0-9]*", GROUP="cdrom"
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", GROUP="cdrom"
+KERNEL=="sch[0-9]*", GROUP="cdrom"
+KERNEL=="pktcdvd[0-9]*", GROUP="cdrom"
+KERNEL=="pktcdvd", GROUP="cdrom"
+
+SUBSYSTEM=="scsi_generic|scsi_tape", SUBSYSTEMS=="scsi", ATTRS{type}=="1|8", GROUP="tape"
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="0", GROUP="disk"
+KERNEL=="qft[0-9]*|nqft[0-9]*|zqft[0-9]*|nzqft[0-9]*|rawqft[0-9]*|nrawqft[0-9]*", GROUP="disk"
+KERNEL=="loop-control", GROUP="disk", OPTIONS+="static_node=loop-control"
+KERNEL=="btrfs-control", GROUP="disk"
+KERNEL=="rawctl", GROUP="disk"
+SUBSYSTEM=="raw", KERNEL=="raw[0-9]*", GROUP="disk"
+SUBSYSTEM=="aoe", GROUP="disk", MODE="0220"
+SUBSYSTEM=="aoe", KERNEL=="err", MODE="0440"
+
+KERNEL=="rfkill", MODE="0664"
+KERNEL=="tun", MODE="0666", OPTIONS+="static_node=net/tun"
+
+KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse"
+
+# The static_node is required on s390x and ppc (they are using MODULE_ALIAS)
+KERNEL=="kvm", GROUP="kvm", MODE="{{DEV_KVM_MODE}}", OPTIONS+="static_node=kvm"
+
+KERNEL=="vfio", MODE="0666", OPTIONS+="static_node=vfio/vfio"
+
+KERNEL=="vsock", MODE="0666"
+KERNEL=="vhost-vsock", GROUP="kvm", MODE="{{DEV_KVM_MODE}}", OPTIONS+="static_node=vhost-vsock"
+
+KERNEL=="vhost-net", GROUP="kvm", MODE="{{DEV_KVM_MODE}}", OPTIONS+="static_node=vhost-net"
+
+KERNEL=="udmabuf", GROUP="kvm"
+
+SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK += "ptp_kvm"
+
+SUBSYSTEM=="ptp", ATTR{clock_name}=="hyperv", SYMLINK += "ptp_hyperv"
+
+SUBSYSTEM!="dmi", GOTO="dmi_end"
+ENV{ID_SYS_VENDOR_IS_RUBBISH}!="1", ENV{ID_VENDOR}="$attr{sys_vendor}"
+ENV{ID_SYSFS_ATTRIBUTE_MODEL}=="", ENV{ID_PRODUCT_NAME_IS_RUBBISH}!="1", ENV{ID_MODEL}="$attr{product_name}"
+ENV{ID_SYSFS_ATTRIBUTE_MODEL}=="product_name", ENV{ID_MODEL}="$attr{product_name}"
+ENV{ID_SYSFS_ATTRIBUTE_MODEL}=="product_version", ENV{ID_MODEL}="$attr{product_version}"
+# fallback to board information
+ENV{ID_VENDOR}=="", ENV{ID_VENDOR}="$attr{board_vendor}"
+ENV{ID_MODEL}=="", ENV{ID_MODEL}="$attr{board_name}"
+LABEL="dmi_end"
+
+LABEL="default_end"
diff --git a/rules.d/60-autosuspend.rules b/rules.d/60-autosuspend.rules
new file mode 100644
index 0000000..ce31a92
--- /dev/null
+++ b/rules.d/60-autosuspend.rules
@@ -0,0 +1,22 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add", GOTO="autosuspend_end"
+
+# I2C rules
+SUBSYSTEM=="i2c", ATTR{name}=="cyapa", \
+ ATTR{power/control}="on", GOTO="autosuspend_end"
+
+# Enable autosuspend if hwdb says so. Here we are relying on
+# the hwdb import done earlier based on MODALIAS.
+ENV{ID_AUTOSUSPEND}=="1", TEST=="power/control", \
+ ATTR{power/control}="auto"
+
+# Disable USB persist if hwdb says so.
+ENV{ID_PERSIST}=="0", TEST=="power/persist", \
+ ATTR{power/persist}="0"
+
+# Set up an autosuspend delay if hwdb say so
+ENV{ID_AUTOSUSPEND_DELAY_MS}!="", TEST=="power/control", \
+ ATTR{power/autosuspend_delay_ms}="$env{ID_AUTOSUSPEND_DELAY_MS}"
+
+LABEL="autosuspend_end"
diff --git a/rules.d/60-block.rules b/rules.d/60-block.rules
new file mode 100644
index 0000000..3134ab9
--- /dev/null
+++ b/rules.d/60-block.rules
@@ -0,0 +1,13 @@
+# do not edit this file, it will be overwritten on update
+
+# enable in-kernel media-presence polling
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_poll_msecs}=="0", \
+ ATTR{parameters/events_dfl_poll_msecs}="2000"
+
+# forward scsi device event to corresponding block device
+ACTION=="change", SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST=="block", ATTR{block/*/uevent}="change"
+
+# watch metadata changes, caused by tools closing the device node which was opened for writing
+ACTION!="remove", SUBSYSTEM=="block", \
+ KERNEL=="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|ubi*|scm*|pmem*|nbd*|zd*", \
+ OPTIONS+="watch"
diff --git a/rules.d/60-cdrom_id.rules b/rules.d/60-cdrom_id.rules
new file mode 100644
index 0000000..288f8ce
--- /dev/null
+++ b/rules.d/60-cdrom_id.rules
@@ -0,0 +1,29 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="cdrom_end"
+SUBSYSTEM!="block", GOTO="cdrom_end"
+KERNEL!="sr[0-9]*|vdisk*|xvd*", GOTO="cdrom_end"
+ENV{DEVTYPE}!="disk", GOTO="cdrom_end"
+
+# unconditionally tag device as CDROM
+KERNEL=="sr[0-9]*", ENV{ID_CDROM}="1"
+
+# stop automatically any mount units bound to the device if the media eject
+# button is pressed.
+ENV{ID_CDROM}=="1", ENV{SYSTEMD_MOUNT_DEVICE_BOUND}="1"
+
+# media eject button pressed
+ENV{DISK_EJECT_REQUEST}=="?*", RUN+="cdrom_id --eject-media $devnode", GOTO="cdrom_end"
+
+# import device and media properties and lock tray to
+# enable the receiving of media eject button events
+IMPORT{program}="cdrom_id --lock-media $devnode"
+
+# ejecting a CD does not remove the device node, so mark the systemd device
+# unit as inactive while there is no medium; this automatically cleans up of
+# stale mounts after ejecting
+ENV{DISK_MEDIA_CHANGE}=="?*", ENV{ID_CDROM_MEDIA}!="?*", ENV{SYSTEMD_READY}="0"
+
+KERNEL=="sr0", SYMLINK+="cdrom", OPTIONS+="link_priority=-100"
+
+LABEL="cdrom_end"
diff --git a/rules.d/60-drm.rules b/rules.d/60-drm.rules
new file mode 100644
index 0000000..f7f3435
--- /dev/null
+++ b/rules.d/60-drm.rules
@@ -0,0 +1,8 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="remove", SUBSYSTEM=="drm", SUBSYSTEMS=="pci|usb|platform", IMPORT{builtin}="path_id"
+
+# by-path
+ENV{ID_PATH}=="?*", KERNEL=="card*", SYMLINK+="dri/by-path/$env{ID_PATH}-card"
+ENV{ID_PATH}=="?*", KERNEL=="controlD*", SYMLINK+="dri/by-path/$env{ID_PATH}-control"
+ENV{ID_PATH}=="?*", KERNEL=="renderD*", SYMLINK+="dri/by-path/$env{ID_PATH}-render"
diff --git a/rules.d/60-evdev.rules b/rules.d/60-evdev.rules
new file mode 100644
index 0000000..c97cdec
--- /dev/null
+++ b/rules.d/60-evdev.rules
@@ -0,0 +1,30 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="evdev_end"
+KERNEL!="event*", GOTO="evdev_end"
+
+# Execute the match patterns below, from least-to-most specific.
+
+# Device matching the modalias string (bustype, vendor, product, version, other properties)
+IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \
+ ENV{.HAVE_HWDB_PROPERTIES}="1"
+
+# AT keyboard matching by the machine's DMI data
+DRIVERS=="atkbd", \
+ IMPORT{builtin}="hwdb 'evdev:atkbd:$attr{[dmi/id]modalias}'", \
+ ENV{.HAVE_HWDB_PROPERTIES}="1"
+
+# Device matching the input device name and the machine's DMI data
+KERNELS=="input*", \
+ IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:$attr{[dmi/id]modalias}'", \
+ ENV{.HAVE_HWDB_PROPERTIES}="1"
+
+# Device matching the input device name + properties + the machine's DMI data
+KERNELS=="input*", \
+ IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:phys:$attr{phys}:ev:$attr{capabilities/ev}:$attr{[dmi/id]modalias}'", \
+ ENV{.HAVE_HWDB_PROPERTIES}="1"
+
+ENV{.HAVE_HWDB_PROPERTIES}=="1", \
+ IMPORT{builtin}="keyboard"
+
+LABEL="evdev_end"
diff --git a/rules.d/60-fido-id.rules b/rules.d/60-fido-id.rules
new file mode 100644
index 0000000..48c259e
--- /dev/null
+++ b/rules.d/60-fido-id.rules
@@ -0,0 +1,14 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="fido_id_end"
+
+SUBSYSTEM=="hidraw", IMPORT{program}="fido_id"
+
+# Tag any form of security token as such
+ENV{ID_SECURITY_TOKEN}=="1", TAG+="security-device"
+
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0b????:*", ENV{ID_SMARTCARD_READER}="1"
+# Tag any CCID device (i.e. Smartcard Reader) as security token
+ENV{ID_SMARTCARD_READER}=="1", TAG+="security-device"
+
+LABEL="fido_id_end"
diff --git a/rules.d/60-infiniband.rules b/rules.d/60-infiniband.rules
new file mode 100644
index 0000000..da3eea6
--- /dev/null
+++ b/rules.d/60-infiniband.rules
@@ -0,0 +1,12 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="infiniband_end"
+SUBSYSTEM!="infiniband_verbs", GOTO="infiniband_end"
+KERNEL!="uverbs*", GOTO="infiniband_end"
+
+IMPORT{builtin}="path_id"
+
+ENV{ID_PATH}=="?*", SYMLINK+="infiniband/by-path/$env{ID_PATH}"
+ATTR{ibdev}=="?*", SYMLINK+="infiniband/by-ibdev/uverbs-$attr{ibdev}"
+
+LABEL="infiniband_end"
diff --git a/rules.d/60-input-id.rules b/rules.d/60-input-id.rules
new file mode 100644
index 0000000..bb8a812
--- /dev/null
+++ b/rules.d/60-input-id.rules
@@ -0,0 +1,8 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="id_input_end"
+
+SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id"
+SUBSYSTEM=="input", IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=id-input:modalias:"
+
+LABEL="id_input_end"
diff --git a/rules.d/60-persistent-alsa.rules b/rules.d/60-persistent-alsa.rules
new file mode 100644
index 0000000..8154e2d
--- /dev/null
+++ b/rules.d/60-persistent-alsa.rules
@@ -0,0 +1,14 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="persistent_alsa_end"
+SUBSYSTEM!="sound", GOTO="persistent_alsa_end"
+KERNEL!="controlC[0-9]*", GOTO="persistent_alsa_end"
+
+SUBSYSTEMS=="usb", ENV{ID_MODEL}=="", IMPORT{builtin}="usb_id"
+ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", SYMLINK+="snd/by-id/$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}"
+ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", SYMLINK+="snd/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
+
+IMPORT{builtin}="path_id"
+ENV{ID_PATH}=="?*", SYMLINK+="snd/by-path/$env{ID_PATH}"
+
+LABEL="persistent_alsa_end"
diff --git a/rules.d/60-persistent-input.rules b/rules.d/60-persistent-input.rules
new file mode 100644
index 0000000..52f4ddb
--- /dev/null
+++ b/rules.d/60-persistent-input.rules
@@ -0,0 +1,42 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="persistent_input_end"
+SUBSYSTEM!="input", GOTO="persistent_input_end"
+SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
+# Bluetooth devices don't always have the bluetooth subsystem
+ATTRS{id/bustype}=="0005", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end"
+SUBSYSTEMS=="rmi4", ENV{ID_BUS}="rmi"
+SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042"
+
+SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id"
+
+# determine class name for persistent symlinks
+ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd"
+ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse"
+ENV{ID_INPUT_TOUCHPAD}=="?*", ENV{.INPUT_CLASS}="mouse"
+ENV{ID_INPUT_TABLET}=="?*", ENV{.INPUT_CLASS}="mouse"
+ENV{ID_INPUT_JOYSTICK}=="?*", ENV{.INPUT_CLASS}="joystick"
+DRIVERS=="pcspkr", ENV{.INPUT_CLASS}="spkr"
+ATTRS{name}=="*dvb*|*DVB*|* IR *", ENV{.INPUT_CLASS}="ir"
+
+# fill empty serial number
+ENV{.INPUT_CLASS}=="?*", ENV{ID_SERIAL}=="", ENV{ID_SERIAL}="noserial"
+
+# by-id links
+KERNEL=="mouse*|js*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="|00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-$env{.INPUT_CLASS}"
+KERNEL=="mouse*|js*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="?*", ATTRS{bInterfaceNumber}!="00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$attr{bInterfaceNumber}-$env{.INPUT_CLASS}"
+KERNEL=="event*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="|00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-event-$env{.INPUT_CLASS}"
+KERNEL=="event*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="?*", ATTRS{bInterfaceNumber}!="00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$attr{bInterfaceNumber}-event-$env{.INPUT_CLASS}"
+# allow empty class for USB devices, by appending the interface number
+SUBSYSTEMS=="usb", ENV{ID_BUS}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", ATTRS{bInterfaceNumber}=="?*", \
+ SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-event-if$attr{bInterfaceNumber}"
+
+# by-path
+SUBSYSTEMS=="pci|usb|platform|acpi", IMPORT{builtin}="path_id"
+ENV{ID_PATH}=="?*", KERNEL=="mouse*|js*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-$env{.INPUT_CLASS}"
+ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-event-$env{.INPUT_CLASS}"
+# allow empty class for platform, usb and i2c devices; platform supports only a single interface that way
+SUBSYSTEMS=="usb|platform|i2c", ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", \
+ SYMLINK+="input/by-path/$env{ID_PATH}-event"
+
+LABEL="persistent_input_end"
diff --git a/rules.d/60-persistent-storage-tape.rules b/rules.d/60-persistent-storage-tape.rules
new file mode 100644
index 0000000..607e51a
--- /dev/null
+++ b/rules.d/60-persistent-storage-tape.rules
@@ -0,0 +1,36 @@
+# do not edit this file, it will be overwritten on update
+
+# persistent storage links: /dev/tape/{by-id,by-path}
+
+ACTION=="remove", GOTO="persistent_storage_tape_end"
+ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_tape_end"
+
+# type 8 devices are "Medium Changers"
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $devnode", \
+ SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL} tape/by-id/scsi-$env{ID_SERIAL}-changer"
+
+# iSCSI devices from the same host have all the same ID_SERIAL,
+# but additionally a property named ID_SCSI_SERIAL.
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", ENV{ID_SCSI_SERIAL}=="?*", \
+ SYMLINK+="tape/by-id/scsi-$env{ID_SCSI_SERIAL}"
+
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{builtin}="path_id", \
+ SYMLINK+="tape/by-path/$env{ID_PATH}-changer"
+
+SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end"
+
+KERNEL=="st*[0-9]|nst*[0-9]", ATTRS{ieee1394_id}=="?*", ENV{ID_SERIAL}="$attr{ieee1394_id}", ENV{ID_BUS}="ieee1394"
+KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
+KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", KERNELS=="[0-9]*:*[0-9]", ENV{.BSG_DEV}="$root/bsg/$id"
+KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --whitelisted --export --device=$env{.BSG_DEV}", ENV{ID_BUS}="scsi"
+KERNEL=="st*[0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}", OPTIONS+="link_priority=10"
+KERNEL=="st*[0-9]", ENV{ID_SCSI_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SCSI_SERIAL}"
+KERNEL=="nst*[0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}-nst"
+KERNEL=="nst*[0-9]", ENV{ID_SCSI_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SCSI_SERIAL}-nst"
+
+# by-path (parent device path)
+KERNEL=="st*[0-9]|nst*[0-9]", IMPORT{builtin}="path_id"
+KERNEL=="st*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}"
+KERNEL=="nst*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}-nst"
+
+LABEL="persistent_storage_tape_end"
diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules
new file mode 100644
index 0000000..d6612da
--- /dev/null
+++ b/rules.d/60-persistent-storage.rules
@@ -0,0 +1,149 @@
+# do not edit this file, it will be overwritten on update
+
+# persistent storage links: /dev/disk/{by-id,by-uuid,by-label,by-path}
+# scheme based on "Linux persistent device names", 2004, Hannes Reinecke <hare@suse.de>
+
+ACTION=="remove", GOTO="persistent_storage_end"
+ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_end"
+
+SUBSYSTEM!="block|ubi", GOTO="persistent_storage_end"
+KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|ubi*|scm*|pmem*|nbd*|zd*", GOTO="persistent_storage_end"
+
+# ignore partitions that span the entire disk
+TEST=="whole_disk", GOTO="persistent_storage_end"
+
+# For partitions import parent disk ID_* information, except ID_FS_*.
+#
+# This is particularly important on media where a filesystem superblock and
+# partition table are found on the same level, e.g. common Linux distro ISO
+# installation media.
+#
+# In the case where a partition device points to the same filesystem that
+# was detected on the parent disk, the ID_FS_* information is already
+# present on the partition devices as well as the parent, so no need to
+# propagate it. In the case where the partition device points to a different
+# filesystem, merging the parent ID_FS_ properties would lead to
+# inconsistencies, so we avoid doing so.
+ENV{DEVTYPE}=="partition", \
+ IMPORT{parent}="ID_[!F]*", IMPORT{parent}="ID_", \
+ IMPORT{parent}="ID_F[!S]*", IMPORT{parent}="ID_F", \
+ IMPORT{parent}="ID_FS[!_]*", IMPORT{parent}="ID_FS"
+
+# NVMe
+KERNEL=="nvme*[0-9]n*[0-9]", ATTR{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}"
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}-part%n"
+
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}"
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{wwid}=="?*", ENV{ID_WWN}="$attr{wwid}"
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}"
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}"
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{nsid}=="?*", ENV{ID_NSID}="$attr{nsid}"
+# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
+ OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
+KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*",\
+ OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}_$env{ID_NSID}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
+
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}"
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}"
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}"
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{nsid}=="?*", ENV{ID_NSID}="$attr{nsid}"
+# obsolete symlink that might get overridden on adding a new nvme controller, kept for backward compatibility
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \
+ OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
+KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_NSID}=="?*",\
+ OPTIONS="string_escape=replace", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}_$env{ID_NSID}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
+
+# virtio-blk
+KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}"
+KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}-part%n"
+
+# ATA
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}="ata_id --export $devnode"
+
+# ATAPI devices (SPC-3 or later)
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5", ATTRS{scsi_level}=="[6-9]*", IMPORT{program}="ata_id --export $devnode"
+
+# Run ata_id on non-removable USB Mass Storage (SATA/PATA disks in enclosures)
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", ATTR{removable}=="0", SUBSYSTEMS=="usb", IMPORT{program}="ata_id --export $devnode"
+
+# Also import properties from usb_id for USB devices
+KERNEL=="sd*[!0-9]|sr*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
+
+# SCSI devices
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="scsi"
+KERNEL=="cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="cciss"
+KERNEL=="sd*|sr*|cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
+KERNEL=="sd*|cciss*", ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n"
+# Previously, ata_id in the above might not be able to retrieve attributes correctly,
+# and properties from usb_id were used as a fallback. See issue #24921 and PR #24923.
+# To keep backward compatibility, still we need to create symlinks based on USB serial.
+# See issue #25179.
+KERNEL=="sd*|sr*|cciss*", ENV{DEVTYPE}=="disk", ENV{ID_USB_SERIAL}=="?*", SYMLINK+="disk/by-id/usb-$env{ID_USB_SERIAL}"
+KERNEL=="sd*|cciss*", ENV{DEVTYPE}=="partition", ENV{ID_USB_SERIAL}=="?*", SYMLINK+="disk/by-id/usb-$env{ID_USB_SERIAL}-part%n"
+
+# PMEM devices
+KERNEL=="pmem*", ENV{DEVTYPE}=="disk", ATTRS{uuid}=="?*", SYMLINK+="disk/by-id/pmem-$attr{uuid}"
+
+# FireWire
+KERNEL=="sd*[!0-9]|sr*", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}"
+KERNEL=="sd*[0-9]", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}-part%n"
+
+# MMC
+KERNEL=="mmcblk[0-9]", SUBSYSTEMS=="mmc", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}"
+KERNEL=="mmcblk[0-9]", SUBSYSTEMS=="mmc", ATTRS{name}=="?*", ENV{ID_NAME}="$attr{name}"
+KERNEL=="mmcblk[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}"
+KERNEL=="mmcblk[0-9]p[0-9]*", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}-part%n"
+
+# Memstick
+KERNEL=="msblk[0-9]|mspblk[0-9]", SUBSYSTEMS=="memstick", ATTRS{name}=="?*", ATTRS{serial}=="?*", \
+ ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}"
+KERNEL=="msblk[0-9]p[0-9]|mspblk[0-9]p[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}-part%n"
+
+# by-path
+ENV{DEVTYPE}=="disk", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id"
+ENV{DEVTYPE}=="disk", SUBSYSTEMS=="nvme-subsystem", IMPORT{builtin}="path_id"
+KERNEL=="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-boot%n"
+KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}"
+ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n"
+# compatible links for ATA devices
+KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH_ATA_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_ATA_COMPAT}"
+ENV{DEVTYPE}=="partition", ENV{ID_PATH_ATA_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_ATA_COMPAT}-part%n"
+
+# legacy virtio-pci by-path links (deprecated)
+KERNEL=="vd*[!0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}"
+KERNEL=="vd*[0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}-part%n"
+
+# allow admin to disable probing the filesystem for slow devices like floppy disk drives
+ENV{UDEV_DISABLE_PERSISTENT_STORAGE_BLKID_FLAG}=="1", GOTO="persistent_storage_blkid_probe_end"
+
+# probe filesystem metadata of optical drives which have a media inserted
+KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="?*", \
+ IMPORT{builtin}="blkid --hint=session_offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}"
+# single-session CDs do not have ID_CDROM_MEDIA_SESSION_LAST_OFFSET
+KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \
+ IMPORT{builtin}="blkid --noraid"
+
+# probe filesystem metadata of disks
+KERNEL!="sr*|mmcblk[0-9]boot[0-9]", IMPORT{builtin}="blkid"
+
+LABEL="persistent_storage_blkid_probe_end"
+
+# by-label/by-uuid links (filesystem metadata)
+ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}"
+ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"
+
+# by-id (World Wide Name)
+ENV{DEVTYPE}=="disk", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}"
+ENV{DEVTYPE}=="partition", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}-part%n"
+
+# by-partlabel/by-partuuid links (partition metadata)
+ENV{ID_PART_ENTRY_UUID}=="?*", SYMLINK+="disk/by-partuuid/$env{ID_PART_ENTRY_UUID}"
+ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_NAME}=="?*", SYMLINK+="disk/by-partlabel/$env{ID_PART_ENTRY_NAME}"
+
+# by-diskseq link (if an app is told to open a path like this, they may parse
+# the diskseq number from the path, then issue BLKGETDISKSEQ to verify they really got
+# the right device, to access specific disks in a race-free fashion)
+ENV{DISKSEQ}=="?*", ENV{DEVTYPE}!="partition", ENV{DISKSEQ}=="?*", ENV{ID_IGNORE_DISKSEQ}!="1", SYMLINK+="disk/by-diskseq/$env{DISKSEQ}"
+
+LABEL="persistent_storage_end"
diff --git a/rules.d/60-persistent-v4l.rules b/rules.d/60-persistent-v4l.rules
new file mode 100644
index 0000000..93c5ee8
--- /dev/null
+++ b/rules.d/60-persistent-v4l.rules
@@ -0,0 +1,20 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="persistent_v4l_end"
+SUBSYSTEM!="video4linux", GOTO="persistent_v4l_end"
+ENV{MAJOR}=="", GOTO="persistent_v4l_end"
+
+IMPORT{program}="v4l_id $devnode"
+
+SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
+KERNEL=="video*", ENV{ID_SERIAL}=="?*", SYMLINK+="v4l/by-id/$env{ID_BUS}-$env{ID_SERIAL}-video-index$attr{index}"
+
+# check for valid "index" number
+TEST!="index", GOTO="persistent_v4l_end"
+ATTR{index}!="?*", GOTO="persistent_v4l_end"
+
+IMPORT{builtin}="path_id"
+ENV{ID_PATH}=="?*", KERNEL=="video*|vbi*", SYMLINK+="v4l/by-path/$env{ID_PATH}-video-index$attr{index}"
+ENV{ID_PATH}=="?*", KERNEL=="audio*", SYMLINK+="v4l/by-path/$env{ID_PATH}-audio-index$attr{index}"
+
+LABEL="persistent_v4l_end"
diff --git a/rules.d/60-sensor.rules b/rules.d/60-sensor.rules
new file mode 100644
index 0000000..09180b4
--- /dev/null
+++ b/rules.d/60-sensor.rules
@@ -0,0 +1,34 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="sensor_end"
+
+# device matching the sensor's label, name and the machine's DMI data for IIO devices
+SUBSYSTEM=="iio", KERNEL=="iio*", SUBSYSTEMS=="usb|i2c|platform", ATTR{label}!="", \
+ IMPORT{builtin}="hwdb 'sensor:$attr{label}:modalias:$attr{modalias}:$attr{[dmi/id]modalias}'", \
+ GOTO="sensor_end"
+
+# Before Linux v6.0, cros-ec-accel used a non-standard 'location' sysfs file
+SUBSYSTEM=="iio", KERNEL=="iio*", SUBSYSTEMS=="platform", \
+ ATTR{name}=="cros-ec-accel|cros-ec-accel-legacy", ATTR{location}=="base", \
+ IMPORT{builtin}="hwdb 'sensor:accel-base:modalias:$attr{modalias}:$attr{[dmi/id]modalias}'", \
+ GOTO="sensor_end"
+
+SUBSYSTEM=="iio", KERNEL=="iio*", SUBSYSTEMS=="platform", \
+ ATTR{name}=="cros-ec-accel|cros-ec-accel-legacy", ATTR{location}=="lid", \
+ IMPORT{builtin}="hwdb 'sensor:accel-display:modalias:$attr{modalias}:$attr{[dmi/id]modalias}'", \
+ GOTO="sensor_end"
+
+# device matching the sensor's name and the machine's DMI data for IIO devices
+SUBSYSTEM=="iio", KERNEL=="iio*", SUBSYSTEMS=="usb|i2c|platform", \
+ IMPORT{builtin}="hwdb 'sensor:modalias:$attr{modalias}:$attr{[dmi/id]modalias}'", \
+ GOTO="sensor_end"
+
+SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="1", SUBSYSTEMS=="acpi", \
+ IMPORT{builtin}="hwdb 'sensor:modalias:acpi:$attr{hid}:$attr{[dmi/id]modalias}'", \
+ GOTO="sensor_end"
+
+SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="1", SUBSYSTEMS=="platform", \
+ IMPORT{builtin}="hwdb 'sensor:modalias:platform:$id:$attr{[dmi/id]modalias}'", \
+ GOTO="sensor_end"
+
+LABEL="sensor_end"
diff --git a/rules.d/60-serial.rules b/rules.d/60-serial.rules
new file mode 100644
index 0000000..a0e6632
--- /dev/null
+++ b/rules.d/60-serial.rules
@@ -0,0 +1,26 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="serial_end"
+SUBSYSTEM!="tty", GOTO="serial_end"
+
+SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
+SUBSYSTEMS=="pci", ENV{ID_BUS}=="", ENV{ID_BUS}="pci", \
+ ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}", \
+ IMPORT{builtin}="hwdb --subsystem=pci"
+
+# /dev/serial/by-path/, /dev/serial/by-id/ for USB devices
+KERNEL!="ttyUSB[0-9]*|ttyACM[0-9]*", GOTO="serial_end"
+
+SUBSYSTEMS=="usb-serial", ENV{.ID_PORT}="$attr{port_number}"
+
+IMPORT{builtin}="path_id"
+ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH}"
+ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{.ID_PORT}"
+
+ENV{ID_BUS}=="", GOTO="serial_end"
+ENV{ID_SERIAL}=="", GOTO="serial_end"
+ENV{ID_USB_INTERFACE_NUM}=="", GOTO="serial_end"
+ENV{.ID_PORT}=="", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}"
+ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}-port$env{.ID_PORT}"
+
+LABEL="serial_end"
diff --git a/rules.d/64-btrfs.rules.in b/rules.d/64-btrfs.rules.in
new file mode 100644
index 0000000..df6e12a
--- /dev/null
+++ b/rules.d/64-btrfs.rules.in
@@ -0,0 +1,17 @@
+# do not edit this file, it will be overwritten on update
+
+SUBSYSTEM!="block", GOTO="btrfs_end"
+ACTION=="remove", GOTO="btrfs_end"
+ENV{ID_FS_TYPE}!="btrfs", GOTO="btrfs_end"
+ENV{SYSTEMD_READY}=="0", GOTO="btrfs_end"
+
+# let the kernel know about this btrfs filesystem, and check if it is complete
+IMPORT{builtin}="btrfs ready $devnode"
+
+# mark the device as not ready to be used by the system
+ENV{ID_BTRFS_READY}=="0", ENV{SYSTEMD_READY}="0"
+
+# reconsider pending devices in case when multidevice volume awaits
+ENV{ID_BTRFS_READY}=="1", RUN+="{{ROOTBINDIR}}/udevadm trigger -s block -p ID_BTRFS_READY=0"
+
+LABEL="btrfs_end"
diff --git a/rules.d/70-camera.rules b/rules.d/70-camera.rules
new file mode 100644
index 0000000..b1053f2
--- /dev/null
+++ b/rules.d/70-camera.rules
@@ -0,0 +1,9 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="camera_end"
+
+SUBSYSTEM=="video4linux", ENV{ID_BUS}="usb" , \
+ IMPORT{builtin}="hwdb 'camera:usb:v$env{ID_VENDOR_ID}p$env{ID_MODEL_ID}:name:$attr{name}:'", \
+ GOTO="camera_end"
+
+LABEL="camera_end"
diff --git a/rules.d/70-joystick.rules b/rules.d/70-joystick.rules
new file mode 100644
index 0000000..b80d203
--- /dev/null
+++ b/rules.d/70-joystick.rules
@@ -0,0 +1,12 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="joystick_end"
+ENV{ID_INPUT_JOYSTICK}=="", GOTO="joystick_end"
+KERNEL!="event*", GOTO="joystick_end"
+
+# joystick:<bustype>:v<vid>p<pid>:name:<name>:*
+KERNELS=="input*", ENV{ID_BUS}!="", \
+ IMPORT{builtin}="hwdb 'joystick:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
+ GOTO="joystick_end"
+
+LABEL="joystick_end"
diff --git a/rules.d/70-memory.rules b/rules.d/70-memory.rules
new file mode 100644
index 0000000..f2610ff
--- /dev/null
+++ b/rules.d/70-memory.rules
@@ -0,0 +1,8 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="memory_end"
+SUBSYSTEM!="dmi", GOTO="memory_end"
+
+IMPORT{program}="dmi_memory_id"
+
+LABEL="memory_end"
diff --git a/rules.d/70-mouse.rules b/rules.d/70-mouse.rules
new file mode 100644
index 0000000..3ea743a
--- /dev/null
+++ b/rules.d/70-mouse.rules
@@ -0,0 +1,18 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="mouse_end"
+KERNEL!="event*", GOTO="mouse_end"
+ENV{ID_INPUT_MOUSE}=="", GOTO="mouse_end"
+
+# mouse:<subsystem>:v<vid>p<pid>:name:<name>:*
+KERNELS=="input*", ENV{ID_BUS}=="usb", \
+ IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
+ GOTO="mouse_end"
+KERNELS=="input*", ENV{ID_BUS}=="bluetooth", \
+ IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
+ GOTO="mouse_end"
+DRIVERS=="psmouse", SUBSYSTEMS=="serio", \
+ IMPORT{builtin}="hwdb 'mouse:ps2::name:$attr{device/name}:'", \
+ GOTO="mouse_end"
+
+LABEL="mouse_end"
diff --git a/rules.d/70-power-switch.rules b/rules.d/70-power-switch.rules
new file mode 100644
index 0000000..3fb954a
--- /dev/null
+++ b/rules.d/70-power-switch.rules
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+ACTION=="remove", GOTO="power_switch_end"
+
+SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_SWITCH}=="1", TAG+="power-switch"
+SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_KEY}=="1", TAG+="power-switch"
+
+LABEL="power_switch_end"
diff --git a/rules.d/70-touchpad.rules b/rules.d/70-touchpad.rules
new file mode 100644
index 0000000..7bede02
--- /dev/null
+++ b/rules.d/70-touchpad.rules
@@ -0,0 +1,13 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="touchpad_end"
+ENV{ID_INPUT}=="", GOTO="touchpad_end"
+ENV{ID_INPUT_TOUCHPAD}=="", GOTO="touchpad_end"
+KERNEL!="event*", GOTO="touchpad_end"
+
+# touchpad:<subsystem>:v<vid>p<pid>:name:<name>:*
+KERNELS=="input*", ENV{ID_BUS}!="", \
+ IMPORT{builtin}="hwdb 'touchpad:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
+ GOTO="touchpad_end"
+
+LABEL="touchpad_end"
diff --git a/rules.d/70-uaccess.rules.in b/rules.d/70-uaccess.rules.in
new file mode 100644
index 0000000..b82ce04
--- /dev/null
+++ b/rules.d/70-uaccess.rules.in
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+ACTION=="remove", GOTO="uaccess_end"
+ENV{MAJOR}=="", GOTO="uaccess_end"
+
+# PTP/MTP protocol devices, cameras, portable media players
+SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess"
+
+# Digicams with proprietary protocol
+ENV{ID_GPHOTO2}=="?*", TAG+="uaccess"
+
+# SCSI and USB scanners
+ENV{libsane_matched}=="yes", TAG+="uaccess"
+
+# HPLIP devices (necessary for ink level check and HP tool maintenance)
+ENV{ID_HPLIP}=="1", TAG+="uaccess"
+
+# optical drives
+SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="uaccess"
+SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess"
+
+# Sound devices
+SUBSYSTEM=="sound", TAG+="uaccess", \
+ OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq"
+
+# Webcams, frame grabber, TV cards
+SUBSYSTEM=="video4linux", TAG+="uaccess"
+SUBSYSTEM=="dvb", TAG+="uaccess"
+SUBSYSTEM=="media", TAG+="uaccess"
+
+# industrial cameras, some webcams, camcorders, set-top boxes, TV sets, audio devices, and more
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_MIDI}=="1", TAG+="uaccess"
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_AUDIO}=="1", TAG+="uaccess"
+SUBSYSTEM=="firewire", TEST=="units", ENV{IEEE1394_UNIT_FUNCTION_VIDEO}=="1", TAG+="uaccess"
+
+# DRI video devices
+SUBSYSTEM=="drm", KERNEL=="card*", TAG+="uaccess"
+{% if GROUP_RENDER_UACCESS %}
+# DRI render nodes
+SUBSYSTEM=="drm", KERNEL=="renderD*", TAG+="uaccess"
+{% endif %}
+{% if DEV_KVM_UACCESS %}
+# KVM
+SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"
+{% endif %}
+
+# smart-card readers
+ENV{ID_SMARTCARD_READER}=="?*", TAG+="uaccess"
+
+# (USB) authentication devices
+ENV{ID_SECURITY_TOKEN}=="?*", TAG+="uaccess"
+
+# PDA devices
+ENV{ID_PDA}=="?*", TAG+="uaccess"
+
+# Programmable remote control
+ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess"
+
+# joysticks
+SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess"
+
+# color measurement devices
+ENV{COLOR_MEASUREMENT_DEVICE}=="?*", TAG+="uaccess"
+
+# DDC/CI device, usually high-end monitors such as the DreamColor
+ENV{DDC_DEVICE}=="?*", TAG+="uaccess"
+
+# media player raw devices (for user-mode drivers, Android SDK, etc.)
+SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess"
+
+# software-defined radio communication devices
+ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess"
+
+# 3D printers, CNC machines, laser cutters, 3D scanners, etc.
+ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess"
+
+# Protocol analyzers
+ENV{ID_SIGNAL_ANALYZER}=="?*", ENV{DEVTYPE}=="usb_device", TAG+="uaccess"
+ENV{ID_SIGNAL_ANALYZER}=="?*", KERNEL=="ttyACM[0-9]*", TAG+="uaccess"
+
+# rfkill / radio killswitches
+KERNEL=="rfkill", SUBSYSTEM=="misc", TAG+="uaccess"
+
+# AV production controllers
+# Most of these devices use HID for the knobs, faders, buttons, encoders, and jog wheels.
+SUBSYSTEM=="hidraw", ENV{ID_AV_PRODUCTION_CONTROLLER}=="1", TAG+="uaccess"
+
+# Some devices use vendor defined protocols on USB Bulk endpoints for controllers.
+# Other devices transfer graphics to screens on the device through USB Bulk endpoints.
+# This also allows accessing HID devices with the libusb backend of hidapi.
+SUBSYSTEM=="usb", ENV{ID_AV_PRODUCTION_CONTROLLER}=="1", TAG+="uaccess"
+
+LABEL="uaccess_end"
diff --git a/rules.d/71-seat.rules.in b/rules.d/71-seat.rules.in
new file mode 100644
index 0000000..25e4ee7
--- /dev/null
+++ b/rules.d/71-seat.rules.in
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+ACTION=="remove", GOTO="seat_end"
+
+TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat"
+SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat"
+SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat"
+SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat"
+
+# Assign keyboard and LCD backlights to the seat
+SUBSYSTEM=="leds", TAG+="seat"
+SUBSYSTEM=="backlight", TAG+="seat"
+
+# Allow efifb / uvesafb to be a master if KMS is disabled
+SUBSYSTEM=="graphics", KERNEL=="fb[0-9]", IMPORT{cmdline}="nomodeset", TAG+="master-of-seat"
+
+# Allow any PCI graphics device to be a master and synthesize a seat if KMS
+# is disabled and the kernel doesn't have a driver that would work with this device.
+SUBSYSTEM=="pci", ENV{ID_PCI_CLASS_FROM_DATABASE}=="Display controller", \
+ ENV{DRIVER}=="", IMPORT{cmdline}="nomodeset", TAG+="seat", TAG+="master-of-seat"
+
+# Synthesize a seat for graphic devices without DRM and that fall back to fb
+# device instead. Such HWs are listed in hwdb.
+SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", ATTRS{modalias}=="?*", IMPORT{builtin}="hwdb fb:$attr{modalias}"
+ENV{ID_TAG_MASTER_OF_SEAT}=="1", TAG+="master-of-seat"
+
+SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat"
+
+# Allow individual USB ports to be assigned to a seat
+SUBSYSTEM=="usb", ATTR{bDeviceClass}=="00", TAG+="seat"
+
+# Allow USB hubs (and all downstream ports) to be assigned to a seat
+SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
+
+# 'Plugable' USB hub, sound, network, graphics adapter
+SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="000[13]", ENV{ID_AUTOSEAT}="1"
+
+# qemu (version 2.4+) has a PCI-PCI bridge (-device pci-bridge-seat) to group
+# devices belonging to one seat. See:
+# http://git.qemu.org/?p=qemu.git;a=blob;f=docs/multiseat.txt
+SUBSYSTEM=="pci", ATTR{vendor}=="0x1b36", ATTR{device}=="0x000a", TAG+="seat", ENV{ID_AUTOSEAT}="1"
+
+# Mimo 720, with integrated USB hub, displaylink graphics, and e2i
+# touchscreen. This device carries no proper VID/PID in the USB hub,
+# but it does carry good ID data in the graphics component, hence we
+# check it from the parent. There's a bit of a race here however,
+# given that the child devices might not exist yet at the time this
+# rule is executed. To work around this we'll trigger the parent from
+# the child if we notice that the parent wasn't recognized yet.
+
+# Match parent
+{% raw -%}
+SUBSYSTEM=="usb", ATTR{idVendor}=="058f", ATTR{idProduct}=="6254", \
+ ATTR{%k.2/idVendor}=="17e9", ATTR{%k.2/idProduct}=="401a", ATTR{%k.2/product}=="mimo inc", \
+ ENV{ID_AUTOSEAT}="1", ENV{ID_AVOID_LOOP}="1"
+{% endraw %}
+
+# Match child, look for parent's ID_AVOID_LOOP
+SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \
+ ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \
+ IMPORT{parent}="ID_AVOID_LOOP"
+
+# Match child, retrigger parent
+SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \
+ ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \
+ ENV{ID_AVOID_LOOP}=="", \
+ RUN+="{{ROOTBINDIR}}/udevadm trigger --parent-match=%p/.."
+
+TAG=="seat", ENV{ID_PATH}=="", IMPORT{builtin}="path_id"
+TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH_TAG}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}"
+
+SUBSYSTEM=="input", ATTR{name}=="Wiebetech LLC Wiebetech", RUN+="{{ROOTBINDIR}}/loginctl lock-sessions"
+
+LABEL="seat_end"
diff --git a/rules.d/73-seat-late.rules.in b/rules.d/73-seat-late.rules.in
new file mode 100644
index 0000000..7cda2b0
--- /dev/null
+++ b/rules.d/73-seat-late.rules.in
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+ACTION=="remove", GOTO="seat_late_end"
+
+ENV{ID_SEAT}=="", ENV{ID_AUTOSEAT}=="1", ENV{ID_FOR_SEAT}!="", ENV{ID_SEAT}="seat-$env{ID_FOR_SEAT}"
+ENV{ID_SEAT}=="", IMPORT{parent}="ID_SEAT"
+
+ENV{ID_SEAT}!="", TAG+="$env{ID_SEAT}"
+{% if HAVE_ACL %}
+TAG=="uaccess", ENV{MAJOR}!="", RUN{builtin}+="uaccess"
+{% endif %}
+
+LABEL="seat_late_end"
diff --git a/rules.d/75-net-description.rules b/rules.d/75-net-description.rules
new file mode 100644
index 0000000..7e62f8b
--- /dev/null
+++ b/rules.d/75-net-description.rules
@@ -0,0 +1,14 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="net_end"
+SUBSYSTEM!="net", GOTO="net_end"
+
+IMPORT{builtin}="net_id"
+
+SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
+SUBSYSTEMS=="usb", GOTO="net_end"
+
+SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
+SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci"
+
+LABEL="net_end"
diff --git a/rules.d/75-probe_mtd.rules b/rules.d/75-probe_mtd.rules
new file mode 100644
index 0000000..8848aee
--- /dev/null
+++ b/rules.d/75-probe_mtd.rules
@@ -0,0 +1,7 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add", GOTO="mtd_probe_end"
+
+KERNEL=="mtd*ro", IMPORT{program}="mtd_probe $devnode"
+
+LABEL="mtd_probe_end"
diff --git a/rules.d/78-sound-card.rules b/rules.d/78-sound-card.rules
new file mode 100644
index 0000000..f2fc277
--- /dev/null
+++ b/rules.d/78-sound-card.rules
@@ -0,0 +1,96 @@
+# do not edit this file, it will be overwritten on update
+
+SUBSYSTEM!="sound", GOTO="sound_end"
+
+ACTION=="add|change", KERNEL=="controlC*", ATTR{../uevent}="change"
+ACTION!="change", GOTO="sound_end"
+
+# Ok, we probably need a little explanation here for what the two lines above
+# are good for.
+#
+# The story goes like this: when ALSA registers a new sound card it emits a
+# series of 'add' events to userspace, for the main card device and for all the
+# child device nodes that belong to it. udev relays those to applications,
+# however only maintains the order between father and child, but not between
+# the siblings. The control device node creation can be used as synchronization
+# point. All other devices that belong to a card are created in the kernel
+# before it. However unfortunately due to the fact that siblings are forwarded
+# out of order by udev this fact is lost to applications.
+#
+# OTOH before an application can open a device it needs to make sure that all
+# its device nodes are completely created and set up.
+#
+# As a workaround for this issue we have added the udev rule above which will
+# generate a 'change' event on the main card device from the 'add' event of the
+# card's control device. Due to the ordering semantics of udev this event will
+# only be relayed after all child devices have finished processing properly.
+# When an application needs to listen for appearing devices it can hence look
+# for 'change' events only, and ignore the actual 'add' events.
+#
+# When the application is initialized at the same time as a device is plugged
+# in it may need to figure out if the 'change' event has already been triggered
+# or not for a card. To find that out we store the flag environment variable
+# SOUND_INITIALIZED on the device which simply tells us if the card 'change'
+# event has already been processed.
+
+KERNEL!="card*", GOTO="sound_end"
+
+ENV{SOUND_INITIALIZED}="1"
+
+IMPORT{builtin}="hwdb"
+SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
+SUBSYSTEMS=="usb", GOTO="skip_pci"
+
+SUBSYSTEMS=="firewire", ATTRS{guid}=="?*", \
+ ENV{ID_BUS}="firewire", ENV{ID_SERIAL}="$attr{guid}", ENV{ID_SERIAL_SHORT}="$attr{guid}", \
+ ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{model}", \
+ ENV{ID_VENDOR}="$attr{vendor_name}", ENV{ID_MODEL}="$attr{model_name}"
+SUBSYSTEMS=="firewire", GOTO="skip_pci"
+
+SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
+SUBSYSTEMS=="pci", GOTO="skip_pci"
+
+# If we reach here, the device nor any of its parents are USB/PCI/firewire bus devices.
+# If we now find a parent that is a platform device, assume that we're working with
+# an internal sound card.
+SUBSYSTEMS=="platform", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end"
+
+LABEL="skip_pci"
+
+# Define ID_ID if ID_BUS and ID_SERIAL are set. This will work for both
+# USB and firewire.
+ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}"
+ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}"
+
+IMPORT{builtin}="path_id"
+
+# The values used here for $SOUND_FORM_FACTOR and $SOUND_CLASS should be kept
+# in sync with those defined for PulseAudio's src/pulse/proplist.h
+# PA_PROP_DEVICE_FORM_FACTOR, PA_PROP_DEVICE_CLASS properties.
+
+# If the first PCM device of this card has the pcm class 'modem', then the card is a modem
+ATTR{pcmC%nD0p/pcm_class}=="modem", ENV{SOUND_CLASS}="modem", GOTO="sound_end"
+
+# Identify cards on the internal PCI bus as internal
+SUBSYSTEMS=="pci", DEVPATH=="*/0000:00:??.?/sound/*", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end"
+
+# Devices that also support Image/Video interfaces are most likely webcams
+SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACES}=="*:0e????:*", ENV{SOUND_FORM_FACTOR}="webcam", GOTO="sound_end"
+
+# Matching on the model strings is a bit ugly, I admit
+ENV{ID_MODEL}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end"
+ENV{ID_MODEL_FROM_DATABASE}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end"
+
+ENV{ID_MODEL}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end"
+ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end"
+
+ENV{ID_MODEL}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end"
+ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end"
+
+ENV{ID_MODEL}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end"
+ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end"
+
+ENV{ID_MODEL}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end"
+ENV{ID_MODEL_FROM_DATABASE}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end"
+
+LABEL="sound_end"
diff --git a/rules.d/80-drivers.rules b/rules.d/80-drivers.rules
new file mode 100644
index 0000000..4bf942f
--- /dev/null
+++ b/rules.d/80-drivers.rules
@@ -0,0 +1,13 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION!="add", GOTO="drivers_end"
+
+ENV{MODALIAS}=="?*", RUN{builtin}+="kmod load"
+SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}+="kmod load tifm_sd"
+SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN{builtin}+="kmod load tifm_ms"
+SUBSYSTEM=="memstick", RUN{builtin}+="kmod load ms_block mspro_block"
+SUBSYSTEM=="i2o", RUN{builtin}+="kmod load i2o_block"
+SUBSYSTEM=="module", KERNEL=="parport_pc", RUN{builtin}+="kmod load ppdev"
+KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", RUN{builtin}+="kmod load sm_ftl"
+
+LABEL="drivers_end"
diff --git a/rules.d/80-net-setup-link.rules b/rules.d/80-net-setup-link.rules
new file mode 100644
index 0000000..bafc3fb
--- /dev/null
+++ b/rules.d/80-net-setup-link.rules
@@ -0,0 +1,13 @@
+# do not edit this file, it will be overwritten on update
+
+SUBSYSTEM!="net", GOTO="net_setup_link_end"
+
+IMPORT{builtin}="path_id"
+
+ACTION=="remove", GOTO="net_setup_link_end"
+
+IMPORT{builtin}="net_setup_link"
+
+NAME=="", ENV{ID_NET_NAME}!="", NAME="$env{ID_NET_NAME}"
+
+LABEL="net_setup_link_end"
diff --git a/rules.d/81-net-dhcp.rules b/rules.d/81-net-dhcp.rules
new file mode 100644
index 0000000..2ef25ba
--- /dev/null
+++ b/rules.d/81-net-dhcp.rules
@@ -0,0 +1,14 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="net_dhcp_end"
+SUBSYSTEM!="net", GOTO="net_dhcp_end"
+
+# Network interfaces requiring DHCPOFFER messages to be broadcast
+# must set ID_NET_DHCP_BROADCAST to "1". This property will be
+# checked by the networkd DHCP4 client to set the DHCP option
+
+# s390 ccwgroup interfaces in layer3 mode need broadcast DHCPOFFER
+# using the link driver to detect this condition
+ENV{ID_NET_DRIVER}=="qeth_l3", ENV{ID_NET_DHCP_BROADCAST}="1"
+
+LABEL="net_dhcp_end"
diff --git a/rules.d/90-vconsole.rules.in b/rules.d/90-vconsole.rules.in
new file mode 100644
index 0000000..8457854
--- /dev/null
+++ b/rules.d/90-vconsole.rules.in
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+# Each vtcon keeps its own state of fonts.
+#
+ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", RUN+="{{ROOTLIBEXECDIR}}/systemd-vconsole-setup"
diff --git a/rules.d/99-systemd.rules.in b/rules.d/99-systemd.rules.in
new file mode 100644
index 0000000..7b50409
--- /dev/null
+++ b/rules.d/99-systemd.rules.in
@@ -0,0 +1,88 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+ACTION=="remove", GOTO="systemd_end"
+
+SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*|xvc*|hvsi*|ttysclp*|sclp_line*|3270/tty[0-9]*", TAG+="systemd"
+KERNEL=="vport*", TAG+="systemd"
+
+SUBSYSTEM=="ptp", TAG+="systemd"
+
+SUBSYSTEM=="ubi", TAG+="systemd"
+
+SUBSYSTEM=="block", TAG+="systemd"
+
+# We can't make any conclusions about suspended DM devices so let's just import previous SYSTEMD_READY state and skip other rules
+SUBSYSTEM=="block", ENV{DM_SUSPENDED}=="1", IMPORT{db}="SYSTEMD_READY"
+SUBSYSTEM=="block", ENV{DM_SUSPENDED}=="1", GOTO="systemd_end"
+
+SUBSYSTEM=="block", ACTION=="add", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
+
+# Ignore encrypted devices with no identified superblock on it, since
+# we are probably still calling mke2fs or mkswap on it.
+SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0"
+
+# Explicitly set SYSTEMD_READY=1 for DM devices that don't have it set yet, so that we always have something to import above
+SUBSYSTEM=="block", ENV{DM_UUID}=="?*", ENV{SYSTEMD_READY}=="", ENV{SYSTEMD_READY}="1"
+
+# add symlink to GPT root disk
+SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT}=="1", ENV{ID_FS_TYPE}!="crypto_LUKS", SYMLINK+="gpt-auto-root"
+SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT}=="1", ENV{ID_FS_TYPE}=="crypto_LUKS", SYMLINK+="gpt-auto-root-luks"
+SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{DM_NAME}=="root", SYMLINK+="gpt-auto-root"
+
+# Ignore raid devices that are not yet assembled and started
+SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0"
+SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0"
+
+# Ignore loop devices that don't have any file attached
+SUBSYSTEM=="block", KERNEL=="loop[0-9]*", ENV{DEVTYPE}=="disk", TEST!="loop/backing_file", ENV{SYSTEMD_READY}="0"
+
+# Ignore nbd devices until the PID file exists (which signals a connected device)
+SUBSYSTEM=="block", KERNEL=="nbd*", ENV{DEVTYPE}=="disk", TEST!="pid", ENV{SYSTEMD_READY}="0"
+
+# We need a hardware independent way to identify network devices. We
+# use the /sys/subsystem/ path for this. Kernel "bus" and "class" names
+# should be treated as one namespace, like udev handles it. This is mostly
+# just an identification string for systemd, so whether the path actually is
+# accessible or not does not matter as long as it is unique and in the
+# filesystem namespace.
+
+SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/$name"
+SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k", \
+ ENV{SYSTEMD_WANTS}+="bluetooth.target", ENV{SYSTEMD_USER_WANTS}+="bluetooth.target"
+
+ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target", ENV{SYSTEMD_USER_WANTS}+="smartcard.target"
+SUBSYSTEM=="sound", KERNEL=="controlC*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target", ENV{SYSTEMD_USER_WANTS}+="sound.target"
+
+SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target"
+SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target"
+SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target"
+
+SUBSYSTEM=="udc", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="usb-gadget.target"
+
+# Apply sysctl variables to network devices (and only to those) as they appear.
+ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="{{ROOTLIBEXECDIR}}/systemd-sysctl --prefix=/net/ipv4/conf/$name --prefix=/net/ipv4/neigh/$name --prefix=/net/ipv6/conf/$name --prefix=/net/ipv6/neigh/$name"
+
+{% if ENABLE_BACKLIGHT %}
+# Pull in backlight save/restore for all backlight devices and
+# keyboard backlights
+SUBSYSTEM=="backlight", TAG+="systemd", IMPORT{builtin}="path_id", ENV{SYSTEMD_WANTS}+="systemd-backlight@backlight:$name.service"
+SUBSYSTEM=="leds", KERNEL=="*kbd_backlight*", TAG+="systemd", IMPORT{builtin}="path_id", ENV{SYSTEMD_WANTS}+="systemd-backlight@leds:$name.service"
+{% endif %}
+
+# Pull in rfkill save/restore for all rfkill devices
+SUBSYSTEM=="rfkill", ENV{SYSTEMD_RFKILL}="1"
+SUBSYSTEM=="rfkill", IMPORT{builtin}="path_id"
+SUBSYSTEM=="misc", KERNEL=="rfkill", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-rfkill.socket"
+
+# Asynchronously mount file systems implemented by these modules as soon as they are loaded.
+SUBSYSTEM=="module", KERNEL=="fuse", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-fs-fuse-connections.mount"
+SUBSYSTEM=="module", KERNEL=="configfs", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-kernel-config.mount"
+
+LABEL="systemd_end"
diff --git a/rules.d/README b/rules.d/README
new file mode 100644
index 0000000..08edb4d
--- /dev/null
+++ b/rules.d/README
@@ -0,0 +1,8 @@
+Files in this directory contain configuration for systemd-udevd.service, a
+daemon that manages symlinks to device nodes, permissions of devices nodes,
+emits device events for userspace, and renames network interfaces.
+
+See man:udev(7) for an overview of the configuration file format, and
+man:systemd-udevd.service(8) for a description of service itself.
+
+Use 'systemd-analyze cat-config udev/rules.d' to display the effective config.
diff --git a/rules.d/meson.build b/rules.d/meson.build
new file mode 100644
index 0000000..cba9dd4
--- /dev/null
+++ b/rules.d/meson.build
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+install_data(
+ 'README',
+ install_dir : udevrulesdir)
+
+rules = [
+ [files('60-autosuspend.rules',
+ '60-block.rules',
+ '60-cdrom_id.rules',
+ '60-drm.rules',
+ '60-evdev.rules',
+ '60-fido-id.rules',
+ '60-infiniband.rules',
+ '60-input-id.rules',
+ '60-persistent-alsa.rules',
+ '60-persistent-input.rules',
+ '60-persistent-storage.rules',
+ '60-persistent-storage-tape.rules',
+ '60-persistent-v4l.rules',
+ '60-sensor.rules',
+ '60-serial.rules',
+ '70-camera.rules',
+ '70-joystick.rules',
+ '70-mouse.rules',
+ '70-touchpad.rules',
+ '75-net-description.rules',
+ '75-probe_mtd.rules',
+ '78-sound-card.rules',
+ '80-net-setup-link.rules',
+ '81-net-dhcp.rules',
+ )],
+
+ [files('80-drivers.rules'),
+ conf.get('HAVE_KMOD') == 1],
+
+ [files('70-memory.rules'),
+ dmi_arches.contains(host_machine.cpu_family())],
+
+ [files('70-power-switch.rules'),
+ enable_logind],
+]
+
+all_rules = []
+
+foreach tuple : rules
+ if tuple.length() == 1 or tuple[1]
+ install_data(tuple[0],
+ install_dir : udevrulesdir)
+ all_rules += tuple[0]
+ endif
+endforeach
+
+rules_in = [
+ ['50-udev-default.rules'],
+ ['64-btrfs.rules'],
+ ['99-systemd.rules'],
+
+ ['70-uaccess.rules', enable_logind and conf.get('HAVE_ACL') == 1],
+ ['71-seat.rules', enable_logind],
+ ['73-seat-late.rules', enable_logind],
+
+ ['90-vconsole.rules', conf.get('ENABLE_VCONSOLE') == 1],
+]
+
+foreach tuple : rules_in
+ want = tuple.length() == 1 or tuple[1]
+
+ rule = custom_target(
+ tuple[0],
+ input : tuple[0] + '.in',
+ output: tuple[0],
+ command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'],
+ install : want,
+ install_dir : udevrulesdir)
+
+ if want
+ all_rules += rule
+ endif
+endforeach