mirror of
https://src.fedoraproject.org/rpms/grub2.git
synced 2024-12-01 00:48:18 +00:00
6b2dd0f731
Signed-off-by: Peter Jones <pjones@redhat.com>
188 lines
5.2 KiB
Diff
188 lines
5.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.rohar@gmail.com>
|
|
Date: Thu, 22 Jun 2017 14:42:16 +0200
|
|
Subject: [PATCH] * grub-core/fs/udf.c: Add support for UUID
|
|
|
|
Use same algorithm as in libblkid from util-linux v2.30.
|
|
|
|
1. Take first 16 bytes from UTF-8 encoded string of VolumeSetIdentifier
|
|
2. If all bytes are hexadecimal digits, convert to lowercase and use as UUID
|
|
3. If first 8 bytes are not all hexadecimal digits, convert those 8 bytes
|
|
to their hexadecimal representation, resulting in 16 bytes for UUID
|
|
4. Otherwise, compose UUID from two parts:
|
|
1. part: converted first 8 bytes (which are hexadecimal digits) to lowercase
|
|
2. part: encoded following 4 bytes to their hexadecimal representation (16 bytes)
|
|
|
|
So UUID would always have 16 hexadecimal digits in lowercase variant.
|
|
|
|
According to UDF specification, first 16 Unicode characters of
|
|
VolumeSetIdentifier should be unique value and first 8 should be
|
|
hexadecimal characters.
|
|
|
|
In most cases all 16 characters are hexadecimal, but e.g. MS Windows
|
|
format.exe set only first 8 as hexadecimal and remaining as fixed
|
|
(non-unique) which violates specification.
|
|
---
|
|
grub-core/fs/udf.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 120 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
|
|
index 2587456336e..00a16098b47 100644
|
|
--- a/grub-core/fs/udf.c
|
|
+++ b/grub-core/fs/udf.c
|
|
@@ -321,6 +321,32 @@ struct grub_udf_partmap
|
|
};
|
|
} GRUB_PACKED;
|
|
|
|
+struct grub_udf_pvd
|
|
+{
|
|
+ struct grub_udf_tag tag;
|
|
+ grub_uint32_t seq_num;
|
|
+ grub_uint32_t pvd_num;
|
|
+ grub_uint8_t ident[32];
|
|
+ grub_uint16_t vol_seq_num;
|
|
+ grub_uint16_t max_vol_seq_num;
|
|
+ grub_uint16_t interchange_level;
|
|
+ grub_uint16_t max_interchange_level;
|
|
+ grub_uint32_t charset_list;
|
|
+ grub_uint32_t max_charset_list;
|
|
+ grub_uint8_t volset_ident[128];
|
|
+ struct grub_udf_charspec desc_charset;
|
|
+ struct grub_udf_charspec expl_charset;
|
|
+ struct grub_udf_extent_ad vol_abstract;
|
|
+ struct grub_udf_extent_ad vol_copyright;
|
|
+ struct grub_udf_regid app_ident;
|
|
+ struct grub_udf_timestamp recording_time;
|
|
+ struct grub_udf_regid imp_ident;
|
|
+ grub_uint8_t imp_use[64];
|
|
+ grub_uint32_t pred_vds_loc;
|
|
+ grub_uint16_t flags;
|
|
+ grub_uint8_t reserved[22];
|
|
+} GRUB_PACKED;
|
|
+
|
|
struct grub_udf_lvd
|
|
{
|
|
struct grub_udf_tag tag;
|
|
@@ -348,6 +374,7 @@ struct grub_udf_aed
|
|
struct grub_udf_data
|
|
{
|
|
grub_disk_t disk;
|
|
+ struct grub_udf_pvd pvd;
|
|
struct grub_udf_lvd lvd;
|
|
struct grub_udf_pd pds[GRUB_UDF_MAX_PDS];
|
|
struct grub_udf_partmap *pms[GRUB_UDF_MAX_PMS];
|
|
@@ -692,7 +719,17 @@ grub_udf_mount (grub_disk_t disk)
|
|
}
|
|
|
|
tag.tag_ident = U16 (tag.tag_ident);
|
|
- if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD)
|
|
+ if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PVD)
|
|
+ {
|
|
+ if (grub_disk_read (disk, block << lbshift, 0,
|
|
+ sizeof (struct grub_udf_pvd),
|
|
+ &data->pvd))
|
|
+ {
|
|
+ grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
|
|
+ goto fail;
|
|
+ }
|
|
+ }
|
|
+ else if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD)
|
|
{
|
|
if (data->npd >= GRUB_UDF_MAX_PDS)
|
|
{
|
|
@@ -1225,6 +1262,87 @@ grub_udf_label (grub_device_t device, char **label)
|
|
return grub_errno;
|
|
}
|
|
|
|
+static char *
|
|
+gen_uuid_from_volset (char *volset_ident)
|
|
+{
|
|
+ grub_size_t i;
|
|
+ grub_size_t len;
|
|
+ grub_size_t nonhexpos;
|
|
+ grub_uint8_t buf[17];
|
|
+ char *uuid;
|
|
+
|
|
+ len = grub_strlen (volset_ident);
|
|
+ if (len < 8)
|
|
+ return NULL;
|
|
+
|
|
+ uuid = grub_malloc (17);
|
|
+ if (!uuid)
|
|
+ return NULL;
|
|
+
|
|
+ if (len > 16)
|
|
+ len = 16;
|
|
+
|
|
+ grub_memset (buf, 0, sizeof (buf));
|
|
+ grub_memcpy (buf, volset_ident, len);
|
|
+
|
|
+ nonhexpos = 16;
|
|
+ for (i = 0; i < 16; ++i)
|
|
+ {
|
|
+ if (!grub_isxdigit (buf[i]))
|
|
+ {
|
|
+ nonhexpos = i;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (nonhexpos < 8)
|
|
+ {
|
|
+ grub_snprintf (uuid, 17, "%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
+ buf[0], buf[1], buf[2], buf[3],
|
|
+ buf[4], buf[5], buf[6], buf[7]);
|
|
+ }
|
|
+ else if (nonhexpos < 16)
|
|
+ {
|
|
+ for (i = 0; i < 8; ++i)
|
|
+ uuid[i] = grub_tolower (buf[i]);
|
|
+ grub_snprintf (uuid+8, 9, "%02x%02x%02x%02x",
|
|
+ buf[8], buf[9], buf[10], buf[11]);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ for (i = 0; i < 16; ++i)
|
|
+ uuid[i] = grub_tolower (buf[i]);
|
|
+ uuid[16] = 0;
|
|
+ }
|
|
+
|
|
+ return uuid;
|
|
+}
|
|
+
|
|
+static grub_err_t
|
|
+grub_udf_uuid (grub_device_t device, char **uuid)
|
|
+{
|
|
+ char *volset_ident;
|
|
+ struct grub_udf_data *data;
|
|
+ data = grub_udf_mount (device->disk);
|
|
+
|
|
+ if (data)
|
|
+ {
|
|
+ volset_ident = read_dstring (data->pvd.volset_ident, sizeof (data->pvd.volset_ident));
|
|
+ if (volset_ident)
|
|
+ {
|
|
+ *uuid = gen_uuid_from_volset (volset_ident);
|
|
+ grub_free (volset_ident);
|
|
+ }
|
|
+ else
|
|
+ *uuid = 0;
|
|
+ grub_free (data);
|
|
+ }
|
|
+ else
|
|
+ *uuid = 0;
|
|
+
|
|
+ return grub_errno;
|
|
+}
|
|
+
|
|
static struct grub_fs grub_udf_fs = {
|
|
.name = "udf",
|
|
.dir = grub_udf_dir,
|
|
@@ -1232,6 +1350,7 @@ static struct grub_fs grub_udf_fs = {
|
|
.read = grub_udf_read,
|
|
.close = grub_udf_close,
|
|
.label = grub_udf_label,
|
|
+ .uuid = grub_udf_uuid,
|
|
#ifdef GRUB_UTIL
|
|
.reserved_first_sector = 1,
|
|
.blocklist_install = 1,
|