#define BLKID_FL_NOSCAN_DEV (1 << 4) /* do not scan this device */
#define BLKID_FL_MODIF_BUFF (1 << 5) /* cached buffers has been modified */
#define BLKID_FL_OPAL_LOCKED (1 << 6) /* OPAL device is locked (I/O errors) */
+#define BLKID_FL_OPAL_CHECKED (1 << 7) /* OPAL lock checked */
/* private per-probing flags */
#define BLKID_PROBE_FL_IGNORE_PT (1 << 1) /* ignore partition table */
* audio+data disks */
if (ret >= 0 || blkid_probe_is_cdrom(pr) || blkdid_probe_is_opal_locked(pr))
errno = 0;
-#ifdef HAVE_OPAL_GET_STATUS
- else {
- struct opal_status st = { };
-
- /* If the device is locked with OPAL, we'll fail to read with I/O
- * errors when probing deep into the block device. Do not return
- * an error, so that we can move on to different types of checks.*/
- ret = ioctl(pr->fd, IOC_OPAL_GET_STATUS, &st);
- if (ret == 0 && (st.flags & OPAL_FL_LOCKED)) {
- pr->flags |= BLKID_FL_OPAL_LOCKED;
- errno = 0;
- }
- }
-#endif
return NULL;
}
int blkdid_probe_is_opal_locked(blkid_probe pr)
{
+ if (!(pr->flags & BLKID_FL_OPAL_CHECKED)) {
+ pr->flags |= BLKID_FL_OPAL_CHECKED;
+
+#ifdef HAVE_OPAL_GET_STATUS
+ ssize_t ret;
+ struct opal_status st = { };
+ int errsv = errno;
+
+ /* If the device is locked with OPAL, we'll fail to read with I/O
+ * errors when probing deep into the block device. */
+ ret = ioctl(pr->fd, IOC_OPAL_GET_STATUS, &st);
+ if (ret == 0 && (st.flags & OPAL_FL_LOCKED)) {
+ pr->flags |= BLKID_FL_OPAL_LOCKED;
+ }
+
+ errno = errsv;
+#endif
+ }
+
return (pr->flags & BLKID_FL_OPAL_LOCKED);
}
#define LUKS_MAGIC "LUKS\xba\xbe"
#define LUKS_MAGIC_2 "SKUL\xba\xbe"
+#define LUKS2_HW_OPAL_SUBSYSTEM "HW-OPAL"
+
/* Offsets for secondary header (for scan if primary header is corrupted). */
#define LUKS2_HDR2_OFFSETS { 0x04000, 0x008000, 0x010000, 0x020000, \
0x40000, 0x080000, 0x100000, 0x200000, 0x400000 }
return BLKID_PROBE_NONE;
}
-static int probe_luks_opal(blkid_probe pr, const struct blkid_idmag *mag)
+static int probe_luks_opal(blkid_probe pr, const struct blkid_idmag *mag __attribute__((__unused__)))
{
+ struct luks2_phdr *header;
+ int version;
+
+ header = (struct luks2_phdr *) blkid_probe_get_buffer(pr, 0, sizeof(struct luks2_phdr));
+ if (!header)
+ return errno ? -errno : BLKID_PROBE_NONE;
+
+ if (!luks_valid(header, LUKS_MAGIC, 0))
+ return BLKID_PROBE_NONE;
+
+ version = be16_to_cpu(header->version);
+
+ if (version != 2)
+ return BLKID_PROBE_NONE;
+
+ if (memcmp(header->subsystem, LUKS2_HW_OPAL_SUBSYSTEM, sizeof(LUKS2_HW_OPAL_SUBSYSTEM)) != 0)
+ return BLKID_PROBE_NONE;
+
if (!blkdid_probe_is_opal_locked(pr))
return BLKID_PROBE_NONE;
- return probe_luks(pr, mag);
+ /* Locked drive with LUKS2 HW OPAL encryption, finish probe now */
+ return luks_attributes(pr, header, 0);
}
const struct blkid_idinfo luks_idinfo =