一、前言
最近客户反馈一个问题,就是Android
系统的机顶盒插上exfat
格式的U盘后,获取不到UUID
这个信息。
/system/vold/
中已经添加对exfat
格式U
盘的支持,并且通过df
命令能够看到U
盘已经挂载上,但是执行blkid
时,并未显示exfat
格式U
盘信息。
二、问题分析
- 执行
blkid /dev/block/sda1
命令(sda1
为U
盘挂载点),若U
盘格式为vfat
的,则能够正常显示,若U
盘格式为exfat
的,则不能显示。 - 问题应该出在
blkid
命令不健全导致的,可以补充一部分代码,让其能够显示出来。
三、解决方法
- 需要修改的代码在
external/e2fsprogs/lib/blkid
路径下。 e2fsprogs
是一个Ext2
(及Ext3/4
)文件系统工具(Ext2Filesystems Utilities
),它包含了诸如创建、修复、配置、调试ext2
文件系统等的标准工具。e2fsprogs
是开放源代码软件 ,遵从GPLv2
或LGPLv2
。- codechina上有
e2fsprogs
的开源代码,里面已经添加对exfat
的相应支持,我们可以在这个里面搜寻相应的修改同步过来。 - 里面主要修改了两个文件,
probe.c
和probe.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
号:
AOSP: blkid: add support to recognize exfat to blkid.
I870e59a14b6bcd8b45562cdd02c2502d60a9eeffAOSP: blkid: Resolve to the exFAT uuid change on reboot.
I376ed9fe1ba1b7f3d367d78cc5e2bb8ea9cc2d13AOSP: blkid: Correct the label name for exfat
Ib16204c75c2cdf675d480e9c66f484bb3c51108e
可根据上面的修改来同步到自己的代码上。