From d0c3b35e1ce72bf499f11166d5e92e90638cb387 Mon Sep 17 00:00:00 2001 From: GuEe-GUI <2991707448@qq.com> Date: Wed, 30 Oct 2024 10:44:16 +0800 Subject: [PATCH 1/3] [DM/FEATURE] Support simple block layer 1. Disk and blk device management. 2. Support partitions probe auto. 3. Support DFS and user mode fops, ioctl. 4. Add a cmd for blk info. Signed-off-by: GuEe-GUI <2991707448@qq.com> --- components/drivers/Kconfig | 1 + components/drivers/block/Kconfig | 7 + components/drivers/block/SConscript | 23 + components/drivers/block/blk.c | 569 ++++++++++++++ components/drivers/block/blk_dev.c | 297 +++++++ components/drivers/block/blk_dev.h | 49 ++ components/drivers/block/blk_dfs.c | 274 +++++++ components/drivers/block/blk_dfs.h | 23 + components/drivers/block/blk_partition.c | 154 ++++ components/drivers/block/blk_partition.h | 22 + components/drivers/block/partitions/Kconfig | 12 + .../drivers/block/partitions/SConscript | 18 + components/drivers/block/partitions/dfs.c | 53 ++ components/drivers/block/partitions/efi.c | 738 ++++++++++++++++++ components/drivers/block/partitions/efi.h | 141 ++++ components/drivers/include/drivers/blk.h | 87 +++ components/drivers/include/rtdevice.h | 4 + 17 files changed, 2472 insertions(+) create mode 100644 components/drivers/block/Kconfig create mode 100644 components/drivers/block/SConscript create mode 100644 components/drivers/block/blk.c create mode 100644 components/drivers/block/blk_dev.c create mode 100644 components/drivers/block/blk_dev.h create mode 100644 components/drivers/block/blk_dfs.c create mode 100644 components/drivers/block/blk_dfs.h create mode 100644 components/drivers/block/blk_partition.c create mode 100644 components/drivers/block/blk_partition.h create mode 100644 components/drivers/block/partitions/Kconfig create mode 100644 components/drivers/block/partitions/SConscript create mode 100644 components/drivers/block/partitions/dfs.c create mode 100644 components/drivers/block/partitions/efi.c create mode 100644 components/drivers/block/partitions/efi.h create mode 100644 components/drivers/include/drivers/blk.h diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 8b69868205f..fc524de939a 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -21,6 +21,7 @@ rsource "touch/Kconfig" rsource "graphic/Kconfig" rsource "hwcrypto/Kconfig" rsource "wlan/Kconfig" +rsource "block/Kconfig" rsource "virtio/Kconfig" rsource "ofw/Kconfig" rsource "pci/Kconfig" diff --git a/components/drivers/block/Kconfig b/components/drivers/block/Kconfig new file mode 100644 index 00000000000..865df5e1241 --- /dev/null +++ b/components/drivers/block/Kconfig @@ -0,0 +1,7 @@ +menuconfig RT_USING_BLK + bool "Using Block device drivers" + default n + +if RT_USING_BLK + rsource "partitions/Kconfig" +endif diff --git a/components/drivers/block/SConscript b/components/drivers/block/SConscript new file mode 100644 index 00000000000..4aff1a82c91 --- /dev/null +++ b/components/drivers/block/SConscript @@ -0,0 +1,23 @@ +from building import * + +group = [] +objs = [] + +if not GetDepend(['RT_USING_BLK']): + Return('group') + +cwd = GetCurrentDir() +list = os.listdir(cwd) +CPPPATH = [cwd + '/../include'] + +src = ['blk.c', 'blk_dev.c', 'blk_dfs.c', 'blk_partition.c'] + +group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) +objs = objs + group + +Return('objs') diff --git a/components/drivers/block/blk.c b/components/drivers/block/blk.c new file mode 100644 index 00000000000..2bfa78b1ef5 --- /dev/null +++ b/components/drivers/block/blk.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI the first version + */ + +#define DBG_TAG "rtdm.blk" +#define DBG_LVL DBG_INFO +#include + +#include "blk_dev.h" +#include "blk_dfs.h" + +static void blk_remove_all(struct rt_blk_disk *disk) +{ + struct rt_blk_device *blk, *blk_next; + + /* Remove all partitions */ + rt_list_for_each_entry_safe(blk, blk_next, &disk->part_nodes, list) + { + disk_remove_blk_dev(blk, RT_TRUE); + } +} + +static rt_err_t blk_open(rt_device_t dev, rt_uint16_t oflag) +{ + struct rt_blk_disk *disk = to_blk_disk(dev); + + if (disk->read_only && (oflag & RT_DEVICE_OFLAG_WRONLY)) + { + return -RT_EINVAL; + } + + return RT_EOK; +} + +static rt_err_t blk_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_ssize_t blk_read(rt_device_t dev, rt_off_t sector, + void *buffer, rt_size_t sector_count) +{ + rt_ssize_t res; + struct rt_blk_disk *disk = to_blk_disk(dev); + + rt_sem_take(&disk->usr_lock, RT_WAITING_FOREVER); + + res = disk->ops->read(disk, sector, buffer, sector_count); + + rt_sem_release(&disk->usr_lock); + + return res; +} + +static rt_ssize_t blk_write(rt_device_t dev, rt_off_t sector, + const void *buffer, rt_size_t sector_count) +{ + rt_ssize_t res; + struct rt_blk_disk *disk = to_blk_disk(dev); + + if (!disk->read_only) + { + rt_sem_take(&disk->usr_lock, RT_WAITING_FOREVER); + + res = disk->ops->write(disk, sector, buffer, sector_count); + + rt_sem_release(&disk->usr_lock); + + return res; + } + + return -RT_ENOSYS; +} + +static rt_ssize_t blk_parallel_read(rt_device_t dev, rt_off_t sector, + void *buffer, rt_size_t sector_count) +{ + struct rt_blk_disk *disk = to_blk_disk(dev); + + return disk->ops->read(disk, sector, buffer, sector_count); +} + +static rt_ssize_t blk_parallel_write(rt_device_t dev, rt_off_t sector, + const void *buffer, rt_size_t sector_count) +{ + struct rt_blk_disk *disk = to_blk_disk(dev); + + if (!disk->read_only) + { + return disk->ops->write(disk, sector, buffer, sector_count); + } + + return -RT_ENOSYS; +} + +static rt_err_t blk_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t err; + struct rt_blk_disk *disk = to_blk_disk(dev); + + switch (cmd) + { + case RT_DEVICE_CTRL_BLK_GETGEOME: + if (args) + { + err = disk->ops->getgeome(disk, args); + } + else + { + err = -RT_EINVAL; + } + + break; + + case RT_DEVICE_CTRL_BLK_SYNC: + if (disk->ops->sync) + { + rt_sem_take(&disk->usr_lock, RT_WAITING_FOREVER); + + spin_lock(&disk->lock); + + err = disk->ops->sync(disk); + + spin_unlock(&disk->lock); + + rt_sem_release(&disk->usr_lock); + } + else + { + err = -RT_ENOSYS; + } + break; + + case RT_DEVICE_CTRL_BLK_ERASE: + if (disk->ops->erase) + { + rt_sem_take(&disk->usr_lock, RT_WAITING_FOREVER); + + spin_lock(&disk->lock); + + if (disk->parent.ref_count != 1) + { + err = -RT_EBUSY; + goto _unlock; + } + + blk_remove_all(disk); + + err = disk->ops->erase(disk); + + _unlock: + spin_unlock(&disk->lock); + + rt_sem_release(&disk->usr_lock); + } + else + { + err = -RT_ENOSYS; + } + break; + + case RT_DEVICE_CTRL_BLK_AUTOREFRESH: + if (disk->ops->autorefresh) + { + err = disk->ops->autorefresh(disk, !!args); + } + else + { + err = -RT_ENOSYS; + } + break; + + case RT_DEVICE_CTRL_BLK_PARTITION: + err = -RT_EINVAL; + break; + + case RT_DEVICE_CTRL_BLK_SSIZEGET: + device_get_blk_ssize(dev, args); + err = RT_EOK; + break; + + case RT_DEVICE_CTRL_ALL_BLK_SSIZEGET: + device_get_all_blk_ssize(dev, args); + err = RT_EOK; + break; + + default: + if (disk->ops->control) + { + err = disk->ops->control(disk, RT_NULL, cmd, args); + } + break; + } + + return err; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops blk_ops = +{ + .open = blk_open, + .close = blk_close, + .read = blk_read, + .write = blk_write, + .control = blk_control, +}; + +const static struct rt_device_ops blk_parallel_ops = +{ + .open = blk_open, + .close = blk_close, + .read = blk_parallel_read, + .write = blk_parallel_write, + .control = blk_control, +}; +#endif /* RT_USING_DEVICE_OPS */ + +rt_err_t rt_hw_blk_disk_register(struct rt_blk_disk *disk) +{ + rt_err_t err; +#ifdef RT_USING_DM + int device_id; +#endif + const char *disk_name; + rt_uint16_t flags = RT_DEVICE_FLAG_RDONLY; + + if (!disk || !disk->ops) + { + return -RT_EINVAL; + } + +#ifdef RT_USING_DM + if (!disk->ida) + { + return -RT_EINVAL; + } +#endif + +#if RT_NAME_MAX > 0 + if (disk->parent.parent.name[0] == '\0') +#else + if (disk->parent.parent.name) +#endif + { + return -RT_EINVAL; + } + +#ifdef RT_USING_DM + if ((device_id = rt_dm_ida_alloc(disk->ida)) < 0) + { + return -RT_EFULL; + } +#endif + + disk->__magic = RT_BLK_DISK_MAGIC; + disk_name = to_disk_name(disk); + + err = rt_sem_init(&disk->usr_lock, disk_name, 1, RT_IPC_FLAG_PRIO); + + if (err) + { + #ifdef RT_USING_DM + rt_dm_ida_free(disk->ida, device_id); + #endif + + LOG_E("%s: Init user mutex error = %s", rt_strerror(err)); + + return err; + } + + rt_list_init(&disk->part_nodes); + rt_spin_lock_init(&disk->lock); + + disk->parent.type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + if (disk->parallel_io) + { + disk->parent.ops = &blk_parallel_ops; + } + else + { + disk->parent.ops = &blk_ops; + } +#else + disk->parent.open = blk_open; + disk->parent.close = blk_close; + + if (disk->parallel_io) + { + disk->parent.read = blk_parallel_read; + disk->parent.write = blk_parallel_write; + } + else + { + disk->parent.read = blk_read; + disk->parent.write = blk_write; + } + disk->parent.control = blk_control; +#endif + + if (!disk->ops->write) + { + disk->read_only = RT_TRUE; + } + + if (!disk->read_only) + { + flags |= RT_DEVICE_FLAG_WRONLY; + } + +#ifdef RT_USING_DM + disk->parent.master_id = disk->ida->master_id; + disk->parent.device_id = device_id; +#endif + device_set_blk_fops(&disk->parent); + + err = rt_device_register(&disk->parent, disk_name, flags); + + if (err) + { + rt_sem_detach(&disk->usr_lock); + } + + /* Ignore partition scanning errors */ + rt_blk_disk_probe_partition(disk); + + return err; +} + +rt_err_t rt_hw_blk_disk_unregister(struct rt_blk_disk *disk) +{ + rt_err_t err; + + if (!disk) + { + return -RT_EINVAL; + } + + spin_lock(&disk->lock); + + if (disk->parent.ref_count != 1) + { + err = -RT_EBUSY; + goto _unlock; + } + + /* Flush all data */ + if (disk->ops->sync) + { + err = disk->ops->sync(disk); + + if (err) + { + LOG_E("%s: Sync error = %s", to_disk_name(disk), rt_strerror(err)); + + goto _unlock; + } + } + + rt_sem_detach(&disk->usr_lock); + + blk_remove_all(disk); + +#ifdef RT_USING_DM + rt_dm_ida_free(disk->ida, disk->parent.device_id); +#endif + + err = rt_device_unregister(&disk->parent); + +_unlock: + spin_unlock(&disk->lock); + + return err; +} + +rt_ssize_t rt_blk_disk_get_capacity(struct rt_blk_disk *disk) +{ + rt_ssize_t res; + struct rt_device_blk_geometry geometry; + + if (!disk) + { + return -RT_EINVAL; + } + + res = disk->ops->getgeome(disk, &geometry); + + if (!res) + { + return geometry.sector_count; + } + + return res; +} + +rt_ssize_t rt_blk_disk_get_logical_block_size(struct rt_blk_disk *disk) +{ + rt_ssize_t res; + struct rt_device_blk_geometry geometry; + + if (!disk) + { + return -RT_EINVAL; + } + + res = disk->ops->getgeome(disk, &geometry); + + if (!res) + { + return geometry.bytes_per_sector; + } + + return res; +} + +#ifdef RT_USING_DFS_MNTTABLE +static int blk_dfs_mnt_table(void) +{ + rt_ubase_t level; + struct rt_object *obj; + struct rt_device *dev; + struct rt_blk_disk *disk; + struct rt_blk_device *blk_dev; + struct rt_object_information *info = rt_object_get_information(RT_Object_Class_Device); + + level = rt_hw_interrupt_disable(); + + rt_list_for_each_entry(obj, &info->object_list, list) + { + dev = rt_container_of(obj, struct rt_device, parent); + + if (dev->type != RT_Device_Class_Block) + { + continue; + } + + disk = to_blk_disk(dev); + + if (disk->__magic != RT_BLK_DISK_MAGIC) + { + continue; + } + + if (disk->max_partitions == RT_BLK_PARTITION_NONE) + { + dfs_mount_device(&disk->parent); + continue; + } + + rt_list_for_each_entry(blk_dev, &disk->part_nodes, list) + { + dfs_mount_device(&blk_dev->parent); + } + } + + rt_hw_interrupt_enable(level); + + return 0; +} +INIT_ENV_EXPORT(blk_dfs_mnt_table); +#endif /* RT_USING_DFS_MNTTABLE */ + +#if defined(RT_USING_CONSOLE) && defined(RT_USING_MSH) +const char *convert_size(struct rt_device_blk_geometry *geome, + rt_size_t sector_count, rt_size_t *out_cap, rt_size_t *out_minor) +{ + rt_size_t cap, minor; + int size_index = 0; + const char *size_name[] = { "B", "K", "M", "G", "T", "P", "E" }; + + cap = geome->bytes_per_sector * sector_count; + + for (size_index = 0; size_index < RT_ARRAY_SIZE(size_name) - 1; ++size_index) + { + if (cap < 1024) + { + break; + } + + /* Only one decimal point */ + minor = (cap % 1024) * 10 / 1024; + cap = cap / 1024; + } + + *out_cap = cap; + *out_minor = minor; + + return size_name[size_index]; +} + +static int list_blk(int argc, char**argv) +{ + rt_ubase_t level; + rt_size_t cap, minor; + const char *size_name; + struct rt_object *obj; + struct rt_device *dev; + struct rt_blk_disk *disk; + struct rt_blk_device *blk_dev; + struct rt_device_blk_geometry geome; + struct rt_object_information *info = rt_object_get_information(RT_Object_Class_Device); + + level = rt_hw_interrupt_disable(); + + rt_kprintf("%-*.s MAJ:MIN RM SIZE\tRO TYPE MOUNTPOINT\n", RT_NAME_MAX, "NAME"); + + rt_list_for_each_entry(obj, &info->object_list, list) + { + dev = rt_container_of(obj, struct rt_device, parent); + + if (dev->type != RT_Device_Class_Block) + { + continue; + } + + disk = to_blk_disk(dev); + + if (disk->__magic != RT_BLK_DISK_MAGIC) + { + continue; + } + + if (disk->ops->getgeome(disk, &geome)) + { + continue; + } + + size_name = convert_size(&geome, geome.sector_count, &cap, &minor); + + rt_kprintf("%-*.s %3u.%-3u %u %u.%u%s\t%u disk %s\n", + RT_NAME_MAX, to_disk_name(disk), + #ifdef RT_USING_DM + disk->parent.master_id, disk->parent.device_id, + #else + 0, 0, + #endif + disk->removable, cap, minor, size_name, disk->read_only, + disk->max_partitions != RT_BLK_PARTITION_NONE ? "\b" : + (dfs_filesystem_get_mounted_path(&disk->parent) ? : "\b")); + + rt_list_for_each_entry(blk_dev, &disk->part_nodes, list) + { + size_name = convert_size(&geome, blk_dev->sector_count, &cap, &minor); + + rt_kprintf("%c--%-*.s %3u.%-3u %u %u.%u%s\t%u part %s\n", + blk_dev->list.next != &disk->part_nodes ? '|' : '`', + RT_NAME_MAX - 3, to_blk_name(blk_dev), + #ifdef RT_USING_DM + blk_dev->parent.master_id, blk_dev->parent.device_id, + #else + 0, 0, + #endif + disk->removable, cap, minor, size_name, disk->read_only, + dfs_filesystem_get_mounted_path(&blk_dev->parent) ? : ""); + } + } + + rt_hw_interrupt_enable(level); + + return 0; +} +MSH_CMD_EXPORT(list_blk, dump all of blks information); +#endif /* RT_USING_CONSOLE && RT_USING_MSH */ diff --git a/components/drivers/block/blk_dev.c b/components/drivers/block/blk_dev.c new file mode 100644 index 00000000000..5c45aa5ecc3 --- /dev/null +++ b/components/drivers/block/blk_dev.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI first version + */ + +#include "blk_dev.h" +#include "blk_dfs.h" + +#define DBG_TAG "blk.dm" +#define DBG_LVL DBG_INFO +#include + +#ifdef RT_USING_DFS +#include +#endif + +static rt_err_t blk_dev_open(rt_device_t dev, rt_uint16_t oflag) +{ + struct rt_blk_device *blk = to_blk(dev); + + return rt_device_open(&blk->disk->parent, oflag); +} + +static rt_err_t blk_dev_close(rt_device_t dev) +{ + struct rt_blk_device *blk = to_blk(dev); + + return rt_device_close(&blk->disk->parent); +} + +static rt_ssize_t blk_dev_read(rt_device_t dev, rt_off_t sector, + void *buffer, rt_size_t sector_count) +{ + struct rt_blk_device *blk = to_blk(dev); + + if (sector <= blk->sector_start + blk->sector_count && + sector_count <= blk->sector_count) + { + return rt_device_read(&blk->disk->parent, + blk->sector_start + sector, buffer, sector_count); + } + + return -RT_EINVAL; +} + +static rt_ssize_t blk_dev_write(rt_device_t dev, rt_off_t sector, + const void *buffer, rt_size_t sector_count) +{ + struct rt_blk_device *blk = to_blk(dev); + + if (sector <= blk->sector_start + blk->sector_count && + sector_count <= blk->sector_count) + { + return rt_device_write(&blk->disk->parent, + blk->sector_start + sector, buffer, sector_count); + } + + return -RT_EINVAL; +} + +static rt_err_t blk_dev_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t err = -RT_EINVAL; + struct rt_blk_device *blk = to_blk(dev); + struct rt_blk_disk *disk = blk->disk; + struct rt_device_blk_geometry disk_geometry, *geometry; + + switch (cmd) + { + case RT_DEVICE_CTRL_BLK_GETGEOME: + if ((geometry = args)) + { + if (!(err = disk->ops->getgeome(disk, &disk_geometry))) + { + geometry->bytes_per_sector = disk_geometry.bytes_per_sector; + geometry->block_size = disk_geometry.block_size; + geometry->sector_count = blk->sector_count; + } + } + else + { + err = -RT_EINVAL; + } + + break; + + case RT_DEVICE_CTRL_BLK_SYNC: + rt_device_control(&disk->parent, cmd, args); + break; + + case RT_DEVICE_CTRL_BLK_ERASE: + case RT_DEVICE_CTRL_BLK_AUTOREFRESH: + if (disk->partitions <= 1) + { + rt_device_control(&disk->parent, cmd, args); + } + else + { + err = -RT_EIO; + } + break; + + case RT_DEVICE_CTRL_BLK_PARTITION: + if (args) + { + rt_memcpy(args, &blk->partition, sizeof(blk->partition)); + } + else + { + err = -RT_EINVAL; + } + + break; + + case RT_DEVICE_CTRL_BLK_SSIZEGET: + device_get_blk_ssize(dev, args); + err = RT_EOK; + break; + + case RT_DEVICE_CTRL_ALL_BLK_SSIZEGET: + device_get_all_blk_ssize(dev, args); + err = RT_EOK; + break; + + default: + if (disk->ops->control) + { + err = disk->ops->control(disk, blk, cmd, args); + } + break; + } + + return err; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops blk_dev_ops = +{ + .open = blk_dev_open, + .close = blk_dev_close, + .read = blk_dev_read, + .write = blk_dev_write, + .control = blk_dev_control, +}; +#endif + +rt_err_t blk_dev_initialize(struct rt_blk_device *blk) +{ + struct rt_device *dev; + + if (!blk) + { + return -RT_EINVAL; + } + + dev = &blk->parent; + dev->type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + dev->ops = &blk_dev_ops; +#else + dev->open = blk_dev_open; + dev->close = blk_dev_close; + dev->read = blk_dev_read; + dev->write = blk_dev_write; + dev->control = blk_dev_control; +#endif + + return RT_EOK; +} + +rt_err_t disk_add_blk_dev(struct rt_blk_disk *disk, struct rt_blk_device *blk) +{ + rt_err_t err; +#ifdef RT_USING_DM + int device_id; +#endif + const char *disk_name, *name_fmt; + + if (!disk || !blk) + { + return -RT_EINVAL; + } + +#ifdef RT_USING_DM + if ((device_id = rt_dm_ida_alloc(disk->ida)) < 0) + { + return -RT_EFULL; + } +#endif + + blk->disk = disk; + rt_list_init(&blk->list); + + disk_name = to_disk_name(disk); + + /* End is [a-zA-Z] or [0-9] */ + if (disk_name[rt_strlen(disk_name) - 1] < 'a') + { + name_fmt = "%sp%d"; + } + else + { + name_fmt = "%s%d"; + } + +#ifdef RT_USING_DM + rt_dm_dev_set_name(&blk->parent, name_fmt, disk_name, blk->partno); + blk->parent.master_id = disk->ida->master_id; + blk->parent.device_id = device_id; +#else + rt_snprintf(blk->parent.parent.name, RT_NAME_MAX, name_fmt, disk_name, blk->partno); +#endif + device_set_blk_fops(&blk->parent); + + err = rt_device_register(&blk->parent, to_blk_name(blk), + disk->parent.flag & RT_DEVICE_FLAG_RDWR); + + if (err) + { + #ifdef RT_USING_DM + rt_dm_ida_free(disk->ida, device_id); + #endif + return err; + } + + spin_lock(&disk->lock); + + rt_list_insert_before(&disk->part_nodes, &blk->list); + + spin_unlock(&disk->lock); + + return RT_EOK; +} + +rt_err_t disk_remove_blk_dev(struct rt_blk_device *blk, rt_bool_t lockless) +{ + struct rt_blk_disk *disk; + + if (!blk) + { + return -RT_EINVAL; + } + + disk = blk->disk; + + if (!disk) + { + return -RT_EINVAL; + } + else + { + #ifdef RT_USING_DFS + const char *mountpath; + + if ((mountpath = dfs_filesystem_get_mounted_path(&blk->parent))) + { + dfs_unmount(mountpath); + LOG_D("%s: Unmount file system on %s", + to_blk_name(blk), mountpath); + } + #endif + } + +#ifdef RT_USING_DM + rt_dm_ida_free(disk->ida, blk->parent.device_id); +#endif + + rt_device_unregister(&blk->parent); + + if (!lockless) + { + spin_lock(&disk->lock); + } + + rt_list_remove(&blk->list); + + if (!lockless) + { + spin_unlock(&disk->lock); + } + + --disk->partitions; + + return RT_EOK; +} + +rt_uint32_t blk_request_ioprio(void) +{ + struct rt_thread *task = rt_thread_self(); + + return task ? RT_SCHED_PRIV(task).current_priority : 0; +} diff --git a/components/drivers/block/blk_dev.h b/components/drivers/block/blk_dev.h new file mode 100644 index 00000000000..b433f57f876 --- /dev/null +++ b/components/drivers/block/blk_dev.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI first version + */ + +#ifndef __BLK_DEV_H__ +#define __BLK_DEV_H__ + +#include +#include +#include +#include + +#define to_blk_disk(dev) rt_container_of(dev, struct rt_blk_disk, parent) +#define to_blk(dev) rt_container_of(dev, struct rt_blk_device, parent) + +#ifdef RT_USING_DM +#define to_disk_name(disk) rt_dm_dev_get_name(&(disk)->parent) +#define to_blk_name(blk) rt_dm_dev_get_name(&(blk)->parent) +#else +#define to_disk_name(disk) (disk)->parent.parent.name +#define to_blk_name(blk) (blk)->parent.parent.name +#endif + +/* %c%c name */ +#define letter_name(n) ('a' + (n) / ((n) >= 26 ? (26 * 2) : 1)), ((n) >= 26 ? 'a' + (n) % 26 : '\0') + +rt_inline void spin_lock(struct rt_spinlock *spinlock) +{ + rt_hw_spin_lock(&spinlock->lock); +} + +rt_inline void spin_unlock(struct rt_spinlock *spinlock) +{ + rt_hw_spin_unlock(&spinlock->lock); +} + +rt_err_t blk_dev_initialize(struct rt_blk_device *blk); +rt_err_t disk_add_blk_dev(struct rt_blk_disk *disk, struct rt_blk_device *blk); +rt_err_t disk_remove_blk_dev(struct rt_blk_device *blk, rt_bool_t lockless); + +rt_uint32_t blk_request_ioprio(void); + +#endif /* __BLK_DEV_H__ */ diff --git a/components/drivers/block/blk_dfs.c b/components/drivers/block/blk_dfs.c new file mode 100644 index 00000000000..96800e15643 --- /dev/null +++ b/components/drivers/block/blk_dfs.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-08 GuEe-GUI first version + */ + +#include "blk_dfs.h" + +#include +#include + +#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_DFS_V2) +struct blk_fops_data +{ + struct rt_device_blk_geometry geometry; +}; + +static int blk_fops_open(struct dfs_file *file) +{ + struct rt_device *dev = file->vnode->data; + struct blk_fops_data *data = rt_malloc(sizeof(*data)); + + if (!data) + { + return (int)-RT_ENOMEM; + } + + dev->user_data = data; + rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &data->geometry); + rt_device_control(dev, RT_DEVICE_CTRL_ALL_BLK_SSIZEGET, &file->vnode->size); + + return 0; +} + +static int blk_fops_close(struct dfs_file *file) +{ + struct rt_device *dev = file->vnode->data; + + rt_free(dev->user_data); + dev->user_data = RT_NULL; + + return 0; +} + +static int blk_fops_ioctl(struct dfs_file *file, int cmd, void *arg) +{ + struct rt_device *dev = file->vnode->data; + + return (int)rt_device_control(dev, cmd, arg); +} + +static ssize_t blk_fops_read(struct dfs_file *file, void *buf, size_t count, off_t *pos) +{ + void *rbuf; + rt_ssize_t res = 0; + int bytes_per_sector, blk_pos, first_offs, rsize = 0; + struct rt_device *dev = file->vnode->data; + struct blk_fops_data *data = dev->user_data; + + bytes_per_sector = data->geometry.bytes_per_sector; + blk_pos = *pos / bytes_per_sector; + first_offs = *pos % bytes_per_sector; + + if ((rbuf = rt_malloc(bytes_per_sector))) + { + /* + ** #1: read first unalign block size. + */ + res = rt_device_read(dev, blk_pos, rbuf, 1); + + if (res == 1) + { + if (count > bytes_per_sector - first_offs) + { + rsize = bytes_per_sector - first_offs; + } + else + { + rsize = count; + } + rt_memcpy(buf, rbuf + first_offs, rsize); + ++blk_pos; + + /* + ** #2: read continuous block size. + */ + while (rsize < count) + { + res = rt_device_read(dev, blk_pos++, rbuf, 1); + + if (res != 1) + { + break; + } + + if (count - rsize >= bytes_per_sector) + { + rt_memcpy(buf + rsize, rbuf, bytes_per_sector); + rsize += bytes_per_sector; + } + else + { + rt_memcpy(buf + rsize, rbuf, count - rsize); + rsize = count; + } + } + + *pos += rsize; + } + + rt_free(rbuf); + } + + return rsize; +} + +static ssize_t blk_fops_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos) +{ + void *rbuf; + rt_ssize_t res = 0; + int bytes_per_sector, blk_pos, first_offs, wsize = 0; + struct rt_device *dev = file->vnode->data; + struct blk_fops_data *data = dev->user_data; + + bytes_per_sector = data->geometry.bytes_per_sector; + blk_pos = *pos / bytes_per_sector; + first_offs = *pos % bytes_per_sector; + + /* + ** #1: write first unalign block size. + */ + if (first_offs != 0) + { + if (count > bytes_per_sector - first_offs) + { + wsize = bytes_per_sector - first_offs; + } + else + { + wsize = count; + } + + if ((rbuf = rt_malloc(bytes_per_sector))) + { + res = rt_device_read(dev, blk_pos, rbuf, 1); + + if (res == 1) + { + rt_memcpy(rbuf + first_offs, buf, wsize); + res = rt_device_write(dev, blk_pos, (const void *)rbuf, 1); + + if (res == 1) + { + blk_pos += 1; + rt_free(rbuf); + + goto _goon; + } + } + + rt_free(rbuf); + } + + return 0; + } + +_goon: + /* + ** #2: write continuous block size. + */ + if ((count - wsize) / bytes_per_sector != 0) + { + res = rt_device_write(dev, blk_pos, buf + wsize, (count - wsize) / bytes_per_sector); + wsize += res * bytes_per_sector; + blk_pos += res; + + if (res != (count - wsize) / bytes_per_sector) + { + *pos += wsize; + return wsize; + } + } + + /* + ** # 3: write last unalign block size. + */ + if ((count - wsize) != 0) + { + if ((rbuf = rt_malloc(bytes_per_sector))) + { + res = rt_device_read(dev, blk_pos, rbuf, 1); + + if (res == 1) + { + rt_memcpy(rbuf, buf + wsize, count - wsize); + res = rt_device_write(dev, blk_pos, (const void *)rbuf, 1); + + if (res == 1) + { + wsize += count - wsize; + } + } + + rt_free(rbuf); + } + } + + *pos += wsize; + return wsize; +} + +static int blk_fops_flush(struct dfs_file *file) +{ + struct rt_device *dev = file->vnode->data; + + return (int)rt_device_control(dev, RT_DEVICE_CTRL_BLK_SYNC, RT_NULL); +} + +static int blk_fops_poll(struct dfs_file *file, struct rt_pollreq *req) +{ + int mask = 0; + + return mask; +} + +const static struct dfs_file_ops blk_fops = +{ + .open = blk_fops_open, + .close = blk_fops_close, + .ioctl = blk_fops_ioctl, + .read = blk_fops_read, + .write = blk_fops_write, + .flush = blk_fops_flush, + .lseek = generic_dfs_lseek, + .poll = blk_fops_poll +}; + +void device_set_blk_fops(struct rt_device *dev) +{ + dev->fops = &blk_fops; +} +#else +void device_set_blk_fops(struct rt_device *dev) +{ +} +#endif /* RT_USING_POSIX_DEVIO && RT_USING_DFS_V2 */ + +void device_get_blk_ssize(struct rt_device *dev, void *args) +{ + rt_uint32_t bytes_per_sector; + struct rt_device_blk_geometry geometry; + + rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry); + bytes_per_sector = geometry.bytes_per_sector; + + RT_ASSERT(sizeof(bytes_per_sector) == sizeof(geometry.bytes_per_sector)); + + rt_memcpy(args, &bytes_per_sector, sizeof(bytes_per_sector)); +} + +void device_get_all_blk_ssize(struct rt_device *dev, void *args) +{ + rt_uint64_t count_mul_per; + struct rt_device_blk_geometry geometry; + + rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry); + count_mul_per = geometry.bytes_per_sector * geometry.sector_count; + + rt_memcpy(args, &count_mul_per, sizeof(count_mul_per)); +} diff --git a/components/drivers/block/blk_dfs.h b/components/drivers/block/blk_dfs.h new file mode 100644 index 00000000000..c532869fc7d --- /dev/null +++ b/components/drivers/block/blk_dfs.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-08 GuEe-GUI first version + */ + +#ifndef __BLK_DFS_H__ +#define __BLK_DFS_H__ + +#include + +#define RT_DEVICE_CTRL_BLK_SSIZEGET 0x00001268 /**< get number of bytes per sector */ +#define RT_DEVICE_CTRL_ALL_BLK_SSIZEGET 0x80081272 /**< get number of bytes per sector * sector counts */ + +void device_set_blk_fops(struct rt_device *dev); +void device_get_blk_ssize(struct rt_device *dev, void *args); +void device_get_all_blk_ssize(struct rt_device *dev, void *args); + +#endif /* __BLK_DFS_H__ */ diff --git a/components/drivers/block/blk_partition.c b/components/drivers/block/blk_partition.c new file mode 100644 index 00000000000..5a9e39d1560 --- /dev/null +++ b/components/drivers/block/blk_partition.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI the first version + */ + +#define DBG_TAG "blk.part" +#define DBG_LVL DBG_INFO +#include + +#include "blk_partition.h" + +static rt_err_t (*partition_list[])(struct rt_blk_disk *) = +{ +#ifdef RT_BLK_PARTITION_EFI + efi_partition, +#endif +#ifdef RT_BLK_PARTITION_DFS + dfs_partition, +#endif +}; + +rt_err_t blk_put_partition(struct rt_blk_disk *disk, const char *type, + rt_size_t start, rt_size_t count, int partno) +{ + rt_err_t err; + + struct rt_blk_device *blk = rt_calloc(1, sizeof(*blk)); + + if (type && rt_strcmp(type, "dfs")) + { + rt_uint32_t ssz = rt_blk_disk_get_logical_block_size(disk); + + rt_kprintf("found part[%u], begin: %lu, size: ", partno, start * ssz); + + if ((count >> 11) == 0) + { + rt_kprintf("%u%cB\n", count >> 1, 'K'); /* KB */ + } + else + { + rt_uint32_t size_mb = count >> 11; /* MB */ + + if ((size_mb >> 10) == 0) + { + rt_kprintf("%u.%u%cB\n", size_mb, (count >> 1) & 0x3ff, 'M'); + } + else + { + rt_kprintf("%u.%u%cB\n", size_mb >> 10, size_mb & 0x3ff, 'G'); + } + } + } + + if (!blk) + { + err = -RT_ENOMEM; + goto _fail; + } + + err = blk_dev_initialize(blk); + + if (err) + { + goto _fail; + } + + blk->partno = partno; + blk->sector_start = start; + blk->sector_count = count; + + blk->partition.offset = start; + blk->partition.size = count; + blk->partition.lock = &disk->usr_lock; + + err = disk_add_blk_dev(disk, blk); + + if (err) + { + goto _fail; + } + + ++disk->partitions; + + return RT_EOK; + +_fail: + LOG_E("%s: Put partition.%s[%u] start = %lu count = %lu error = %s", + to_disk_name(disk), type, partno, start, count, rt_strerror(err)); + + if (blk) + { + rt_free(blk); + } + + return err; +} + +rt_err_t rt_blk_disk_probe_partition(struct rt_blk_disk *disk) +{ + rt_err_t err = RT_EOK; + + if (!disk) + { + return -RT_EINVAL; + } + + LOG_D("%s: Probing disk partitions", to_disk_name(disk)); + + if (disk->partitions) + { + return err; + } + + err = -RT_EEMPTY; + + if (disk->max_partitions == RT_BLK_PARTITION_NONE) + { + LOG_D("%s: Unsupported partitions", to_disk_name(disk)); + + return err; + } + + for (int i = 0; i < RT_ARRAY_SIZE(partition_list); ++i) + { + rt_err_t part_err = partition_list[i](disk); + + if (part_err == -RT_ENOMEM) + { + err = part_err; + break; + } + + if (!part_err) + { + err = RT_EOK; + break; + } + } + + if ((err && err != -RT_ENOMEM) || disk->partitions == 0) + { + /* No partition found */ + rt_size_t total_sectors = rt_blk_disk_get_capacity(disk); + + err = blk_put_partition(disk, RT_NULL, 0, total_sectors, 0); + } + + return err; +} diff --git a/components/drivers/block/blk_partition.h b/components/drivers/block/blk_partition.h new file mode 100644 index 00000000000..fb7158f72b9 --- /dev/null +++ b/components/drivers/block/blk_partition.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI first version + */ + +#ifndef __BLK_PARTITION_H__ +#define __BLK_PARTITION_H__ + +#include "blk_dev.h" + +rt_err_t blk_put_partition(struct rt_blk_disk *disk, const char *type, + rt_size_t start, rt_size_t count, int partno); + +rt_err_t dfs_partition(struct rt_blk_disk *disk); +rt_err_t efi_partition(struct rt_blk_disk *disk); + +#endif /* __BLK_PARTITION_H__ */ diff --git a/components/drivers/block/partitions/Kconfig b/components/drivers/block/partitions/Kconfig new file mode 100644 index 00000000000..6df5e715f55 --- /dev/null +++ b/components/drivers/block/partitions/Kconfig @@ -0,0 +1,12 @@ +menu "Partition Types" + +config RT_BLK_PARTITION_DFS + bool "DFS Partition support" + depends on RT_USING_DFS + default y + +config RT_BLK_PARTITION_EFI + bool "EFI Globally Unique Identifier (GUID) Partition support" + default y + +endmenu diff --git a/components/drivers/block/partitions/SConscript b/components/drivers/block/partitions/SConscript new file mode 100644 index 00000000000..06b320b18d5 --- /dev/null +++ b/components/drivers/block/partitions/SConscript @@ -0,0 +1,18 @@ +from building import * + +group = [] + +cwd = GetCurrentDir() +CPPPATH = [cwd + '/../../include'] + +src = [] + +if GetDepend(['RT_BLK_PARTITION_DFS']): + src += ['dfs.c'] + +if GetDepend(['RT_BLK_PARTITION_EFI']): + src += ['efi.c'] + +group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/block/partitions/dfs.c b/components/drivers/block/partitions/dfs.c new file mode 100644 index 00000000000..da4605e512b --- /dev/null +++ b/components/drivers/block/partitions/dfs.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-07-25 weety first version + * 2023-02-25 GuEe-GUI make blk interface + */ + +#include "efi.h" + +#define DBG_TAG "blk.part.dfs" +#define DBG_LVL DBG_INFO +#include + +rt_err_t dfs_partition(struct rt_blk_disk *disk) +{ + rt_ssize_t res; + struct dfs_partition part; + rt_uint8_t *sector = rt_malloc(rt_blk_disk_get_logical_block_size(disk)); + + if (!sector) + { + return -RT_ENOMEM; + } + + res = disk->ops->read(disk, 0, sector, 1); + + if (res < 0) + { + rt_free(sector); + return res; + } + + for (rt_size_t i = 0; i < disk->max_partitions; ++i) + { + res = dfs_filesystem_get_partition(&part, sector, i); + + if (res) + { + break; + } + + if (blk_put_partition(disk, "dfs", part.offset, part.size, i) == -RT_ENOMEM) + { + break; + } + } + + return RT_EOK; +} diff --git a/components/drivers/block/partitions/efi.c b/components/drivers/block/partitions/efi.c new file mode 100644 index 00000000000..a68a1470a1e --- /dev/null +++ b/components/drivers/block/partitions/efi.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-05 linzhenxing first version + * 2023-02-25 GuEe-GUI make blk interface + */ + +#include "efi.h" + +#define DBG_TAG "blk.part.efi" +#define DBG_LVL DBG_INFO +#include + +static rt_bool_t force_gpt = 0; + +static int force_gpt_setup(void) +{ +#ifdef RT_USING_OFW + force_gpt = !!rt_ofw_bootargs_select("gpt", 0); +#endif + + return 0; +} +INIT_CORE_EXPORT(force_gpt_setup); + +/** + * @brief This function is EFI version of crc32 function. + * + * @param buf the buffer to calculate crc32 of. + * @param len the length of buf. + * @return EFI-style CRC32 value for @buf. + */ +rt_inline rt_uint32_t efi_crc32(const rt_uint8_t *buf, rt_size_t len) +{ + rt_ubase_t crc = 0xffffffffUL; + + for (rt_size_t i = 0; i < len; ++i) + { + crc ^= buf[i]; + + for (int j = 0; j < 8; ++j) + { + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320L : 0); + } + } + + return ~crc; +} + +/** + * @brief This function get number of last logical block of device. + * + * @param disk the blk of disk. + * @return last LBA value on success, 0 on error. + * This is stored (by sd and ide-geometry) in + * the part[0] entry for this disk, and is the number of + * physical sectors available on the disk. + */ +static rt_size_t last_lba(struct rt_blk_disk *disk) +{ + return rt_blk_disk_get_capacity(disk) - 1ULL; +} + +rt_inline int pmbr_part_valid(gpt_mbr_record *part) +{ + if (part->os_type != EFI_PMBR_OSTYPE_EFI_GPT) + { + return 0; + } + + /* set to 0x00000001 (i.e., the LBA of the GPT Partition Header) */ + if (rt_le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA) + { + return 0; + } + + return GPT_MBR_PROTECTIVE; +} + +/** + * @brief This function test Protective MBR for validity. + * + * @param mbr the pointer to a legacy mbr structure. + * @param total_sectors the amount of sectors in the device + * @return + * 0 -> Invalid MBR + * 1 -> GPT_MBR_PROTECTIVE + * 2 -> GPT_MBR_HYBRID + */ +static int is_pmbr_valid(legacy_mbr *mbr, rt_size_t total_sectors) +{ + rt_uint32_t sz = 0; + int part = 0, ret = 0; /* invalid by default */ + + if (!mbr || rt_le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) + { + goto _done; + } + + for (int i = 0; i < 4; ++i) + { + ret = pmbr_part_valid(&mbr->partition_record[i]); + + if (ret == GPT_MBR_PROTECTIVE) + { + part = i; + /* + * Ok, we at least know that there's a protective MBR, + * now check if there are other partition types for + * hybrid MBR. + */ + goto _check_hybrid; + } + } + + if (ret != GPT_MBR_PROTECTIVE) + { + goto _done; + } + +_check_hybrid: + for (int i = 0; i < 4; i++) + { + if (mbr->partition_record[i].os_type != EFI_PMBR_OSTYPE_EFI_GPT && + mbr->partition_record[i].os_type != 0x00) + { + ret = GPT_MBR_HYBRID; + } + } + + /* + * Protective MBRs take up the lesser of the whole disk + * or 2 TiB (32bit LBA), ignoring the rest of the disk. + * Some partitioning programs, nonetheless, choose to set + * the size to the maximum 32-bit limitation, disregarding + * the disk size. + * + * Hybrid MBRs do not necessarily comply with this. + * + * Consider a bad value here to be a warning to support dd'ing + * an image from a smaller disk to a larger disk. + */ + if (ret == GPT_MBR_PROTECTIVE) + { + sz = rt_le32_to_cpu(mbr->partition_record[part].size_in_lba); + + if (sz != (rt_uint32_t)total_sectors - 1 && sz != 0xffffffff) + { + LOG_W("GPT: mbr size in lba (%u) different than whole disk (%u)", + sz, rt_min_t(rt_uint32_t, total_sectors - 1, 0xffffffff)); + } + } + +_done: + return ret; +} + +/** + * @brief This function read bytes from disk, starting at given LBA. + * + * @param disk the blk of disk. + * @param lba the Logical Block Address of the partition table. + * @param buffer the destination buffer. + * @param count the bytes to read. + * @return number of bytes read on success, 0 on error. + */ +static rt_size_t read_lba(struct rt_blk_disk *disk, + rt_uint64_t lba, rt_uint8_t *buffer, rt_size_t count) +{ + rt_size_t totalreadcount = 0; + + if (!buffer || lba > last_lba(disk)) + { + return 0; + } + + for (rt_uint64_t n = lba; count; ++n) + { + int copied = 512; + + disk->ops->read(disk, n, buffer, 1); + + if (copied > count) + { + copied = count; + } + + buffer += copied; + totalreadcount += copied; + count -= copied; + } + + return totalreadcount; +} + +/** + * @brief This function reads partition entries from disk. + * + * @param disk the blk of disk. + * @param gpt the GPT header + * @return ptes on success, null on error. + */ +static gpt_entry *alloc_read_gpt_entries(struct rt_blk_disk *disk, + gpt_header *gpt) +{ + rt_size_t count; + gpt_entry *pte; + rt_uint64_t entry_lba; + + if (!gpt) + { + return RT_NULL; + } + + count = (rt_size_t)rt_le32_to_cpu(gpt->num_partition_entries) * + rt_le32_to_cpu(gpt->sizeof_partition_entry); + + if (!count) + { + return RT_NULL; + } + + pte = rt_malloc(count); + + if (!pte) + { + return RT_NULL; + } + + entry_lba = rt_le64_to_cpu(gpt->partition_entry_lba); + + if (read_lba(disk, entry_lba, (rt_uint8_t *)pte, count) < count) + { + rt_free(pte); + pte = RT_NULL; + + return RT_NULL; + } + + /* Remember to free pte when done */ + return pte; +} + +/** + * @brief This function allocates GPT header, reads into it from disk. + * + * @param disk the blk of disk. + * @param lba the Logical Block Address of the partition table + * @return GPT header on success, null on error. + */ +static gpt_header *alloc_read_gpt_header(struct rt_blk_disk *disk, rt_uint64_t lba) +{ + gpt_header *gpt; + rt_uint32_t ssz = rt_blk_disk_get_logical_block_size(disk); + + gpt = rt_malloc(ssz); + + if (!gpt) + { + return RT_NULL; + } + + if (read_lba(disk, lba, (rt_uint8_t *)gpt, ssz) < ssz) + { + rt_free(gpt); + gpt = RT_NULL; + + return RT_NULL; + } + + /* Remember to free gpt when finished with it */ + return gpt; +} + +/** + * @brief This function tests one GPT header and PTEs for validity. + * + * @param disk the blk of disk. + * @param lba the Logical Block Address of the GPT header to test. + * @param gpt the GPT header ptr, filled on return. + * @param ptes the PTEs ptr, filled on return. + * @returns true if valid, false on error. + * If valid, returns pointers to newly allocated GPT header and PTEs. + */ +static rt_bool_t is_gpt_valid(struct rt_blk_disk *disk, + rt_uint64_t lba, gpt_header **gpt, gpt_entry **ptes) +{ + rt_uint32_t crc, origcrc; + rt_uint64_t lastlba, pt_size; + rt_ssize_t logical_block_size; + + if (!ptes) + { + return RT_FALSE; + } + + if (!(*gpt = alloc_read_gpt_header(disk, lba))) + { + return RT_FALSE; + } + + /* Check the GUID Partition Table signature */ + if (rt_le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) + { + LOG_D("%s: GUID Partition Table Header signature is wrong: %lld != %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu((*gpt)->signature), + (rt_uint64_t)GPT_HEADER_SIGNATURE); + + goto _fail; + } + + /* Check the GUID Partition Table header size is too big */ + logical_block_size = rt_blk_disk_get_logical_block_size(disk); + + if (rt_le32_to_cpu((*gpt)->header_size) > logical_block_size) + { + LOG_D("%s: GUID Partition Table Header size is too large: %u > %u", + to_disk_name(disk), + rt_le32_to_cpu((*gpt)->header_size), + logical_block_size); + + goto _fail; + } + + /* Check the GUID Partition Table header size is too small */ + if (rt_le32_to_cpu((*gpt)->header_size) < sizeof(gpt_header)) + { + LOG_D("%s: GUID Partition Table Header size is too small: %u < %u", + to_disk_name(disk), + rt_le32_to_cpu((*gpt)->header_size), + sizeof(gpt_header)); + + goto _fail; + } + + /* Check the GUID Partition Table CRC */ + origcrc = rt_le32_to_cpu((*gpt)->header_crc32); + (*gpt)->header_crc32 = 0; + crc = efi_crc32((const rt_uint8_t *)(*gpt), rt_le32_to_cpu((*gpt)->header_size)); + + if (crc != origcrc) + { + LOG_D("%s: GUID Partition Table Header CRC is wrong: %x != %x", + to_disk_name(disk), crc, origcrc); + + goto _fail; + } + + (*gpt)->header_crc32 = rt_cpu_to_le32(origcrc); + + /* + * Check that the start_lba entry points to the LBA that contains + * the GUID Partition Table + */ + if (rt_le64_to_cpu((*gpt)->start_lba) != lba) + { + LOG_D("%s: GPT start_lba incorrect: %lld != %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu((*gpt)->start_lba), + (rt_uint64_t)lba); + + goto _fail; + } + + /* Check the first_usable_lba and last_usable_lba are within the disk */ + lastlba = last_lba(disk); + + if (rt_le64_to_cpu((*gpt)->first_usable_lba) > lastlba) + { + LOG_D("%s: GPT: first_usable_lba incorrect: %lld > %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu((*gpt)->first_usable_lba), + (rt_uint64_t)lastlba); + + goto _fail; + } + + if (rt_le64_to_cpu((*gpt)->last_usable_lba) > lastlba) + { + LOG_D("%s: GPT: last_usable_lba incorrect: %lld > %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu((*gpt)->last_usable_lba), + (rt_uint64_t)lastlba); + + goto _fail; + } + if (rt_le64_to_cpu((*gpt)->last_usable_lba) < rt_le64_to_cpu((*gpt)->first_usable_lba)) + { + LOG_D("%s: GPT: last_usable_lba incorrect: %lld > %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu((*gpt)->last_usable_lba), + (rt_uint64_t)rt_le64_to_cpu((*gpt)->first_usable_lba)); + + goto _fail; + } + + /* Check that sizeof_partition_entry has the correct value */ + if (rt_le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) + { + LOG_D("%s: GUID Partition Entry Size check failed", to_disk_name(disk)); + + goto _fail; + } + + /* Sanity check partition table size */ + pt_size = (rt_uint64_t)rt_le32_to_cpu((*gpt)->num_partition_entries) * + rt_le32_to_cpu((*gpt)->sizeof_partition_entry); + + if (!(*ptes = alloc_read_gpt_entries(disk, *gpt))) + { + goto _fail; + } + + /* Check the GUID Partition Entry Array CRC */ + crc = efi_crc32((const rt_uint8_t *)(*ptes), pt_size); + + if (crc != rt_le32_to_cpu((*gpt)->partition_entry_array_crc32)) + { + LOG_D("%s: GUID Partition Entry Array CRC check failed", to_disk_name(disk)); + + goto _fail_ptes; + } + + /* We're done, all's well */ + return RT_TRUE; + +_fail_ptes: + rt_free(*ptes); + *ptes = RT_NULL; + +_fail: + rt_free(*gpt); + *gpt = RT_NULL; + + return RT_FALSE; +} + +/** + * @brief This function tests one PTE for validity. + * + * @param pte the pte to check. + * @param lastlba the last lba of the disk. + * @return valid boolean of pte. + */ +rt_inline rt_bool_t is_pte_valid(const gpt_entry *pte, const rt_size_t lastlba) +{ + if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) || + rt_le64_to_cpu(pte->starting_lba) > lastlba || + rt_le64_to_cpu(pte->ending_lba) > lastlba) + { + return RT_FALSE; + } + + return RT_TRUE; +} + +/** + * @brief This function search disk for valid GPT headers and PTEs. + * + * @param disk the blk of disk. + * @param pgpt the primary GPT header. + * @param agpt the alternate GPT header. + * @param lastlba the last LBA number. + */ +static void compare_gpts(struct rt_blk_disk *disk, + gpt_header *pgpt, gpt_header *agpt, rt_uint64_t lastlba) +{ + int error_found = 0; + + if (!pgpt || !agpt) + { + return; + } + + if (rt_le64_to_cpu(pgpt->start_lba) != rt_le64_to_cpu(agpt->alternate_lba)) + { + LOG_W("%s: GPT:Primary header LBA(%lld) != Alt(%lld), header alternate_lba", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu(pgpt->start_lba), + (rt_uint64_t)rt_le64_to_cpu(agpt->alternate_lba)); + + ++error_found; + } + + if (rt_le64_to_cpu(pgpt->alternate_lba) != rt_le64_to_cpu(agpt->start_lba)) + { + LOG_W("%s: GPT:Primary header alternate_lba(%lld) != Alt(%lld), header start_lba", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu(pgpt->alternate_lba), + (rt_uint64_t)rt_le64_to_cpu(agpt->start_lba)); + + ++error_found; + } + + if (rt_le64_to_cpu(pgpt->first_usable_lba) != rt_le64_to_cpu(agpt->first_usable_lba)) + { + LOG_W("%s: GPT:first_usable_lbas don't match %lld != %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu(pgpt->first_usable_lba), + (rt_uint64_t)rt_le64_to_cpu(agpt->first_usable_lba)); + + ++error_found; + } + + if (rt_le64_to_cpu(pgpt->last_usable_lba) != rt_le64_to_cpu(agpt->last_usable_lba)) + { + LOG_W("%s: GPT:last_usable_lbas don't match %lld != %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu(pgpt->last_usable_lba), + (rt_uint64_t)rt_le64_to_cpu(agpt->last_usable_lba)); + + ++error_found; + } + + if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) + { + LOG_W("%s: GPT:disk_guids don't match", to_disk_name(disk)); + + ++error_found; + } + + if (rt_le32_to_cpu(pgpt->num_partition_entries) != + rt_le32_to_cpu(agpt->num_partition_entries)) + { + LOG_W("%s: GPT:num_partition_entries don't match: 0x%x != 0x%x", + to_disk_name(disk), + rt_le32_to_cpu(pgpt->num_partition_entries), + rt_le32_to_cpu(agpt->num_partition_entries)); + + ++error_found; + } + + if (rt_le32_to_cpu(pgpt->sizeof_partition_entry) != + rt_le32_to_cpu(agpt->sizeof_partition_entry)) + { + LOG_W("%s: GPT:sizeof_partition_entry values don't match: 0x%x != 0x%x", + to_disk_name(disk), + rt_le32_to_cpu(pgpt->sizeof_partition_entry), + rt_le32_to_cpu(agpt->sizeof_partition_entry)); + + ++error_found; + } + + if (rt_le32_to_cpu(pgpt->partition_entry_array_crc32) != + rt_le32_to_cpu(agpt->partition_entry_array_crc32)) + { + LOG_W("%s: GPT:partition_entry_array_crc32 values don't match: 0x%x != 0x%x", + to_disk_name(disk), + rt_le32_to_cpu(pgpt->partition_entry_array_crc32), + rt_le32_to_cpu(agpt->partition_entry_array_crc32)); + + ++error_found; + } + + if (rt_le64_to_cpu(pgpt->alternate_lba) != lastlba) + { + LOG_W("%s: GPT:Primary header thinks Alt. header is not at the end of the disk: %lld != %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu(pgpt->alternate_lba), + (rt_uint64_t)lastlba); + + ++error_found; + } + + if (rt_le64_to_cpu(agpt->start_lba) != lastlba) + { + LOG_W("%s: GPT:Alternate GPT header not at the end of the disk: %lld != %lld", + to_disk_name(disk), + (rt_uint64_t)rt_le64_to_cpu(agpt->start_lba), + (rt_uint64_t)lastlba); + + ++error_found; + } + + if (error_found) + { + LOG_W("GPT: Use GNU Parted to correct GPT errors"); + } +} + +/** + * @brief This function search disk for valid GPT headers and PTEs. + * + * @param disk the disk parsed partitions. + * @param gpt the GPT header ptr, filled on return. + * @param ptes the PTEs ptr, filled on return. + * @return 1 if valid, 0 on error. + * If valid, returns pointers to newly allocated GPT header and PTEs. + * Validity depends on PMBR being valid (or being overridden by the + * 'gpt' kernel command line option) and finding either the Primary + * GPT header and PTEs valid, or the Alternate GPT header and PTEs + * valid. If the Primary GPT header is not valid, the Alternate GPT header + * is not checked unless the 'gpt' kernel command line option is passed. + * This protects against devices which misreport their size, and forces + * the user to decide to use the Alternate GPT. + */ +static rt_bool_t find_valid_gpt(struct rt_blk_disk *disk, + gpt_header **gpt, gpt_entry **ptes) +{ + int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; + gpt_header *pgpt = RT_NULL, *agpt = RT_NULL; + gpt_entry *pptes = RT_NULL, *aptes = RT_NULL; + legacy_mbr *legacymbr; + rt_size_t total_sectors = rt_blk_disk_get_capacity(disk); + rt_size_t lastlba; + + if (!ptes) + { + return RT_FALSE; + } + + lastlba = last_lba(disk); + + if (!force_gpt) + { + /* This will be added to the EFI Spec. per Intel after v1.02. */ + legacymbr = rt_malloc(sizeof(*legacymbr)); + + if (!legacymbr) + { + return RT_FALSE; + } + + read_lba(disk, 0, (rt_uint8_t *)legacymbr, sizeof(*legacymbr)); + good_pmbr = is_pmbr_valid(legacymbr, total_sectors); + rt_free(legacymbr); + + if (!good_pmbr) + { + return RT_FALSE; + } + + LOG_D("%s: Device has a %s MBR", to_disk_name(disk), + good_pmbr == GPT_MBR_PROTECTIVE ? "protective" : "hybrid"); + } + + good_pgpt = is_gpt_valid(disk, GPT_PRIMARY_PARTITION_TABLE_LBA, &pgpt, &pptes); + + if (good_pgpt) + { + good_agpt = is_gpt_valid(disk, rt_le64_to_cpu(pgpt->alternate_lba), &agpt, &aptes); + } + + if (!good_agpt && force_gpt) + { + good_agpt = is_gpt_valid(disk, lastlba, &agpt, &aptes); + } + + /* The obviously unsuccessful case */ + if (!good_pgpt && !good_agpt) + { + goto _fail; + } + + compare_gpts(disk, pgpt, agpt, lastlba); + + /* The good cases */ + if (good_pgpt) + { + *gpt = pgpt; + *ptes = pptes; + rt_free(agpt); + rt_free(aptes); + + if (!good_agpt) + { + LOG_D("%s: Alternate GPT is invalid, using primary GPT", to_disk_name(disk)); + } + + return RT_TRUE; + } + else if (good_agpt) + { + *gpt = agpt; + *ptes = aptes; + rt_free(pgpt); + rt_free(pptes); + + LOG_D("%s: Primary GPT is invalid, using alternate GPT", to_disk_name(disk)); + + return RT_TRUE; + } + +_fail: + rt_free(pgpt); + rt_free(agpt); + rt_free(pptes); + rt_free(aptes); + + *gpt = RT_NULL; + *ptes = RT_NULL; + + return RT_FALSE; +} + +rt_err_t efi_partition(struct rt_blk_disk *disk) +{ + rt_uint32_t entries_nr; + gpt_header *gpt = RT_NULL; + gpt_entry *ptes = RT_NULL; + + if (!find_valid_gpt(disk, &gpt, &ptes) || !gpt || !ptes) + { + rt_free(gpt); + rt_free(ptes); + + return -RT_EINVAL; + } + + entries_nr = rt_le32_to_cpu(gpt->num_partition_entries); + + for (int i = 0; i < entries_nr && i < disk->max_partitions; ++i) + { + rt_uint64_t start = rt_le64_to_cpu(ptes[i].starting_lba); + rt_uint64_t size = rt_le64_to_cpu(ptes[i].ending_lba) - + rt_le64_to_cpu(ptes[i].starting_lba) + 1ULL; + + if (!is_pte_valid(&ptes[i], last_lba(disk))) + { + continue; + } + + if (blk_put_partition(disk, "gpt", start, size, i) == -RT_ENOMEM) + { + break; + } + } + + rt_free(gpt); + rt_free(ptes); + + return RT_EOK; +} diff --git a/components/drivers/block/partitions/efi.h b/components/drivers/block/partitions/efi.h new file mode 100644 index 00000000000..6a10ec884f4 --- /dev/null +++ b/components/drivers/block/partitions/efi.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-05 linzhenxing first version + * 2023-02-25 GuEe-GUI make blk interface + */ + +#ifndef __PARTITIONS_EFI_H__ +#define __PARTITIONS_EFI_H__ + +#include "../blk_partition.h" +#include +#include + +#define MSDOS_MBR_SIGNATURE 0xaa55 +#define EFI_PMBR_OSTYPE_EFI 0xef +#define EFI_PMBR_OSTYPE_EFI_GPT 0xee + +#define GPT_MBR_PROTECTIVE 1 +#define GPT_MBR_HYBRID 2 + +#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL +#define GPT_HEADER_REVISION_V1 0x00010000 +#define GPT_PRIMARY_PARTITION_TABLE_LBA 1 + +#ifndef __UUID_H__ +#define UUID_SIZE 16 + +typedef struct +{ + rt_uint8_t b[UUID_SIZE]; +} guid_t; +#endif /* __UUID_H__ */ + +#ifndef __EFI_H__ +typedef guid_t efi_guid_t rt_align(4); + +#define EFI_GUID(a, b, c, d...) (efi_guid_t) \ +{{ \ + (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + d \ +}} + +#define NULL_GUID \ + EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + +rt_inline int efi_guidcmp(efi_guid_t left, efi_guid_t right) +{ + return rt_memcmp(&left, &right, sizeof (efi_guid_t)); +} +#endif /* __EFI_H__ */ + +#define PARTITION_SYSTEM_GUID \ + EFI_GUID(0xc12a7328, 0xf81f, 0x11d2, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b) + +#define LEGACY_MBR_PARTITION_GUID \ + EFI_GUID(0x024dee41, 0x33e7, 0x11d3, 0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f) + +#define PARTITION_MSFT_RESERVED_GUID \ + EFI_GUID(0xe3c9e316, 0x0b5c, 0x4db8, 0x81, 0x7d, 0xf9, 0x2d, 0xf0, 0x02, 0x15, 0xae) + +#define PARTITION_BASIC_DATA_GUID \ + EFI_GUID(0xebd0a0a2, 0xb9e5, 0x4433, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7) + +rt_packed(struct _gpt_header +{ + rt_le64_t signature; + rt_le32_t revision; + rt_le32_t header_size; + rt_le32_t header_crc32; + rt_le32_t reserved1; + rt_le64_t start_lba; + rt_le64_t alternate_lba; + rt_le64_t first_usable_lba; + rt_le64_t last_usable_lba; + efi_guid_t disk_guid; + rt_le64_t partition_entry_lba; + rt_le32_t num_partition_entries; + rt_le32_t sizeof_partition_entry; + rt_le32_t partition_entry_array_crc32; + + /* + * The rest of the logical block is reserved by UEFI and must be zero. + * EFI standard handles this by: + * + * uint8_t reserved2[BlockSize - 92]; + */ +}); +typedef struct _gpt_header gpt_header; + +rt_packed(struct _gpt_entry_attributes +{ + rt_uint64_t required_to_function:1; + rt_uint64_t reserved:47; + rt_uint64_t type_guid_specific:16; +}); +typedef struct _gpt_entry_attributes gpt_entry_attributes; + +rt_packed(struct _gpt_entry +{ + efi_guid_t partition_type_guid; + efi_guid_t unique_partition_guid; + rt_le64_t starting_lba; + rt_le64_t ending_lba; + gpt_entry_attributes attributes; + rt_le16_t partition_name[72/sizeof(rt_le16_t)]; +}); +typedef struct _gpt_entry gpt_entry; + +rt_packed(struct _gpt_mbr_record +{ + rt_uint8_t boot_indicator; /* unused by EFI, set to 0x80 for bootable */ + rt_uint8_t start_head; /* unused by EFI, pt start in CHS */ + rt_uint8_t start_sector; /* unused by EFI, pt start in CHS */ + rt_uint8_t start_track; + rt_uint8_t os_type; /* EFI and legacy non-EFI OS types */ + rt_uint8_t end_head; /* unused by EFI, pt end in CHS */ + rt_uint8_t end_sector; /* unused by EFI, pt end in CHS */ + rt_uint8_t end_track; /* unused by EFI, pt end in CHS */ + rt_le32_t starting_lba; /* used by EFI - start addr of the on disk pt */ + rt_le32_t size_in_lba; /* used by EFI - size of pt in LBA */ +}); +typedef struct _gpt_mbr_record gpt_mbr_record; + +rt_packed(struct _legacy_mbr +{ + rt_uint8_t boot_code[440]; + rt_le32_t unique_mbr_signature; + rt_le16_t unknown; + gpt_mbr_record partition_record[4]; + rt_le16_t signature; +}); +typedef struct _legacy_mbr legacy_mbr; + +#endif /* __PARTITIONS_EFI_H__ */ diff --git a/components/drivers/include/drivers/blk.h b/components/drivers/include/drivers/blk.h new file mode 100644 index 00000000000..42159c4688b --- /dev/null +++ b/components/drivers/include/drivers/blk.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI first version + */ + +#ifndef __BLK_H__ +#define __BLK_H__ + +#include +#include +#include + +struct rt_dm_ida; +struct rt_blk_device; +struct rt_blk_disk_ops; + +struct rt_blk_disk +{ + struct rt_device parent; + + const struct rt_blk_disk_ops *ops; +#ifdef RT_USING_DM + struct rt_dm_ida *ida; +#endif + + rt_uint32_t read_only:1; + rt_uint32_t parallel_io:1; + rt_uint32_t removable:1; +#define RT_BLK_DISK_MAGIC 0xbdaabdaa + rt_uint32_t __magic; + + rt_uint32_t partitions; +#define RT_BLK_PARTITION_NONE (-1) +#define RT_BLK_PARTITION_MAX (RT_UINT32_MAX >> 1) + rt_int32_t max_partitions; + rt_list_t part_nodes; + + struct rt_spinlock lock; + struct rt_semaphore usr_lock; +}; + +struct rt_blk_disk_ops +{ + rt_ssize_t (*read)(struct rt_blk_disk *disk, rt_off_t sector, void *buffer, + rt_size_t sector_count); + rt_ssize_t (*write)(struct rt_blk_disk *disk, rt_off_t sector, const void *buffer, + rt_size_t sector_count); + rt_err_t (*getgeome)(struct rt_blk_disk *disk, struct rt_device_blk_geometry *geometry); + rt_err_t (*sync)(struct rt_blk_disk *disk); + rt_err_t (*erase)(struct rt_blk_disk *disk); + rt_err_t (*autorefresh)(struct rt_blk_disk *disk, rt_bool_t is_auto); + rt_err_t (*control)(struct rt_blk_disk *disk, struct rt_blk_device *blk, int cmd, void *args); +}; + +#ifndef __DFS_H__ +#include + +struct rt_blk_device +{ + struct rt_device parent; + + int partno; + struct dfs_partition partition; + + rt_list_t list; + struct rt_blk_disk *disk; + + rt_size_t sector_start; + rt_size_t sector_count; +}; +#else +struct rt_blk_device; +#endif /* __DFS_H__ */ + +rt_err_t rt_hw_blk_disk_register(struct rt_blk_disk *disk); +rt_err_t rt_hw_blk_disk_unregister(struct rt_blk_disk *disk); + +rt_err_t rt_blk_disk_probe_partition(struct rt_blk_disk *disk); +rt_ssize_t rt_blk_disk_get_capacity(struct rt_blk_disk *disk); +rt_ssize_t rt_blk_disk_get_logical_block_size(struct rt_blk_disk *disk); + +#endif /* __BLK_H__ */ diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index c8ed3c04899..2218b79911f 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -45,6 +45,10 @@ extern "C" { #include "drivers/core/power_domain.h" #include "drivers/platform.h" +#ifdef RT_USING_BLK +#include "drivers/blk.h" +#endif + #ifdef RT_USING_OFW #include "drivers/ofw.h" #include "drivers/ofw_fdt.h" From 5df8b54ef3305e30cd3f8eb12c0332a3d43bc4b3 Mon Sep 17 00:00:00 2001 From: GuEe-GUI <2991707448@qq.com> Date: Wed, 30 Oct 2024 11:41:07 +0800 Subject: [PATCH 2/3] [DEVICE/SDIO] port to the block 1. remove gpt. 2. remove block device custom. Signed-off-by: GuEe-GUI <2991707448@qq.com> --- components/drivers/include/drivers/dev_gpt.h | 132 ---- .../drivers/include/drivers/dev_mmcsd_core.h | 2 - .../drivers/include/drivers/mmcsd_card.h | 2 +- .../drivers/include/drivers/mmcsd_host.h | 1 + components/drivers/sdio/Kconfig | 1 + components/drivers/sdio/SConscript | 1 - components/drivers/sdio/dev_block.c | 716 +++--------------- components/drivers/sdio/dev_gpt.c | 563 -------------- 8 files changed, 96 insertions(+), 1322 deletions(-) delete mode 100644 components/drivers/include/drivers/dev_gpt.h delete mode 100644 components/drivers/sdio/dev_gpt.c diff --git a/components/drivers/include/drivers/dev_gpt.h b/components/drivers/include/drivers/dev_gpt.h deleted file mode 100644 index 269208e82cf..00000000000 --- a/components/drivers/include/drivers/dev_gpt.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-05-05 linzhenxing first version - */ -#ifndef __DEV_GPT_H__ -#define __DEV_GPT_H__ - -#include -#include - -typedef struct -{ - uint8_t b[16]; /* GUID 16 bytes*/ -} guid_t; - -#define MSDOS_MBR_SIGNATURE 0xaa55 -#define EFI_PMBR_OSTYPE_EFI 0xEF -#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE - -#define GPT_MBR_PROTECTIVE 1 -#define GPT_MBR_HYBRID 2 - -#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL -#define GPT_HEADER_REVISION_V1 0x00010000 -#define GPT_PRIMARY_PARTITION_TABLE_LBA 1 - -typedef guid_t gpt_guid_t __attribute__ ((aligned (4))); -#define EFI_GUID(a, b, c, d...) (gpt_guid_t){ { \ - (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ - (b) & 0xff, ((b) >> 8) & 0xff, \ - (c) & 0xff, ((c) >> 8) & 0xff, d } } - -#define NULL_GUID \ - EFI_GUID(0x00000000, 0x0000, 0x0000,\ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) -#define PARTITION_SYSTEM_GUID \ - EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \ - 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B) -#define LEGACY_MBR_PARTITION_GUID \ - EFI_GUID( 0x024DEE41, 0x33E7, 0x11d3, \ - 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F) -#define PARTITION_MSFT_RESERVED_GUID \ - EFI_GUID( 0xE3C9E316, 0x0B5C, 0x4DB8, \ - 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE) -#define PARTITION_BASIC_DATA_GUID \ - EFI_GUID( 0xEBD0A0A2, 0xB9E5, 0x4433, \ - 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7) -#define PARTITION_LINUX_RAID_GUID \ - EFI_GUID( 0xa19d880f, 0x05fc, 0x4d3b, \ - 0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e) -#define PARTITION_LINUX_SWAP_GUID \ - EFI_GUID( 0x0657fd6d, 0xa4ab, 0x43c4, \ - 0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f) -#define PARTITION_LINUX_LVM_GUID \ - EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \ - 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28) -#pragma pack(push, 1) -typedef struct _gpt_header -{ - uint64_t signature; - uint32_t revision; - uint32_t header_size; - uint32_t header_crc32; - uint32_t reserved1; - uint64_t start_lba; /*GPT head start sector*/ - uint64_t alternate_lba; /*GPT head alternate sector*/ - uint64_t first_usable_lba; - uint64_t last_usable_lba; - gpt_guid_t disk_guid; - uint64_t partition_entry_lba; - uint32_t num_partition_entries; - uint32_t sizeof_partition_entry; - uint32_t partition_entry_array_crc32; - - /* The rest of the logical block is reserved by UEFI and must be zero. - * EFI standard handles this by: - * - * uint8_t reserved2[ BlockSize - 92 ]; - */ -} gpt_header; - -typedef struct _gpt_entry_attributes -{ - uint64_t required_to_function:1; - uint64_t reserved:47; - uint64_t type_guid_specific:16; -} gpt_entry_attributes; - -typedef struct _gpt_entry -{ - gpt_guid_t partition_type_guid; - gpt_guid_t unique_partition_guid; - uint64_t starting_lba; - uint64_t ending_lba; - gpt_entry_attributes attributes; - uint16_t partition_name[72/sizeof(uint16_t)]; -} gpt_entry; - -typedef struct _gpt_mbr_record -{ - uint8_t boot_indicator; /* unused by EFI, set to 0x80 for bootable */ - uint8_t start_head; /* unused by EFI, pt start in CHS */ - uint8_t start_sector; /* unused by EFI, pt start in CHS */ - uint8_t start_track; - uint8_t os_type; /* EFI and legacy non-EFI OS types */ - uint8_t end_head; /* unused by EFI, pt end in CHS */ - uint8_t end_sector; /* unused by EFI, pt end in CHS */ - uint8_t end_track; /* unused by EFI, pt end in CHS */ - uint32_t starting_lba; /* used by EFI - start addr of the on disk pt */ - uint32_t size_in_lba; /* used by EFI - size of pt in LBA */ -} gpt_mbr_record; - - -typedef struct _legacy_mbr -{ - uint8_t boot_code[440]; - uint32_t unique_mbr_signature; - uint16_t unknown; - gpt_mbr_record partition_record[4]; - uint16_t signature; -} legacy_mbr; -#pragma pack(pop) - -int check_gpt(struct rt_mmcsd_card *card); -int gpt_get_partition_param(struct rt_mmcsd_card *card, struct dfs_partition *part, uint32_t pindex); -void gpt_free(void); -#endif /*__DEV_GPT_H__*/ diff --git a/components/drivers/include/drivers/dev_mmcsd_core.h b/components/drivers/include/drivers/dev_mmcsd_core.h index b6bb1edcc58..c86e9dde481 100644 --- a/components/drivers/include/drivers/dev_mmcsd_core.h +++ b/components/drivers/include/drivers/dev_mmcsd_core.h @@ -249,8 +249,6 @@ struct rt_mmcsd_host *mmcsd_alloc_host(void); void mmcsd_free_host(struct rt_mmcsd_host *host); int rt_mmcsd_core_init(void); -int rt_mmcsd_blk_init(void); -rt_int32_t read_lba(struct rt_mmcsd_card *card, size_t lba, uint8_t *buffer, size_t count); rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card); void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card); diff --git a/components/drivers/include/drivers/mmcsd_card.h b/components/drivers/include/drivers/mmcsd_card.h index 13173f1413d..6d86760a78a 100644 --- a/components/drivers/include/drivers/mmcsd_card.h +++ b/components/drivers/include/drivers/mmcsd_card.h @@ -218,7 +218,7 @@ struct rt_mmcsd_card { struct rt_sdio_cccr cccr; /* common card info */ struct rt_sdio_cis cis; /* common tuple info */ struct rt_sdio_function *sdio_function[SDIO_MAX_FUNCTIONS + 1]; /* SDIO functions (devices) */ - rt_list_t blk_devices; /* for block device list */ + void *blk_dev; struct rt_mmc_ext_csd ext_csd; }; diff --git a/components/drivers/include/drivers/mmcsd_host.h b/components/drivers/include/drivers/mmcsd_host.h index 73c1b971d81..5632ee10753 100644 --- a/components/drivers/include/drivers/mmcsd_host.h +++ b/components/drivers/include/drivers/mmcsd_host.h @@ -134,6 +134,7 @@ struct rt_mmcsd_host #define MMCSD_SUP_HS200_1V2 (1 << 10) #define MMCSD_SUP_HS200 (MMCSD_SUP_HS200_1V2 | MMCSD_SUP_HS200_1V8) /* hs200 sdr */ #define MMCSD_SUP_NONREMOVABLE (1 << 11) +#define controller_is_removable(host) (!(host->flags & MMCSD_SUP_NONREMOVABLE)) #define MMCSD_SUP_HS400_1V8 (1 << 12) #define MMCSD_SUP_HS400_1V2 (1 << 13) #define MMCSD_SUP_HS400 (MMCSD_SUP_HS400_1V2 | MMCSD_SUP_HS400_1V8) /* hs400 ddr */ diff --git a/components/drivers/sdio/Kconfig b/components/drivers/sdio/Kconfig index e5bff4549d8..e318104932a 100644 --- a/components/drivers/sdio/Kconfig +++ b/components/drivers/sdio/Kconfig @@ -1,5 +1,6 @@ config RT_USING_SDIO bool "Using SD/MMC device drivers" + select RT_USING_BLK default n if RT_USING_SDIO diff --git a/components/drivers/sdio/SConscript b/components/drivers/sdio/SConscript index 57f05875331..04061a9e02a 100644 --- a/components/drivers/sdio/SConscript +++ b/components/drivers/sdio/SConscript @@ -7,7 +7,6 @@ dev_block.c dev_mmcsd_core.c dev_sd.c dev_sdio.c -dev_gpt.c dev_mmc.c """) diff --git a/components/drivers/sdio/dev_block.c b/components/drivers/sdio/dev_block.c index e4097bc329a..d4f8f62885d 100644 --- a/components/drivers/sdio/dev_block.c +++ b/components/drivers/sdio/dev_block.c @@ -5,15 +5,14 @@ * * Change Logs: * Date Author Notes - * 2011-07-25 weety first version + * 2011-07-25 weety first version + * 2023-08-08 GuEe-GUI port to the block */ #include -#include -#include - +#include +#include #include -#include #define DBG_TAG "SDIO" #ifdef RT_SDIO_DEBUG @@ -23,26 +22,24 @@ #endif /* RT_SDIO_DEBUG */ #include -static rt_list_t blk_devices = RT_LIST_OBJECT_INIT(blk_devices); - -#define BLK_MIN(a, b) ((a) < (b) ? (a) : (b)) -#define RT_DEVICE_CTRL_BLK_SSIZEGET 0x1268 /**< get number of bytes per sector */ -#define RT_DEVICE_CTRL_ALL_BLK_SSIZEGET 0x80081272 /**< get number of bytes per sector * sector counts*/ +#ifndef RT_MMCSD_MAX_PARTITION +#define RT_MMCSD_MAX_PARTITION 16 +#endif struct mmcsd_blk_device { + struct rt_blk_disk parent; struct rt_mmcsd_card *card; - rt_list_t list; - struct rt_device dev; - struct dfs_partition part; - struct rt_device_blk_geometry geometry; + rt_size_t max_req_size; + struct rt_device_blk_geometry geometry; }; -#ifndef RT_MMCSD_MAX_PARTITION -#define RT_MMCSD_MAX_PARTITION 16 +#define raw_to_mmcsd_blk(raw) rt_container_of(raw, struct mmcsd_blk_device, parent) + +#ifdef RT_USING_DM +static struct rt_dm_ida sdio_ida = RT_DM_IDA_INIT(SDIO); #endif -#define RT_GPT_PARTITION_MAX 128 static int __send_status(struct rt_mmcsd_card *card, rt_uint32_t *status, unsigned retries) { @@ -252,131 +249,6 @@ static rt_err_t rt_mmcsd_req_blk(struct rt_mmcsd_card *card, return RT_EOK; } -static rt_err_t rt_mmcsd_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t rt_mmcsd_open(rt_device_t dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t rt_mmcsd_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t rt_mmcsd_control(rt_device_t dev, int cmd, void *args) -{ - struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data; - - switch (cmd) - { - case RT_DEVICE_CTRL_BLK_GETGEOME: - rt_memcpy(args, &blk_dev->geometry, sizeof(struct rt_device_blk_geometry)); - break; - case RT_DEVICE_CTRL_BLK_PARTITION: - rt_memcpy(args, &blk_dev->part, sizeof(struct dfs_partition)); - break; - case RT_DEVICE_CTRL_BLK_SSIZEGET: - rt_memcpy(args, &blk_dev->geometry.bytes_per_sector, sizeof(rt_uint32_t)); - break; - case RT_DEVICE_CTRL_ALL_BLK_SSIZEGET: - { - rt_uint64_t count_mul_per = blk_dev->geometry.bytes_per_sector * blk_dev->geometry.sector_count; - rt_memcpy(args, &count_mul_per, sizeof(rt_uint64_t)); - } - break; - default: - break; - } - return RT_EOK; -} - -static rt_ssize_t rt_mmcsd_read(rt_device_t dev, - rt_off_t pos, - void *buffer, - rt_size_t size) -{ - rt_err_t err = 0; - rt_size_t offset = 0; - rt_size_t req_size = 0; - rt_size_t remain_size = size; - void *rd_ptr = (void *)buffer; - struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data; - struct dfs_partition *part = &blk_dev->part; - - if (dev == RT_NULL) - { - rt_set_errno(-EINVAL); - return 0; - } - - rt_sem_take(part->lock, RT_WAITING_FOREVER); - while (remain_size) - { - req_size = (remain_size > blk_dev->max_req_size) ? blk_dev->max_req_size : remain_size; - err = rt_mmcsd_req_blk(blk_dev->card, part->offset + pos + offset, rd_ptr, req_size, 0); - if (err) - break; - offset += req_size; - rd_ptr = (void *)((rt_uint8_t *)rd_ptr + (req_size << 9)); - remain_size -= req_size; - } - rt_sem_release(part->lock); - - /* the length of reading must align to SECTOR SIZE */ - if (err) - { - rt_set_errno(-EIO); - return 0; - } - return size - remain_size; -} - -static rt_ssize_t rt_mmcsd_write(rt_device_t dev, - rt_off_t pos, - const void *buffer, - rt_size_t size) -{ - rt_err_t err = 0; - rt_size_t offset = 0; - rt_size_t req_size = 0; - rt_size_t remain_size = size; - void *wr_ptr = (void *)buffer; - struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data; - struct dfs_partition *part = &blk_dev->part; - - if (dev == RT_NULL) - { - rt_set_errno(-EINVAL); - return 0; - } - - rt_sem_take(part->lock, RT_WAITING_FOREVER); - while (remain_size) - { - req_size = (remain_size > blk_dev->max_req_size) ? blk_dev->max_req_size : remain_size; - err = rt_mmcsd_req_blk(blk_dev->card, part->offset + pos + offset, wr_ptr, req_size, 1); - if (err) - break; - offset += req_size; - wr_ptr = (void *)((rt_uint8_t *)wr_ptr + (req_size << 9)); - remain_size -= req_size; - } - rt_sem_release(part->lock); - - /* the length of reading must align to SECTOR SIZE */ - if (err) - { - rt_set_errno(-EIO); - - return 0; - } - return size - remain_size; -} - static rt_int32_t mmcsd_set_blksize(struct rt_mmcsd_card *card) { struct rt_mmcsd_cmd cmd; @@ -402,551 +274,149 @@ static rt_int32_t mmcsd_set_blksize(struct rt_mmcsd_card *card) return 0; } -rt_int32_t read_lba(struct rt_mmcsd_card *card, size_t lba, uint8_t *buffer, size_t count) -{ - rt_uint8_t status = 0; - - status = mmcsd_set_blksize(card); - if (status) - { - return status; - } - rt_thread_mdelay(1); - status = rt_mmcsd_req_blk(card, lba, buffer, count, 0); - return status; -} - -#ifdef RT_USING_DEVICE_OPS -const static struct rt_device_ops mmcsd_blk_ops = -{ - rt_mmcsd_init, - rt_mmcsd_open, - rt_mmcsd_close, - rt_mmcsd_read, - rt_mmcsd_write, - rt_mmcsd_control -}; -#endif - -#ifdef RT_USING_DFS_V2 -static ssize_t rt_mmcsd_fops_read(struct dfs_file *file, void *buf, size_t count, off_t *pos) +static rt_ssize_t mmcsd_blk_read(struct rt_blk_disk *disk, rt_off_t sector, + void *buffer, rt_size_t sector_count) { - int result = 0; - rt_device_t dev = (rt_device_t)file->vnode->data; - struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data; - int bytes_per_sector = blk_dev->geometry.bytes_per_sector; - int blk_pos = *pos / bytes_per_sector; - int first_offs = *pos % bytes_per_sector; - char *rbuf; - int rsize = 0; - - rbuf = rt_malloc(bytes_per_sector); - if (!rbuf) - { - return 0; - } + rt_err_t err; + rt_size_t offset = 0; + rt_size_t req_size = 0; + rt_size_t remain_size = sector_count; + void *rd_ptr = (void *)buffer; + struct mmcsd_blk_device *blk_dev = raw_to_mmcsd_blk(disk); - /* - ** #1: read first unalign block size. - */ - result = rt_mmcsd_read(dev, blk_pos, rbuf, 1); - if (result != 1) + while (remain_size) { - rt_free(rbuf); - return 0; - } + req_size = rt_min_t(rt_size_t, remain_size, blk_dev->max_req_size); - if (count > bytes_per_sector - first_offs) - { - rsize = bytes_per_sector - first_offs; - } - else - { - rsize = count; - } - rt_memcpy(buf, rbuf + first_offs, rsize); - blk_pos++; + err = rt_mmcsd_req_blk(blk_dev->card, sector + offset, rd_ptr, req_size, 0); - /* - ** #2: read continuous block size. - */ - while (rsize < count) - { - result = rt_mmcsd_read(dev, blk_pos++, rbuf, 1); - if (result != 1) + if (err) { - break; + return err; } - if (count - rsize >= bytes_per_sector) - { - rt_memcpy(buf + rsize, rbuf, bytes_per_sector); - rsize += bytes_per_sector; - } - else - { - rt_memcpy(buf + rsize, rbuf, count - rsize); - rsize = count; - } + offset += req_size; + rd_ptr = (void *)((rt_uint8_t *)rd_ptr + (req_size << 9)); + remain_size -= req_size; } - rt_free(rbuf); - *pos += rsize; - - return rsize; + return sector_count - remain_size; } -static int rt_mmcsd_fops_ioctl(struct dfs_file *file, int cmd, void *arg) +static rt_ssize_t mmcsd_blk_write(struct rt_blk_disk *disk, rt_off_t sector, + const void *buffer, rt_size_t sector_count) { - rt_device_t dev = (rt_device_t)file->vnode->data; - - return rt_mmcsd_control(dev,cmd,arg); -} - -static int rt_mmcsd_fops_open(struct dfs_file *file) -{ - rt_device_t dev = (rt_device_t)file->vnode->data; - rt_mmcsd_control(dev, RT_DEVICE_CTRL_ALL_BLK_SSIZEGET, &file->vnode->size); - return RT_EOK; -} - -static int rt_mmcsd_fops_close(struct dfs_file *file) -{ - return RT_EOK; -} + rt_err_t err; + rt_size_t offset = 0; + rt_size_t req_size = 0; + rt_size_t remain_size = sector_count; + void *wr_ptr = (void *)buffer; + struct mmcsd_blk_device *blk_dev = raw_to_mmcsd_blk(disk); -static ssize_t rt_mmcsd_fops_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos) -{ - int result = 0; - rt_device_t dev = (rt_device_t)file->vnode->data; - struct mmcsd_blk_device *blk_dev = (struct mmcsd_blk_device *)dev->user_data; - int bytes_per_sector = blk_dev->geometry.bytes_per_sector; - int blk_pos = *pos / bytes_per_sector; - int first_offs = *pos % bytes_per_sector; - char *rbuf = 0; - int wsize = 0; - - /* - ** #1: write first unalign block size. - */ - if (first_offs != 0) + while (remain_size) { - if (count > bytes_per_sector - first_offs) - { - wsize = bytes_per_sector - first_offs; - } - else - { - wsize = count; - } - - rbuf = rt_malloc(bytes_per_sector); - if (!rbuf) - { - return 0; - } + req_size = rt_min_t(rt_size_t, remain_size, blk_dev->max_req_size); - result = rt_mmcsd_read(dev, blk_pos, rbuf, 1); - if (result != 1) - { - rt_free(rbuf); - return 0; - } + err = rt_mmcsd_req_blk(blk_dev->card, sector + offset, wr_ptr, req_size, 1); - rt_memcpy(rbuf + first_offs, buf, wsize); - result = rt_mmcsd_write(dev, blk_pos, rbuf, 1); - if (result != 1) - { - rt_free(rbuf); - return 0; - } - rt_free(rbuf); - blk_pos += 1; - } - - /* - ** #2: write continuous block size. - */ - if ((count - wsize) / bytes_per_sector != 0) - { - result = rt_mmcsd_write(dev, blk_pos, buf + wsize, (count - wsize) / bytes_per_sector); - wsize += result * bytes_per_sector; - blk_pos += result; - if (result != (count - wsize) / bytes_per_sector) + if (err) { - *pos += wsize; - return wsize; + return err; } - } - /* - ** # 3: write last unalign block size. - */ - if ((count - wsize) != 0) - { - rbuf = rt_malloc(bytes_per_sector); - if (rbuf != RT_NULL) - { - result = rt_mmcsd_read(dev, blk_pos, rbuf, 1); - if (result == 1) - { - rt_memcpy(rbuf, buf + wsize, count - wsize); - result = rt_mmcsd_write(dev, blk_pos, rbuf, 1); - if (result == 1) - { - wsize += count - wsize; - } - } - - rt_free(rbuf); - } + offset += req_size; + wr_ptr = (void *)((rt_uint8_t *)wr_ptr + (req_size << 9)); + remain_size -= req_size; } - *pos += wsize; - return wsize; + return sector_count - remain_size; } -static int rt_mmcsd_fops_poll(struct dfs_file *file, struct rt_pollreq *req) +static rt_err_t mmcsd_blk_getgeome(struct rt_blk_disk *disk, + struct rt_device_blk_geometry *geometry) { - int mask = 0; + struct mmcsd_blk_device *blk_dev = raw_to_mmcsd_blk(disk); - return mask; -} + rt_memcpy(geometry, &blk_dev->geometry, sizeof(*geometry)); -static int rt_mmcsd_fops_flush(struct dfs_file *file) -{ return RT_EOK; } -const static struct dfs_file_ops mmcsd_blk_fops = +static const struct rt_blk_disk_ops mmcsd_blk_ops = { - rt_mmcsd_fops_open, - rt_mmcsd_fops_close, - rt_mmcsd_fops_ioctl, - rt_mmcsd_fops_read, - rt_mmcsd_fops_write, - rt_mmcsd_fops_flush, - generic_dfs_lseek, - RT_NULL, - RT_NULL, - rt_mmcsd_fops_poll + .read = mmcsd_blk_read, + .write = mmcsd_blk_write, + .getgeome = mmcsd_blk_getgeome, }; -#endif -rt_int32_t gpt_device_probe(struct rt_mmcsd_card *card) +rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) { - rt_int32_t err = RT_EOK; - rt_uint8_t i, status; - char dname[10]; - char sname[16]; - struct mmcsd_blk_device *blk_dev = RT_NULL; + rt_err_t err; + struct rt_mmcsd_host *host = card->host; + struct mmcsd_blk_device *blk_dev = rt_calloc(1, sizeof(*blk_dev)); - blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device)); if (!blk_dev) { - LOG_E("mmcsd:malloc memory failed!"); - return -1; + return -RT_ENOMEM; } + card->blk_dev = blk_dev; - blk_dev->max_req_size = BLK_MIN((card->host->max_dma_segs * - card->host->max_seg_size) >> 9, - (card->host->max_blk_count * - card->host->max_blk_size) >> 9); - blk_dev->part.offset = 0; - blk_dev->part.size = 0; - rt_snprintf(sname, sizeof(sname) - 1, "sem_%s%d", card->host->name, 0); - blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); - /* register mmcsd device */ - blk_dev->dev.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - blk_dev->dev.ops = &mmcsd_blk_ops; -#else - blk_dev->dev.init = rt_mmcsd_init; - blk_dev->dev.open = rt_mmcsd_open; - blk_dev->dev.close = rt_mmcsd_close; - blk_dev->dev.read = rt_mmcsd_read; - blk_dev->dev.write = rt_mmcsd_write; - blk_dev->dev.control = rt_mmcsd_control; +#ifdef RT_USING_DM + blk_dev->parent.ida = &sdio_ida; #endif - blk_dev->card = card; + blk_dev->parent.parallel_io = RT_FALSE; + blk_dev->parent.removable = controller_is_removable(host); + blk_dev->parent.ops = &mmcsd_blk_ops; + blk_dev->parent.max_partitions = RT_MMCSD_MAX_PARTITION; + blk_dev->card = card; + blk_dev->max_req_size = rt_min_t(rt_size_t, + host->max_dma_segs * host->max_seg_size, + host->max_blk_count * host->max_blk_size) >> 9; blk_dev->geometry.bytes_per_sector = 1 << 9; blk_dev->geometry.block_size = card->card_blksize; - blk_dev->geometry.sector_count = - card->card_capacity * (1024 / 512); - - blk_dev->dev.user_data = blk_dev; - - rt_device_register(&(blk_dev->dev), card->host->name, - RT_DEVICE_FLAG_RDWR); -#ifdef RT_USING_POSIX_DEVIO -#ifdef RT_USING_DFS_V2 - blk_dev->dev.fops = &mmcsd_blk_fops; -#endif -#endif - rt_list_insert_after(&blk_devices, &blk_dev->list); - - for (i = 0; i < RT_GPT_PARTITION_MAX; i++) - { - blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device)); - if (!blk_dev) - { - LOG_E("mmcsd:malloc memory failed!"); - break; - } - blk_dev->max_req_size = BLK_MIN((card->host->max_dma_segs * - card->host->max_seg_size) >> 9, - (card->host->max_blk_count * - card->host->max_blk_size) >> 9); - - /* get the first partition */ - status = gpt_get_partition_param(card, &blk_dev->part, i); - if (status == RT_EOK) - { - rt_snprintf(dname, sizeof(dname) - 1, "%s%d", card->host->name, i); - rt_snprintf(sname, sizeof(sname) - 1, "sem_%s%d", card->host->name, i + 1); - blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); - - /* register mmcsd device */ - blk_dev->dev.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - blk_dev->dev.ops = &mmcsd_blk_ops; -#else - blk_dev->dev.init = rt_mmcsd_init; - blk_dev->dev.open = rt_mmcsd_open; - blk_dev->dev.close = rt_mmcsd_close; - blk_dev->dev.read = rt_mmcsd_read; - blk_dev->dev.write = rt_mmcsd_write; - blk_dev->dev.control = rt_mmcsd_control; -#endif - blk_dev->card = card; + blk_dev->geometry.sector_count = card->card_capacity * (1024 / 512); - blk_dev->geometry.bytes_per_sector = 1 << 9; - blk_dev->geometry.block_size = card->card_blksize; - blk_dev->geometry.sector_count = blk_dev->part.size; - - blk_dev->dev.user_data = blk_dev; - - rt_device_register(&(blk_dev->dev), dname, - RT_DEVICE_FLAG_RDWR); -#ifdef RT_USING_POSIX_DEVIO -#ifdef RT_USING_DFS_V2 - blk_dev->dev.fops = &mmcsd_blk_fops; -#endif -#endif - rt_list_insert_after(&blk_devices, &blk_dev->list); - } - else - { - rt_free(blk_dev); - blk_dev = RT_NULL; - break; - } - -#ifdef RT_USING_DFS_MNTTABLE - if (blk_dev) - { - LOG_I("try to mount file system!"); - /* try to mount file system on this block device */ - dfs_mount_device(&(blk_dev->dev)); - } -#endif - } - gpt_free(); - - return err; -} - -rt_int32_t mbr_device_probe(struct rt_mmcsd_card *card) -{ - rt_int32_t err = 0; - rt_uint8_t i, status; - rt_uint8_t *sector; - char dname[10]; - char sname[16]; - struct mmcsd_blk_device *blk_dev = RT_NULL; - - err = mmcsd_set_blksize(card); - if (err) + /* Set blk size before partitions probe, Why? */ + if ((err = mmcsd_set_blksize(card))) { - return err; + goto _fail; } rt_thread_mdelay(1); - /* get the first sector to read partition table */ - sector = (rt_uint8_t *)rt_malloc(SECTOR_SIZE); - if (sector == RT_NULL) - { - LOG_E("allocate partition sector buffer failed!"); - - return -RT_ENOMEM; - } - status = rt_mmcsd_req_blk(card, 0, sector, 1, 0); - if (status == RT_EOK) - { - blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device)); - if (!blk_dev) - { - LOG_E("mmcsd:malloc memory failed!"); - return -1; - } - blk_dev->max_req_size = BLK_MIN((card->host->max_dma_segs * - card->host->max_seg_size) >> 9, - (card->host->max_blk_count * - card->host->max_blk_size) >> 9); - blk_dev->part.offset = 0; - blk_dev->part.size = 0; - rt_snprintf(sname, sizeof(sname) - 1, "sem_%s%d", card->host->name, 0); - blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); - /* register mmcsd device */ - blk_dev->dev.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - blk_dev->dev.ops = &mmcsd_blk_ops; +#ifdef RT_USING_DM + rt_dm_dev_set_name(&blk_dev->parent.parent, host->name); #else - blk_dev->dev.init = rt_mmcsd_init; - blk_dev->dev.open = rt_mmcsd_open; - blk_dev->dev.close = rt_mmcsd_close; - blk_dev->dev.read = rt_mmcsd_read; - blk_dev->dev.write = rt_mmcsd_write; - blk_dev->dev.control = rt_mmcsd_control; + rt_strncpy(blk_dev->parent.parent.parent.name, host->name, RT_NAME_MAX); #endif - blk_dev->card = card; - blk_dev->geometry.bytes_per_sector = 1 << 9; - blk_dev->geometry.block_size = card->card_blksize; - blk_dev->geometry.sector_count = - card->card_capacity * (1024 / 512); - - blk_dev->dev.user_data = blk_dev; - - rt_device_register(&(blk_dev->dev), card->host->name, - RT_DEVICE_FLAG_RDWR); - rt_list_insert_after(&blk_devices, &blk_dev->list); - for (i = 0; i < RT_MMCSD_MAX_PARTITION; i++) - { - blk_dev = rt_calloc(1, sizeof(struct mmcsd_blk_device)); - if (!blk_dev) - { - LOG_E("mmcsd:malloc memory failed!"); - break; - } - blk_dev->max_req_size = BLK_MIN((card->host->max_dma_segs * - card->host->max_seg_size) >> 9, - (card->host->max_blk_count * - card->host->max_blk_size) >> 9); - - /* get the first partition */ - status = dfs_filesystem_get_partition(&blk_dev->part, sector, i); - if (status == RT_EOK) - { - rt_snprintf(dname, sizeof(dname) - 1, "%s%d", card->host->name, i); - rt_snprintf(sname, sizeof(sname) - 1, "sem_%s%d", card->host->name, i + 1); - blk_dev->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); - - /* register mmcsd device */ - blk_dev->dev.type = RT_Device_Class_Block; -#ifdef RT_USING_DEVICE_OPS - blk_dev->dev.ops = &mmcsd_blk_ops; -#else - blk_dev->dev.init = rt_mmcsd_init; - blk_dev->dev.open = rt_mmcsd_open; - blk_dev->dev.close = rt_mmcsd_close; - blk_dev->dev.read = rt_mmcsd_read; - blk_dev->dev.write = rt_mmcsd_write; - blk_dev->dev.control = rt_mmcsd_control; -#endif - blk_dev->card = card; - - blk_dev->geometry.bytes_per_sector = 1 << 9; - blk_dev->geometry.block_size = card->card_blksize; - blk_dev->geometry.sector_count = blk_dev->part.size; - - blk_dev->dev.user_data = blk_dev; - - rt_device_register(&(blk_dev->dev), dname, - RT_DEVICE_FLAG_RDWR); - rt_list_insert_after(&blk_devices, &blk_dev->list); - } - else - { - rt_free(blk_dev); - blk_dev = RT_NULL; - break; - } - -#ifdef RT_USING_DFS_MNTTABLE - if (blk_dev) - { - LOG_I("try to mount file system!"); - /* try to mount file system on this block device */ - dfs_mount_device(&(blk_dev->dev)); - } -#endif - } - } - else + if ((err = rt_hw_blk_disk_register(&blk_dev->parent))) { - LOG_E("read mmcsd first sector failed"); - err = -RT_ERROR; + goto _fail; } - /* release sector buffer */ - rt_free(sector); - - return err; + return RT_EOK; -} +_fail: + card->blk_dev = RT_NULL; + free(blk_dev); -rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card) -{ - uint32_t err = 0; - - LOG_D("probe mmcsd block device!"); - if (check_gpt(card) != 0) - { - err = gpt_device_probe(card); - } - else - { - err = mbr_device_probe(card); - } return err; } void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card) { - rt_list_t *l, *n; - struct mmcsd_blk_device *blk_dev; + struct mmcsd_blk_device *blk_dev = card->blk_dev; - for (l = (&blk_devices)->next, n = l->next; l != &blk_devices; l = n, n = n->next) + if (!blk_dev) { - blk_dev = (struct mmcsd_blk_device *)rt_list_entry(l, struct mmcsd_blk_device, list); - if (blk_dev->card == card) - { - /* unmount file system */ - const char *mounted_path = dfs_filesystem_get_mounted_path(&(blk_dev->dev)); - if (mounted_path) - { - dfs_unmount(mounted_path); - LOG_D("unmount file system %s for device %s.\r\n", mounted_path, blk_dev->dev.parent.name); - } - rt_sem_delete(blk_dev->part.lock); - rt_device_unregister(&blk_dev->dev); - rt_list_remove(&blk_dev->list); - rt_free(blk_dev); - } + return; } -} -/* - * This function will initialize block device on the mmc/sd. - * - * @deprecated since 2.1.0, this function does not need to be invoked - * in the system initialization. - */ -int rt_mmcsd_blk_init(void) -{ - /* nothing */ - return 0; + if (!rt_hw_blk_disk_unregister(&blk_dev->parent)) + { + card->blk_dev = RT_NULL; + rt_free(blk_dev); + } } diff --git a/components/drivers/sdio/dev_gpt.c b/components/drivers/sdio/dev_gpt.c deleted file mode 100644 index 047c6544fe8..00000000000 --- a/components/drivers/sdio/dev_gpt.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-05-05 linzhenxing first version - */ -#include -#include -#include -#include - -#define DBG_TAG "GPT" -#ifdef RT_SDIO_DEBUG -#define DBG_LVL DBG_LOG -#else -#define DBG_LVL DBG_INFO -#endif /* RT_SDIO_DEBUG */ -#include - -#define min(a, b) a < b ? a : b -static int force_gpt = 0; -static gpt_header *_gpt; -static gpt_entry *_ptes; -#define GPT_TYPE 1 -#define MBR_TYPE 0 - -static inline int efi_guidcmp (gpt_guid_t left, gpt_guid_t right) -{ - return rt_memcmp(&left, &right, sizeof (gpt_guid_t)); -} - -static uint32_t last_lba(struct rt_mmcsd_card *card) -{ - RT_ASSERT(card != RT_NULL); - return (card->card_sec_cnt) - 1; -} - -static inline int pmbr_part_valid(gpt_mbr_record *part) -{ - if (part->os_type != EFI_PMBR_OSTYPE_EFI_GPT) - { - goto invalid; - } - - /* set to 0x00000001 (i.e., the LBA of the GPT Partition Header) */ - if ((uint32_t)(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA) - { - goto invalid; - } - - return GPT_MBR_PROTECTIVE; -invalid: - return 0; -} - -/* -* -* return ret -* ret = 0, invalid mbr -* ret = 1, protect mbr -* ret = 2, hybrid mbr -*/ -int is_pmbr_valid(legacy_mbr *mbr, uint64_t total_sectors) -{ - uint32_t sz = 0; - int i, part = 0, ret = 0; /* invalid by default */ - - if (!mbr || (uint16_t)(mbr->signature) != MSDOS_MBR_SIGNATURE) - { - goto done; - } - - for (i = 0; i < 4; i++) - { - ret = pmbr_part_valid(&mbr->partition_record[i]); - if (ret == GPT_MBR_PROTECTIVE) - { - part = i; - /* - * Ok, we at least know that there's a protective MBR, - * now check if there are other partition types for - * hybrid MBR. - */ - goto check_hybrid; - } - } - - if (ret != GPT_MBR_PROTECTIVE) - { - goto done; - } - -check_hybrid: - for (i = 0; i < 4; i++) - { - if ((mbr->partition_record[i].os_type != - EFI_PMBR_OSTYPE_EFI_GPT) && - (mbr->partition_record[i].os_type != 0x00)) - { - ret = GPT_MBR_HYBRID; - } - - } - - /* - * Protective MBRs take up the lesser of the whole disk - * or 2 TiB (32bit LBA), ignoring the rest of the disk. - * Some partitioning programs, nonetheless, choose to set - * the size to the maximum 32-bit limitation, disregarding - * the disk size. - * - * Hybrid MBRs do not necessarily comply with this. - * - * Consider a bad value here to be a warning to support dd'ing - * an image from a smaller disk to a larger disk. - */ - if (ret == GPT_MBR_PROTECTIVE) - { - sz = (uint32_t)(mbr->partition_record[part].size_in_lba); - if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF) - { - LOG_I("GPT: mbr size in lba (%u) different than whole disk (%u).", - sz, min(total_sectors - 1, 0xFFFFFFFF)); - } - } - -done: - return ret; - -} - -static gpt_entry *alloc_read_gpt_entries(struct rt_mmcsd_card *card, gpt_header *gpt) -{ - size_t count; - gpt_entry *pte; - - if (!gpt) - { - return RT_NULL; - } - - count = (size_t)(gpt->num_partition_entries) * (gpt->sizeof_partition_entry); - if (!count) - { - return RT_NULL; - } - - pte = rt_malloc(count); - if (!pte) - return RT_NULL; - - if (read_lba(card, (size_t)(gpt->partition_entry_lba),(uint8_t *)pte, count/512) != RT_EOK) - { - rt_free(pte); - return RT_NULL; - } - return pte; - -} - -static gpt_header *alloc_read_gpt_header(struct rt_mmcsd_card *card, size_t lba) -{ - gpt_header *gpt; - void *buf; - - buf = rt_malloc(512); - if (!buf) - { - return RT_NULL; - } - - if (read_lba(card, lba, (uint8_t *)buf, 1) != RT_EOK) - { - rt_free(buf); - return RT_NULL; - } - gpt = (gpt_header *)buf; - - return gpt; -} - -static int is_gpt_valid(struct rt_mmcsd_card *card, size_t lba, gpt_header **gpt, gpt_entry **ptes) -{ - size_t lastlba; - - if (!ptes || !gpt) - { - return 0; - } - - *gpt = alloc_read_gpt_header(card, lba); - if (!(*gpt)) - { - return 0; - } - - /* Check the GUID Partition Table signature */ - if ((uint64_t)((*gpt)->signature) != GPT_HEADER_SIGNATURE) - { - LOG_E("GUID Partition Table Header signature is wrong:" - "%ld != %ld",(uint64_t)((*gpt)->signature),(uint64_t)GPT_HEADER_SIGNATURE); - goto fail; - } - - /* Check the GUID Partition Table header size is too small */ - if ((uint32_t)((*gpt)->header_size) < sizeof(gpt_header)) - { - LOG_E("GUID Partition Table Header size is too small: %u < %zu", - (uint32_t)((*gpt)->header_size),sizeof(gpt_header)); - goto fail; - } - - /* Check that the start_lba entry points to the LBA that contains - * the GUID Partition Table */ - if ((uint64_t)((*gpt)->start_lba) != lba) - { - LOG_E("GPT start_lba incorrect: %ld != %ld", - (uint64_t)((*gpt)->start_lba), - (uint64_t)lba); - goto fail; - } - - /* Check the first_usable_lba and last_usable_lba are - * within the disk. - */ - lastlba = last_lba(card); - if ((uint64_t)((*gpt)->first_usable_lba) > lastlba) - { - LOG_E("GPT: first_usable_lba incorrect: %ld > %ld", - ((uint64_t)((*gpt)->first_usable_lba)), - (size_t)lastlba); - goto fail; - } - - if ((uint64_t)((*gpt)->last_usable_lba) > lastlba) - { - LOG_E("GPT: last_usable_lba incorrect: %ld > %ld", - (uint64_t)((*gpt)->last_usable_lba), - (size_t)lastlba); - goto fail; - } - - if ((uint64_t)((*gpt)->last_usable_lba) < (uint64_t)((*gpt)->first_usable_lba)) - { - LOG_E("GPT: last_usable_lba incorrect: %ld > %ld", - (uint64_t)((*gpt)->last_usable_lba), - (uint64_t)((*gpt)->first_usable_lba)); - goto fail; - } - /* Check that sizeof_partition_entry has the correct value */ - if ((uint32_t)((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { - LOG_E("GUID Partition Entry Size check failed."); - goto fail; - } - - *ptes = alloc_read_gpt_entries(card, *gpt); - if (!(*ptes)) - { - goto fail; - } - - /* We're done, all's well */ - return 1; - - fail: - rt_free(*gpt); - *gpt = RT_NULL; - return 0; -} - -/** - * is_pte_valid() - tests one PTE for validity - * pte:pte to check - * lastlba: last lba of the disk - * - * Description: returns 1 if valid, 0 on error. - */ -static inline int is_pte_valid(const gpt_entry *pte, const size_t lastlba) -{ - if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) || - (uint64_t)(pte->starting_lba) > lastlba || - (uint64_t)(pte->ending_lba) > lastlba) - { - return 0; - } - - return 1; -} - -/** - * compare_gpts() - Search disk for valid GPT headers and PTEs - * pgpt: primary GPT header - * agpt: alternate GPT header - * lastlba: last LBA number - * - * Description: Returns nothing. Sanity checks pgpt and agpt fields - * and prints warnings on discrepancies. - * - */ -static void compare_gpts(gpt_header *pgpt, gpt_header *agpt, size_t lastlba) -{ - int error_found = 0; - if (!pgpt || !agpt) - { - return; - } - - if ((uint64_t)(pgpt->start_lba) != (uint64_t)(agpt->alternate_lba)) - { - LOG_I("GPT:Primary header LBA != Alt. header alternate_lba"); - LOG_I("GPT:%lld != %lld", - (uint64_t)(pgpt->start_lba), - (uint64_t)(agpt->alternate_lba)); - error_found++; - } - - if ((uint64_t)(pgpt->alternate_lba) != (uint64_t)(agpt->start_lba)) - { - LOG_I("GPT:Primary header alternate_lba != Alt. header start_lba"); - LOG_I("GPT:%lld != %lld", - (uint64_t)(pgpt->alternate_lba), - (uint64_t)(agpt->start_lba)); - error_found++; - } - - if ((uint64_t)(pgpt->first_usable_lba) != (uint64_t)(agpt->first_usable_lba)) - { - LOG_I("GPT:first_usable_lbas don't match."); - LOG_I("GPT:%lld != %lld", - (uint64_t)(pgpt->first_usable_lba), - (uint64_t)(agpt->first_usable_lba)); - error_found++; - } - - if ((uint64_t)(pgpt->last_usable_lba) != (uint64_t)(agpt->last_usable_lba)) - { - LOG_I("GPT:last_usable_lbas don't match."); - LOG_I("GPT:%lld != %lld", - (uint64_t)(pgpt->last_usable_lba), - (uint64_t)(agpt->last_usable_lba)); - error_found++; - } - - if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) - { - LOG_I("GPT:disk_guids don't match."); - error_found++; - } - - if ((pgpt->num_partition_entries) != (agpt->num_partition_entries)) - { - LOG_I("GPT:num_partition_entries don't match: " - "0x%x != 0x%x", - (pgpt->num_partition_entries), - (agpt->num_partition_entries)); - error_found++; - } - - if ((pgpt->sizeof_partition_entry) != (agpt->sizeof_partition_entry)) - { - LOG_I("GPT:sizeof_partition_entry values don't match: " - "0x%x != 0x%x", - (pgpt->sizeof_partition_entry), - (agpt->sizeof_partition_entry)); - error_found++; - } - - if ((pgpt->partition_entry_array_crc32) != (agpt->partition_entry_array_crc32)) - { - LOG_I("GPT:partition_entry_array_crc32 values don't match: " - "0x%x != 0x%x", - (pgpt->partition_entry_array_crc32), - (agpt->partition_entry_array_crc32)); - error_found++; - } - - if ((pgpt->alternate_lba) != lastlba) - { - LOG_I("GPT:Primary header thinks Alt. header is not at the end of the disk."); - LOG_I("GPT:%lld != %lld", - (uint64_t)(pgpt->alternate_lba), - (size_t)lastlba); - error_found++; - } - - if ((agpt->start_lba) != lastlba) - { - LOG_I("GPT:Alternate GPT header not at the end of the disk."); - LOG_I("GPT:%lld != %lld", - (uint64_t)(agpt->start_lba), - (size_t)lastlba); - error_found++; - } - - if (error_found) - { - LOG_I("GPT: Use GNU Parted to correct GPT errors."); - } - return; -} - -/** - * find_valid_gpt() - Search disk for valid GPT headers and PTEs - * state: disk parsed partitions - * gpt: GPT header ptr, filled on return. - * ptes: PTEs ptr, filled on return. - * - * Description: Returns 1 if valid, 0 on error. - * If valid, returns pointers to newly allocated GPT header and PTEs. - * Validity depends on PMBR being valid (or being overridden by the - * 'gpt' kernel command line option) and finding either the Primary - * GPT header and PTEs valid, or the Alternate GPT header and PTEs - * valid. If the Primary GPT header is not valid, the Alternate GPT header - * is not checked unless the 'gpt' kernel command line option is passed. - * This protects against devices which misreport their size, and forces - * the user to decide to use the Alternate GPT. - */ -static int find_valid_gpt(struct rt_mmcsd_card *card, gpt_header **gpt, - gpt_entry **ptes) -{ - int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; - gpt_header *pgpt = RT_NULL, *agpt = RT_NULL; - gpt_entry *pptes = RT_NULL, *aptes = RT_NULL; - legacy_mbr *legacymbr; - size_t total_sectors = last_lba(card) + 1; - size_t lastlba; - int status = 0; - - if (!ptes) - { - return 0; - } - - lastlba = last_lba(card); - if (!force_gpt) - { - /* This will be added to the EFI Spec. per Intel after v1.02. */ - legacymbr = rt_malloc(512); - if (!legacymbr) - { - goto fail; - } - - status = read_lba(card, 0, (uint8_t *)legacymbr, 1); - if (status) - { - LOG_I("status:%d", status); - goto fail; - } - - good_pmbr = is_pmbr_valid(legacymbr, total_sectors); - rt_free(legacymbr); - - if (!good_pmbr) - { - goto fail; - } - - rt_kprintf("Device has a %s MBR\n", - good_pmbr == GPT_MBR_PROTECTIVE ? - "protective" : "hybrid"); - } - - good_pgpt = is_gpt_valid(card, GPT_PRIMARY_PARTITION_TABLE_LBA, - &pgpt, &pptes); - if (good_pgpt) - { - good_agpt = is_gpt_valid(card, (pgpt->alternate_lba), &agpt, &aptes); - if (!good_agpt && force_gpt) - { - good_agpt = is_gpt_valid(card, lastlba, &agpt, &aptes); - } - - /* The obviously unsuccessful case */ - if (!good_pgpt && !good_agpt) - { - goto fail; - } - - compare_gpts(pgpt, agpt, lastlba); - - /* The good cases */ - if (good_pgpt) - { - *gpt = pgpt; - *ptes = pptes; - rt_free(agpt); - rt_free(aptes); - if (!good_agpt) - { - LOG_D("Alternate GPT is invalid, using primary GPT."); - } - return 1; - } - else if (good_agpt) - { - *gpt = agpt; - *ptes = aptes; - rt_free(pgpt); - rt_free(pptes); - LOG_D("Primary GPT is invalid, using alternate GPT."); - return 1; - } - } - - fail: - rt_free(pgpt); - rt_free(agpt); - rt_free(pptes); - rt_free(aptes); - *gpt = RT_NULL; - *ptes = RT_NULL; - return 0; -} - -int check_gpt(struct rt_mmcsd_card *card) -{ - if (!find_valid_gpt(card, &_gpt, &_ptes) || !_gpt || !_ptes) - { - rt_free(_gpt); - rt_free(_ptes); - return MBR_TYPE; - } - return GPT_TYPE; -} - -int gpt_get_partition_param(struct rt_mmcsd_card *card, struct dfs_partition *part, uint32_t pindex) -{ - if (!is_pte_valid(&_ptes[pindex], last_lba(card))) - { - return -1; - } - - part->offset = (off_t)(_ptes[pindex].starting_lba); - part->size = (_ptes[pindex].ending_lba) - (_ptes[pindex].starting_lba) + 1ULL; - - rt_kprintf("found part[%d], begin(sector): %d, end(sector):%d size: ", - pindex, _ptes[pindex].starting_lba, _ptes[pindex].ending_lba); - - if ((part->size >> 11) == 0) - { - rt_kprintf("%d%s", part->size >> 1, "KB\n"); /* KB */ - } - else - { - unsigned int part_size; - part_size = part->size >> 11; /* MB */ - if ((part_size >> 10) == 0) - rt_kprintf("%d.%d%s", part_size, (part->size >> 1) & 0x3FF, "MB\n"); - else - rt_kprintf("%d.%d%s", part_size >> 10, part_size & 0x3FF, "GB\n"); - } - return 0; -} - -void gpt_free(void) -{ - rt_free(_ptes); - rt_free(_gpt); -} From de38a63e9c4c9dcdb933acd4d529906d92132b08 Mon Sep 17 00:00:00 2001 From: GuEe-GUI <2991707448@qq.com> Date: Wed, 20 Nov 2024 15:10:05 +0800 Subject: [PATCH 3/3] [DM/FIXUP] add cortex-m23's cpuport.h Signed-off-by: GuEe-GUI <2991707448@qq.com> --- libcpu/arm/cortex-m23/cpuport.c | 29 +-------------------- libcpu/arm/cortex-m23/cpuport.h | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 28 deletions(-) create mode 100644 libcpu/arm/cortex-m23/cpuport.h diff --git a/libcpu/arm/cortex-m23/cpuport.c b/libcpu/arm/cortex-m23/cpuport.c index 20c611a6f0d..c5525d2a886 100644 --- a/libcpu/arm/cortex-m23/cpuport.c +++ b/libcpu/arm/cortex-m23/cpuport.c @@ -14,34 +14,7 @@ #include -struct exception_stack_frame -{ - rt_uint32_t r0; - rt_uint32_t r1; - rt_uint32_t r2; - rt_uint32_t r3; - rt_uint32_t r12; - rt_uint32_t lr; - rt_uint32_t pc; - rt_uint32_t psr; -}; - -struct stack_frame -{ - /* r4 ~ r7 low register */ - rt_uint32_t r4; - rt_uint32_t r5; - rt_uint32_t r6; - rt_uint32_t r7; - - /* r8 ~ r11 high register */ - rt_uint32_t r8; - rt_uint32_t r9; - rt_uint32_t r10; - rt_uint32_t r11; - - struct exception_stack_frame exception_stack_frame; -}; +#include "cpuport.h" /* flag in interrupt handling */ rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; diff --git a/libcpu/arm/cortex-m23/cpuport.h b/libcpu/arm/cortex-m23/cpuport.h new file mode 100644 index 00000000000..d5bd7645a42 --- /dev/null +++ b/libcpu/arm/cortex-m23/cpuport.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-11-17 RT-Thread first version + */ + +#ifndef __CPUPORT_H__ +#define __CPUPORT_H__ + +#include + +struct exception_stack_frame +{ + rt_uint32_t r0; + rt_uint32_t r1; + rt_uint32_t r2; + rt_uint32_t r3; + rt_uint32_t r12; + rt_uint32_t lr; + rt_uint32_t pc; + rt_uint32_t psr; +}; + +struct stack_frame +{ + /* r4 ~ r7 low register */ + rt_uint32_t r4; + rt_uint32_t r5; + rt_uint32_t r6; + rt_uint32_t r7; + + /* r8 ~ r11 high register */ + rt_uint32_t r8; + rt_uint32_t r9; + rt_uint32_t r10; + rt_uint32_t r11; + + struct exception_stack_frame exception_stack_frame; +}; + +#endif /* __CPUPORT_H__ */