rk3399 安卓7 添加 exfat 格式U 盘支持

开发板是 IBOX3399卡片电脑:http://www.9tripod.com/showpro.php?id=93

安卓源码:https://gitlab.com/9tripod/x3399_nougat

主要的修改:

1,内核添加 exfat 文件系统支持
2,vold 添加 exfat 文件系统支持
3,需要 exfat 文件检查,格式化工具的支持,vold 中需要用到

参考:git clone https://gitee.com/rock_telp/android_add_exfat

1,内核 exfat 文件系统支持
复制 android_add_exfat\kernel-4.19\fs\exfat 到 kernel/fs/

2,exfat 相关工具 格式化 检查
复制 external下 exfat fuse 到 安卓源码 external下

3,安卓相关配置 主要是 vold 的修改和对应产品的配置相关

产品配置信息

device/rockchip/rk3399/device.mk

selinux 标签 非必需
device/rockchip/common/sepolicy/file_contexts

4,blkid 添加对 exfat 的识别支持

e2fsprogs

合入以下 patch
https://github.com/tytso/e2fsprogs/commit/1206f6d8c5ed47ba19cfc30a19dba51fcd2cd5cb.patch

5,修改错误

android_add_exfat\external\exfat\Android.mk

LOCAL_STATIC_LIBRARIES += libexfat libfuse

libfuse 不存在,实际编译的为 libfuse_static
LOCAL_STATIC_LIBRARIES += libexfat libfuse_static

vold 的修改对应不上,需要手动修改

参考 vfat 改成 exfat 并添加到 Android.mk vold 的编译中
vold/fs/Exfat.cpp

status_t Mount(const std::string& source, const std::string& target, int ownerUid, int ownerGid,
int permMask) {
int mountFlags = MS_NODEV | MS_NOSUID | MS_DIRSYNC | MS_NOATIME | MS_NOEXEC;
auto mountData = android::base::StringPrintf("uid=%d, gid=%d, fmask=%o, dmask=%o", ownerUid,
ownerGid, permMask, permMask);

if (mount(source.c_str(), target.c_str(), "exfat", mountFlags, mountData.c_str()) == 0) {
return 0;
PLOG(ERROR) << "Mount failed; attempting read-only";
mountFlags |= MS_RDONLY;
if (mount(source.c_str(), target.c_str(), "exfat", mountFlags, mountData.c_str()) == 0) {
return 0;
}
}
return -1;
}

修改完成重新刷机,插入U盘测试,查看 exfat 格式挂载:
x3399:/ # cat /proc/mounts |grep exfat
/dev/block/vold/public:8,1 /mnt/media_rw/public:8,1 exfat rw,dirsync,nosuid,nodev,noexec,noatime,uid=1023,gid=1023,fmask=0007,dmask=0007,allow_utime=0020,iocharset=utf8,namecase=0,errors=remount-ro 0 0

win11 使用下载软件版本:
AndroidTool_Release_v2.38

patch1 手动合入补丁:https://gitee.com/rock_telp/android_add_exfat

patch 2 适配了exfat 格式支持添加了新的 遥控器码 和 去掉了导航栏:

From b12a9ade383906eae0a1f6a5b8c35eda94ae6b06 Mon Sep 17 00:00:00 2001
From: ningci<ningci@ningci.com>
Date: Mon, 20 Oct 2025 09:41:03 +0800
Subject: [PATCH 2/2] x3399 add exfat support

---
 device/rockchip/rk3399/device.mk                   |   6 +-
 external/e2fsprogs/lib/blkid/probe.c               | 101 +++++++++++++-
 external/e2fsprogs/lib/blkid/probe.h               |  42 ++++++
 external/exfat/Android.mk                          |   2 +-
 .../systemui/statusbar/phone/PhoneStatusBar.java   |   2 +-
 .../boot/dts/rockchip/x3399-development-board.dts  |  53 ++++---
 kernel/arch/arm64/configs/x3399_defconfig          |   1 +
 kernel/fs/Kconfig                                  |   1 +
 kernel/fs/Makefile                                 |   1 +
 system/vold/Android.mk                             |   1 +
 system/vold/PublicVolume.cpp                       |  36 +++--
 system/vold/fs/Exfat.cpp                           | 153 +++++++++++++++++++++
 system/vold/fs/Exfat.h                             |  40 ++++++
 system/vold/main.cpp                               |   3 +-
 14 files changed, 392 insertions(+), 50 deletions(-)
 mode change 100644 => 100755 kernel/arch/arm64/boot/dts/rockchip/x3399-development-board.dts
 mode change 100644 => 100755 kernel/arch/arm64/configs/x3399_defconfig
 mode change 100644 => 100755 kernel/fs/Kconfig
 mode change 100644 => 100755 kernel/fs/Makefile
 create mode 100755 system/vold/fs/Exfat.cpp
 create mode 100755 system/vold/fs/Exfat.h
 mode change 100644 => 100755 system/vold/main.cpp

diff --git a/device/rockchip/rk3399/device.mk b/device/rockchip/rk3399/device.mk
index a594df6..80d69e4 100755
--- a/device/rockchip/rk3399/device.mk
+++ b/device/rockchip/rk3399/device.mk
@@ -20,7 +20,11 @@ PRODUCT_PROPERTY_OVERRIDES := \
 PRODUCT_PACKAGES += \
     memtrack.$(TARGET_BOARD_PLATFORM) \
     WallpaperPicker \
-    Launcher3
+    Launcher3\
+    fsck.exfat \
+    mkfs.exfat \
+    mount.exfat \
+    libfuse_static
 
 #enable this for support f2fs with data partion
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := f2fs
diff --git a/external/e2fsprogs/lib/blkid/probe.c b/external/e2fsprogs/lib/blkid/probe.c
index 8215768..fd04f1a 100644
--- a/external/e2fsprogs/lib/blkid/probe.c
+++ b/external/e2fsprogs/lib/blkid/probe.c
@@ -105,7 +105,6 @@ static int check_mdraid(int fd, unsigned char *ret_uuid)
     if (blkid_llseek(fd, offset, 0) < 0 ||
         read(fd, buf, 4096) != 4096)
         return -BLKID_ERR_IO;
-
     /* Check for magic number */
     if (memcmp("\251+N\374", buf, 4) && memcmp("\374N+\251", buf, 4))
         return -BLKID_ERR_PARAM;
@@ -329,7 +328,7 @@ static int probe_ext4dev(struct blkid_probe *probe,
         EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
         return -BLKID_ERR_PARAM;
 
-    /* 
+    /*
      * If the filesystem does not have a journal and ext2 and ext4
      * is not present, then force this to be detected as an
      * ext4dev filesystem.
@@ -373,7 +372,7 @@ static int probe_ext4(struct blkid_probe *probe, struct blkid_magic *id,
         EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
         return -BLKID_ERR_PARAM;
 
-    /* 
+    /*
      * If the filesystem does not have a journal and ext2 is not
      * present, then force this to be detected as an ext2
      * filesystem.
@@ -451,7 +450,7 @@ static int probe_ext2(struct blkid_probe *probe, struct blkid_magic *id,
          EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
         return -BLKID_ERR_PARAM;
 
-    /* 
+    /*
      * If ext2 is not present, but ext4 or ext4dev are, then
      * disclaim we are ext2
      */
@@ -1398,6 +1397,99 @@ static int probe_f2fs(struct blkid_probe *probe,
     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,
+                       unsigned char *buf)
+{
+    struct exfat_super_block *sb;
+    struct exfat_entry_label *label;
+    uuid_t uuid;
+    sb = (struct exfat_super_block *)buf;
+    if (!sb || !CLUSTER_SIZE(sb)) {
+        DBG(DEBUG_PROBE, printf("bad exfat superblock.\n"));
+        return errno ? - errno : 1;
+    }
+
+    label = find_exfat_entry_label(probe, sb);
+    if (label) {
+        blkid_set_tag(probe->dev, "LABEL", label->name, label->length);
+    } else {
+        blkid_set_tag(probe->dev, "LABEL", "disk", 4);
+    }
+
+    snprintf(uuid, sizeof (uuid), "%02hhX%02hhX-%02hhX%02hhX",
+             sb->volume_serial[3], sb->volume_serial[2],
+             sb->volume_serial[1], sb->volume_serial[0]);
+
+    set_uuid(probe->dev, uuid, 0);
+
+    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
@@ -1498,6 +1590,7 @@ static struct blkid_magic type_array[] = {
   { "lvm2pv",     1,  0x218,  8, "LVM2 001",        probe_lvm2 },
   { "btrfs",     64,  0x40,  8, "_BHRfS_M",        probe_btrfs },
   { "f2fs",     1,      0,  4, "\x10\x20\xf5\xf2",    probe_f2fs },
+  { "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 8eef37e..7e8706a 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;
@@ -762,6 +764,46 @@ struct f2fs_super_block {
     __u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */
 } __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
  */
diff --git a/external/exfat/Android.mk b/external/exfat/Android.mk
index 2800509..8299578 100755
--- a/external/exfat/Android.mk
+++ b/external/exfat/Android.mk
@@ -40,7 +40,7 @@ LOCAL_CFLAGS := \
 LOCAL_MODULE := mount.exfat
 LOCAL_SRC_FILES := main.c
 LOCAL_STATIC_LIBRARIES += libexfat_mount libexfat_fsck libexfat_mkfs libexfat_dump libexfat_label
-LOCAL_STATIC_LIBRARIES += libexfat libfuse
+LOCAL_STATIC_LIBRARIES += libexfat libfuse_static
 include $(BUILD_EXECUTABLE)
 
 LINKS := fsck.exfat mkfs.exfat
diff --git a/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index d111bf2..32578e8 100755
--- a/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1530,7 +1530,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
 
         prepareNavigationBarView();
 
-        mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
+        //mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     protected void repositionNavigationBar() {
diff --git a/kernel/arch/arm64/boot/dts/rockchip/x3399-development-board.dts b/kernel/arch/arm64/boot/dts/rockchip/x3399-development-board.dts
old mode 100644
new mode 100755
index 496df79..2539ed9
--- a/kernel/arch/arm64/boot/dts/rockchip/x3399-development-board.dts
+++ b/kernel/arch/arm64/boot/dts/rockchip/x3399-development-board.dts
@@ -209,36 +209,31 @@
     handle_cpu_id = <0>;
 
     ir_key0 {
-        rockchip,usercode = <0xff40>;
+        rockchip,usercode = <0xff00>;
         rockchip,key_table =
-            <0xb2    KEY_POWER>,
-            <0xe5    KEY_HOME>,
-            <0xbd    KEY_BACK>,
-            <0xba    KEY_MENU>,
-            <0xf4    KEY_UP>,
-            <0xf1    KEY_DOWN>,
-            <0xef    KEY_LEFT>,
-            <0xee    KEY_RIGHT>,
-            <0xf2    KEY_ENTER>,
-            <0xf0    KEY_REPLY>,
-            <0xea    KEY_VOLUMEUP>,
-            <0xe3    KEY_VOLUMEDOWN>,
-            <0xbc    KEY_MUTE>,
-            <0xfe    KEY_1>,
-            <0xfd    KEY_2>,
-            <0xfc    KEY_3>,
-            <0xfb    KEY_4>,
-            <0xfa    KEY_5>,
-            <0xf9    KEY_6>,
-            <0xf8    KEY_7>,
-            <0xf7    KEY_8>,
-            <0xb6    KEY_9>,
-            <0xff    KEY_0>,
-            <0xed    KEY_BACKSPACE>,
-
-            <0xaf    KEY_POWER>,
-            <0x8b    KEY_VOLUMEUP>,
-            <0xb9    KEY_VOLUMEDOWN>;
+        /*old IR code*/
+        <0xe9 KEY_BACK>,
+        <0xff KEY_HOME>,
+        <0xfe KEY_ENTER>,
+        <0xef KEY_VOLUMEUP>,
+        <0xf6 KEY_VOLUMEDOWN>,
+        <0xfd KEY_UP>,
+        <0xfc KEY_DOWN>,
+        <0xfb KEY_LEFT>,
+        <0xfa KEY_RIGHT>,
+
+        /* new IR code*/
+        <0x23 KEY_POWER>,
+        <0x7d KEY_MENU>,
+        <0x3a KEY_BACK>,
+        <0x77 KEY_HOME>,
+        <0x31 KEY_ENTER>,
+        <0x7f KEY_VOLUMEUP>,
+        <0x7e KEY_VOLUMEDOWN>,
+        <0x35 KEY_UP>,
+        <0x2d KEY_DOWN>,
+        <0x66 KEY_LEFT>,
+        <0x3e KEY_RIGHT>;
     };
 };
 
diff --git a/kernel/arch/arm64/configs/x3399_defconfig b/kernel/arch/arm64/configs/x3399_defconfig
old mode 100644
new mode 100755
index 537c974..c28fe80
--- a/kernel/arch/arm64/configs/x3399_defconfig
+++ b/kernel/arch/arm64/configs/x3399_defconfig
@@ -4831,3 +4831,4 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
 CONFIG_LIBFDT=y
 # CONFIG_SG_SPLIT is not set
 CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_EXFAT_FS=y
diff --git a/kernel/fs/Kconfig b/kernel/fs/Kconfig
old mode 100644
new mode 100755
index a5d2dc3..bf9e727
--- a/kernel/fs/Kconfig
+++ b/kernel/fs/Kconfig
@@ -281,5 +281,6 @@ endif # NETWORK_FILESYSTEMS
 
 source "fs/nls/Kconfig"
 source "fs/dlm/Kconfig"
+source "fs/exfat/Kconfig"
 
 endmenu
diff --git a/kernel/fs/Makefile b/kernel/fs/Makefile
old mode 100644
new mode 100755
index 3b54070..cf91d0d
--- a/kernel/fs/Makefile
+++ b/kernel/fs/Makefile
@@ -127,3 +127,4 @@ obj-y                += exofs/ # Multiple modules
 obj-$(CONFIG_CEPH_FS)        += ceph/
 obj-$(CONFIG_PSTORE)        += pstore/
 obj-$(CONFIG_EFIVAR_FS)        += efivarfs/
+obj-$(CONFIG_EXFAT_FS)        += exfat/
diff --git a/system/vold/Android.mk b/system/vold/Android.mk
index 3251c9d..74d7d37 100755
--- a/system/vold/Android.mk
+++ b/system/vold/Android.mk
@@ -12,6 +12,7 @@ common_src_files := \
     fs/F2fs.cpp \
     fs/Vfat.cpp \
     fs/Ntfs.cpp \
+    fs/Exfat.cpp \
     Loop.cpp \
     Devmapper.cpp \
     ResponseCode.cpp \
diff --git a/system/vold/PublicVolume.cpp b/system/vold/PublicVolume.cpp
index 320eb9a..62f6c74 100755
--- a/system/vold/PublicVolume.cpp
+++ b/system/vold/PublicVolume.cpp
@@ -18,6 +18,7 @@
 #include "fs/Ext4.h"
 #include "fs/F2fs.h"
 #include "fs/Ntfs.h"
+#include "fs/Exfat.h"
 #include "PublicVolume.h"
 #include "Utils.h"
 #include "VolumeManager.h"
@@ -132,6 +133,8 @@ status_t PublicVolume::doMount() {
         return -errno;
     }
 
+    LOG(DEBUG) << getId() << " filesystem mFsType:" << mFsType;
+
     if (mFsType == "vfat") {
         int res = vfat::Check(mDevPath);
         if (res == 0 || res == 1) {
@@ -195,7 +198,22 @@ status_t PublicVolume::doMount() {
             return -EIO;
         }
 
-    } else {
+    } else if (mFsType == "exfat") {
+        int res = exfat::Check(mDevPath);
+        if (res == 0) {
+            LOG(DEBUG) << getId() << " passed filesystem check";
+        } else {
+            PLOG(ERROR) << getId() << " failed filesystem check";
+            return -EIO;
+        }
+
+        if (exfat::Mount(mDevPath, mRawPath, false, false, false,
+                AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
+            PLOG(ERROR) << getId() << " failed to mount";
+            return -EIO;
+        }
+    }
+    else {
         LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
         return -EIO;
     }
@@ -302,18 +320,10 @@ status_t PublicVolume::doUnmount() {
 }
 
 status_t PublicVolume::doFormat(const std::string& fsType) {
-    if (fsType == "vfat" || fsType == "auto") {
-        if (WipeBlockDevice(mDevPath) != OK) {
-            LOG(WARNING) << getId() << " failed to wipe";
-        }
-        if (vfat::Format(mDevPath, 0)) {
-            LOG(ERROR) << getId() << " failed to format";
-            return -errno;
-        }
-    } else {
-        LOG(ERROR) << "Unsupported filesystem " << fsType;
-        return -EINVAL;
-    }
+    if (exfat::Format(mDevPath)) {
+        LOG(ERROR) << getId() << " failed to format";
+        return -errno;
+    }
 
     return OK;
 }
diff --git a/system/vold/fs/Exfat.cpp b/system/vold/fs/Exfat.cpp
new file mode 100755
index 0000000..7dc0128
--- /dev/null
+++ b/system/vold/fs/Exfat.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+
+#include <linux/kdev_t.h>
+
+#define LOG_TAG "Vold"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <selinux/selinux.h>
+
+#include <logwrap/logwrap.h>
+
+#include "Exfat.h"
+#include "Utils.h"
+#include "VoldUtil.h"
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace vold {
+namespace exfat {
+
+static const char* kMkfsPath = "/system/bin/mkfs.exfat";
+static const char* kFsckPath = "/system/bin/fsck.exfat";
+
+bool IsSupported() {
+    return access(kMkfsPath, X_OK) == 0
+            && access(kFsckPath, X_OK) == 0
+            && IsFilesystemSupported("exfat");
+}
+
+status_t Check(const std::string& source) {
+    if (access(kFsckPath, X_OK)) {
+        SLOGW("Skipping fs checks\n");
+        return 0;
+    }
+
+    std::vector<std::string> cmd;
+    cmd.push_back(kFsckPath);
+    cmd.push_back(source);
+
+    int rc = ForkExecvp(cmd);
+    SLOGI("Check OK");
+    return 0;
+}
+
+status_t Mount(const std::string& source, const std::string& target, bool ro,
+        bool remount, bool executable, int ownerUid, int ownerGid, int permMask,
+        bool createLost) {
+    int rc;
+    unsigned long flags;
+    char mountData[255];
+
+    const char* c_source = source.c_str();
+    const char* c_target = target.c_str();
+
+    flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC | MS_NOATIME | MS_NOEXEC;
+
+    flags |= (executable ? 0 : MS_NOEXEC);
+    flags |= (ro ? MS_RDONLY : 0);
+    flags |= (remount ? MS_REMOUNT : 0);
+
+    sprintf(mountData,
+            "uid=%d,gid=%d,fmask=%o,dmask=%o",
+            ownerUid, ownerGid, permMask, permMask);
+
+    rc = mount(c_source, c_target, "exfat", flags, mountData);
+
+    if (rc && errno == EROFS) {
+        SLOGE("%s appears to be a read only filesystem - retrying mount RO", c_source);
+        flags |= MS_RDONLY;
+        rc = mount(c_source, c_target, "exfat", flags, mountData);
+    }
+
+    if (rc == 0 && createLost) {
+        char *lost_path;
+        asprintf(&lost_path, "%s/LOST.DIR", c_target);
+        if (access(lost_path, F_OK)) {
+            /*
+             * Create a LOST.DIR in the root so we have somewhere to put
+             * lost cluster chains (fsck_msdos doesn't currently do this)
+             */
+            if (mkdir(lost_path, 0755)) {
+                SLOGE("Unable to create LOST.DIR (%s)", strerror(errno));
+            }
+        }
+        free(lost_path);
+    }
+
+    return rc;
+}
+
+status_t Format(const std::string& source) {
+    std::vector<std::string> cmd;
+    cmd.push_back(kMkfsPath);
+    cmd.push_back(source);
+
+    int rc = ForkExecvp(cmd);
+    if (rc < 0) {
+        SLOGE("Filesystem format failed due to logwrap error");
+        errno = EIO;
+        return -1;
+    }
+
+    if (rc == 0) {
+        SLOGI("Filesystem formatted OK");
+        return 0;
+    } else {
+        SLOGE("Format failed (unknown exit code %d)", rc);
+        errno = EIO;
+        return -1;
+    }
+    return 0;
+}
+
+}  // namespace exfat
+}  // namespace vold
+}  // namespace android
diff --git a/system/vold/fs/Exfat.h b/system/vold/fs/Exfat.h
new file mode 100755
index 0000000..4f4792a
--- /dev/null
+++ b/system/vold/fs/Exfat.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VOLD_EXFAT_H
+#define ANDROID_VOLD_EXFAT_H
+
+#include <utils/Errors.h>
+
+#include <string>
+
+namespace android {
+namespace vold {
+namespace exfat {
+
+bool IsSupported();
+
+status_t Check(const std::string& source);
+status_t Mount(const std::string& source, const std::string& target, bool ro,
+        bool remount, bool executable, int ownerUid, int ownerGid, int permMask,
+        bool createLost);
+status_t Format(const std::string& source);
+
+}  // namespace exfat
+}  // namespace vold
+}  // namespace android
+
+#endif
diff --git a/system/vold/main.cpp b/system/vold/main.cpp
old mode 100644
new mode 100755
index 4ec0173..49d107d
--- a/system/vold/main.cpp
+++ b/system/vold/main.cpp
@@ -62,7 +62,8 @@ int main(int argc, char** argv) {
     LOG(VERBOSE) << "Detected support for:"
             << (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")
             << (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")
-            << (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "");
+            << (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "")
+            << (android::vold::IsFilesystemSupported("exfat") ? " exfat" : "");
 
     VolumeManager *vm;
     CommandListener *cl;
-- 
2.7.4
View Code

 

posted @ 2025-10-18 13:10  宁次  阅读(30)  评论(0)    收藏  举报