[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>
This commit is contained in:
GuEe-GUI
2024-10-30 10:44:16 +08:00
committed by Rbb666
parent 10cac76d3b
commit c424cb8186
17 changed files with 2472 additions and 0 deletions

View File

@@ -21,6 +21,7 @@ rsource "touch/Kconfig"
rsource "graphic/Kconfig"
rsource "hwcrypto/Kconfig"
rsource "wlan/Kconfig"
rsource "block/Kconfig"
rsource "virtio/Kconfig"
rsource "mfd/Kconfig"
rsource "ofw/Kconfig"

View File

@@ -0,0 +1,7 @@
menuconfig RT_USING_BLK
bool "Using Block device drivers"
default n
if RT_USING_BLK
rsource "partitions/Kconfig"
endif

View File

@@ -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')

File diff suppressed because it is too large Load Diff

View File

@@ -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 <rtdbg.h>
#ifdef RT_USING_DFS
#include <dfs_fs.h>
#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;
}

View File

@@ -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 <rthw.h>
#include <rtthread.h>
#include <drivers/blk.h>
#include <drivers/misc.h>
#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__ */

View File

@@ -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 <dfs_file.h>
#include <drivers/classes/block.h>
#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));
}

View File

@@ -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 <rtdef.h>
#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__ */

View File

@@ -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 <rtdbg.h>
#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;
}

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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')

View File

@@ -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 <rtdbg.h>
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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 <drivers/misc.h>
#include <drivers/byteorder.h>
#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__ */

View File

@@ -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 <rthw.h>
#include <rtthread.h>
#include <drivers/classes/block.h>
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 <dfs_fs.h>
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__ */

View File

@@ -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"