Android 4.4 -- blkid命令支持exfat格式U盘显示信息(UUID、LABEL等)

23 篇文章 4 订阅

一、前言

最近客户反馈一个问题,就是Android系统的机顶盒插上exfat格式的U盘后,获取不到UUID这个信息。
/system/vold/中已经添加对exfat格式U盘的支持,并且通过df命令能够看到U盘已经挂载上,但是执行blkid时,并未显示exfat格式U盘信息。

二、问题分析

  1. 执行blkid /dev/block/sda1命令(sda1U盘挂载点),若U盘格式为vfat的,则能够正常显示,若U盘格式为exfat的,则不能显示。
  2. 问题应该出在blkid命令不健全导致的,可以补充一部分代码,让其能够显示出来。

三、解决方法

  1. 需要修改的代码在external/e2fsprogs/lib/blkid路径下。
  2. e2fsprogs是一个Ext2(及Ext3/4)文件系统工具(Ext2Filesystems Utilities),它包含了诸如创建、修复、配置、调试ext2文件系统等的标准工具。e2fsprogs是开放源代码软件 ,遵从GPLv2LGPLv2
  3. codechina上有e2fsprogs的开源代码,里面已经添加对exfat的相应支持,我们可以在这个里面搜寻相应的修改同步过来。
  4. 里面主要修改了两个文件,probe.cprobe.h

四、代码修改

下面是针对exfat格式的设备修改的,代码如下:

From 05cf6cbb92bf6d65ef0480053ddcc4a625f0e86b Mon Sep 17 00:00:00 2001
From: Amosstan
Date: Tue, 6 Jul 2021 16:02:38 +0800
Subject: [PATCH] aaa

---
 external/e2fsprogs/lib/blkid/probe.c | 131 +++++++++++++++++++++++++++
 external/e2fsprogs/lib/blkid/probe.h |  41 +++++++++
 2 files changed, 172 insertions(+)

diff --git a/external/e2fsprogs/lib/blkid/probe.c b/external/e2fsprogs/lib/blkid/probe.c
index 1867129..36f5ca3 100644
--- a/external/e2fsprogs/lib/blkid/probe.c
+++ b/external/e2fsprogs/lib/blkid/probe.c
@@ -1158,6 +1158,38 @@ static void unicode_16be_to_utf8(unsigned char *str, int out_len,
 	str[j] = '\0';
 }
 
+static void unicode_16le_to_utf8(unsigned char *str, int out_len,
+				 const unsigned char *buf, int in_len)
+{
+	int i, j;
+	unsigned int c;
+
+	for (i = j = 0; i + 2 <= in_len; i += 2) {
+		c = (buf[i+1] << 8) | buf[i];
+		if (c == 0) {
+			str[j] = '\0';
+			break;
+		} else if (c < 0x80) {
+			if (j+1 >= out_len)
+				break;
+			str[j++] = (unsigned char) c;
+		} else if (c < 0x800) {
+			if (j+2 >= out_len)
+				break;
+			str[j++] = (unsigned char) (0xc0 | (c >> 6));
+			str[j++] = (unsigned char) (0x80 | (c & 0x3f));
+		} else {
+			if (j+3 >= out_len)
+				break;
+			str[j++] = (unsigned char) (0xe0 | (c >> 12));
+			str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f));
+			str[j++] = (unsigned char) (0x80 | (c & 0x3f));
+		}
+	}
+	str[j] = '\0';
+}
+
+
 static int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)),
 			 struct blkid_magic *id __BLKID_ATTR((unused)),
 			 unsigned char *buf)
@@ -1383,6 +1415,104 @@ static int probe_btrfs(struct blkid_probe *probe,
 	set_uuid(probe->dev, bs->fsid, 0);
 	return 0;
 }
+
+static uint64_t exfat_block_to_offset(const struct exfat_super_block *sb,
+                                      uint64_t block)
+{
+    return block << sb->block_bits;
+}
+
+static uint64_t exfat_cluster_to_block(const struct exfat_super_block *sb,
+                                       uint32_t cluster)
+{
+    return sb->cluster_block_start +
+            ((uint64_t)(cluster - EXFAT_FIRST_DATA_CLUSTER) << sb->bpc_bits);
+}
+
+static uint64_t exfat_cluster_to_offset(const struct exfat_super_block *sb,
+                                        uint32_t cluster)
+{
+    return exfat_block_to_offset(sb, exfat_cluster_to_block(sb, cluster));
+}
+
+static uint32_t exfat_next_cluster(struct blkid_probe *probe,
+                                   const struct exfat_super_block *sb,
+                                   uint32_t cluster)
+{
+    uint32_t *next;
+    uint64_t offset;
+
+    offset = exfat_block_to_offset(sb, sb->fat_block_start)
+            + (uint64_t) cluster * sizeof (cluster);
+    next = (uint32_t *)get_buffer(probe, offset, sizeof (uint32_t));
+
+    return next ? *next : 0;
+}
+
+static struct exfat_entry_label *find_exfat_entry_label(
+    struct blkid_probe *probe, const struct exfat_super_block *sb)
+{
+    uint32_t cluster = sb->rootdir_cluster;
+    uint64_t offset = exfat_cluster_to_offset(sb, cluster);
+    uint8_t *entry;
+    const size_t max_iter = 10000;
+    size_t i = 0;
+
+    for (; i < max_iter; ++i) {
+        entry = (uint8_t *)get_buffer(probe, offset, EXFAT_ENTRY_SIZE);
+        if (!entry)
+            return NULL;
+        if (entry[0] == EXFAT_ENTRY_EOD)
+            return NULL;
+        if (entry[0] == EXFAT_ENTRY_LABEL)
+            return (struct exfat_entry_label*) entry;
+
+        offset += EXFAT_ENTRY_SIZE;
+        if (offset % CLUSTER_SIZE(sb) == 0) {
+            cluster = exfat_next_cluster(probe, sb, cluster);
+            if (cluster < EXFAT_FIRST_DATA_CLUSTER)
+                return NULL;
+            if (cluster > EXFAT_LAST_DATA_CLUSTER)
+                return NULL;
+            offset = exfat_cluster_to_offset(sb, cluster);
+        }
+    }
+
+    return NULL;
+}
+
+static int probe_exfat(struct blkid_probe *probe,
+		       struct blkid_magic *id __BLKID_ATTR((unused)),
+                       unsigned char *buf)
+{
+    struct exfat_super_block *sb;
+    struct exfat_entry_label *label;
+    char uuid[40];
+
+    sb = (struct exfat_super_block *)buf;
+    if (!sb || CLUSTER_SIZE(sb) == 0) {
+        DBG(DEBUG_PROBE, printf("bad exfat superblock.\n"));
+        return errno ? - errno : 1;
+    }
+
+    label = find_exfat_entry_label(probe, sb);
+    if (label) {
+        unsigned char utf8_label[128];
+        unicode_16le_to_utf8(utf8_label, sizeof(utf8_label), label->name, label->length * 2);
+        blkid_set_tag(probe->dev, "LABEL", (char *) utf8_label, 0);
+    } else {
+        blkid_set_tag(probe->dev, "LABEL", "disk", 4);
+    }
+
+    memset(uuid, 0, sizeof (uuid));
+    snprintf(uuid, sizeof (uuid), "%02hhX%02hhX-%02hhX%02hhX",
+             sb->volume_serial[3], sb->volume_serial[2],
+             sb->volume_serial[1], sb->volume_serial[0]);
+    blkid_set_tag(probe->dev, "UUID", uuid, strlen(uuid));
+
+    return 0;
+}
+
 /*
  * Various filesystem magics that we can check for.  Note that kboff and
  * sboff are in kilobytes and bytes respectively.  All magics are in
@@ -1482,6 +1612,7 @@ static struct blkid_magic type_array[] = {
   { "lvm2pv",	 1,  0x018,  8, "LVM2 001",		probe_lvm2 },
   { "lvm2pv",	 1,  0x218,  8, "LVM2 001",		probe_lvm2 },
   { "btrfs",	 64,  0x40,  8, "_BHRfS_M",		probe_btrfs },
+  { "exfat",     0,      3,  8, "EXFAT   ",             probe_exfat },
   {   NULL,	 0,	 0,  0, NULL,			NULL }
 };
 
diff --git a/external/e2fsprogs/lib/blkid/probe.h b/external/e2fsprogs/lib/blkid/probe.h
index 37fc9c0..2c6acea 100644
--- a/external/e2fsprogs/lib/blkid/probe.h
+++ b/external/e2fsprogs/lib/blkid/probe.h
@@ -14,6 +14,8 @@
 #ifndef _BLKID_PROBE_H
 #define _BLKID_PROBE_H
 
+#include <stdint.h>
+
 #include <blkid/blkid_types.h>
 
 struct blkid_magic;
@@ -725,6 +727,45 @@ struct btrfs_super_block {
 	__u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
 } __attribute__ ((__packed__));
 
+struct exfat_super_block {
+    uint8_t jump[3];
+    uint8_t oem_name[8];
+    uint8_t __unused1[53];
+    uint64_t block_start;
+    uint64_t block_count;
+    uint32_t fat_block_start;
+    uint32_t fat_block_count;
+    uint32_t cluster_block_start;
+    uint32_t cluster_count;
+    uint32_t rootdir_cluster;
+    uint8_t volume_serial[4];
+    struct {
+        uint8_t vermin;
+        uint8_t vermaj;
+    } version;
+    uint16_t volume_state;
+    uint8_t block_bits;
+    uint8_t bpc_bits;
+    uint8_t fat_count;
+    uint8_t drive_no;
+    uint8_t allocated_percent;
+}  __attribute__ ((__packed__));
+
+struct exfat_entry_label {
+    uint8_t type;
+    uint8_t length;
+    uint8_t name[30];
+} __attribute__ ((__packed__));
+
+#define BLOCK_SIZE(sb)   (1 << (sb)->block_bits)
+#define CLUSTER_SIZE(sb) (BLOCK_SIZE(sb) << (sb)->bpc_bits)
+
+#define EXFAT_FIRST_DATA_CLUSTER 2
+#define EXFAT_LAST_DATA_CLUSTER  0xffffff6
+#define EXFAT_ENTRY_SIZE         32
+
+#define EXFAT_ENTRY_EOD   0x00
+#define EXFAT_ENTRY_LABEL 0x83
 /*
  * Byte swap functions
  */
-- 
2.17.1


codechina上的提交id号:

  1. AOSP: blkid: add support to recognize exfat to blkid.
    I870e59a14b6bcd8b45562cdd02c2502d60a9eeff
  2. AOSP: blkid: Resolve to the exFAT uuid change on reboot.
    I376ed9fe1ba1b7f3d367d78cc5e2bb8ea9cc2d13
  3. AOSP: blkid: Correct the label name for exfat
    Ib16204c75c2cdf675d480e9c66f484bb3c51108e
    可根据上面的修改来同步到自己的代码上。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值