SUBSYSTEM=="tpmrm", KERNEL=="tpmrm[0-9]*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="tpm2.target"
SUBSYSTEM=="tpm", KERNEL=="tpm[0-9]*", TAG+="systemd"
-# If the GPT sector size doesn't match the device's native sector size (e.g. 512-byte GPT on a
-# 2048-byte CD-ROM booted via El Torito), trigger a loop device to re-expose it with the correct
-# sector size so the kernel can parse the partition table.
-SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT_DISK_SECTOR_SIZE_MISMATCH}=="1", \
+# If the kernel cannot parse the GPT partition table on the boot disk (e.g. due to a sector size
+# mismatch on a CD-ROM booted via El Torito, or because the device does not support partition
+# scanning), trigger a loop device to expose the partitions.
+SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT_DISK_NEEDS_LOOP}=="1", \
ENV{SYSTEMD_WANTS}+="systemd-loop@.service"
LABEL="systemd_end"
return 0;
}
-static int probe_gpt_sector_size_mismatch(UdevEvent *event, int fd) {
+static int probe_gpt_boot_disk_needs_loop(UdevEvent *event, int fd) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
* check if this is the boot disk by comparing GPT partition UUIDs with the ESP/XBOOTLDR UUID
* exported by the boot loader. If it matches, set a property so that udev rules can set up a
* loop device with the correct sector size — the kernel can't parse the partition table itself
- * in this case. */
+ * in this case.
+ *
+ * Even if the sector sizes match, if the device does not support partition scanning (e.g. some
+ * CD-ROM drives), the kernel still can't parse the partition table. In that case, if the disk
+ * contains the ESP we booted from, we still need a loop device to expose the partitions. */
_cleanup_free_ void *entries = NULL;
uint32_t n_entries, entry_size;
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get device sector size: %m");
- if ((uint32_t) gpt_ssz == device_ssz)
- return 0;
+ bool sector_size_mismatch = (uint32_t) gpt_ssz != device_ssz;
+
+ if (!sector_size_mismatch) {
+ r = blockdev_partscan_enabled(dev);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to check if partition scanning is enabled: %m");
+ if (r > 0)
+ return 0;
+ }
- log_device_debug(dev, "GPT sector size %zi does not match device sector size %" PRIu32 ".",
- gpt_ssz, device_ssz);
+ if (sector_size_mismatch)
+ log_device_debug(dev, "GPT sector size %zi does not match device sector size %" PRIu32 ".",
+ gpt_ssz, device_ssz);
+ else
+ log_device_debug(dev, "Device does not support partition scanning.");
sd_id128_t loader_part_uuid;
r = efi_loader_get_device_part_uuid(&loader_part_uuid);
if (!sd_id128_equal(efi_guid_to_id128(entry->unique_partition_guid), loader_part_uuid))
continue;
- log_device_debug(dev, "Found boot partition (ESP/XBOOTLDR) on disk with sector size mismatch.");
- udev_builtin_add_property(event, "ID_PART_GPT_AUTO_ROOT_DISK_SECTOR_SIZE_MISMATCH", "1");
+ log_device_debug(dev, "Found boot partition (ESP/XBOOTLDR) on disk where kernel cannot scan partitions.");
+ udev_builtin_add_property(event, "ID_PART_GPT_AUTO_ROOT_DISK_NEEDS_LOOP", "1");
udev_builtin_add_propertyf(event, "ID_PART_GPT_SECTOR_SIZE", "%zi", gpt_ssz);
- return 1; /* mismatch detected and handled */
+ return 1; /* boot disk needs loop device */
}
return 0;
}
if (offset == 0) {
- r = probe_gpt_sector_size_mismatch(event, fd);
+ r = probe_gpt_boot_disk_needs_loop(event, fd);
if (r > 0)
return 0;
}