
Hi Heinrich,
On Thu, 20 Jul 2023 at 00:10, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 14.07.23 07:44, Masahisa Kojima wrote:
This introcudes the ramdisk uclass and driver.
Signed-off-by: Masahisa Kojima masahisa.kojima@linaro.org
Newly introcuded in v2
disk/part.c | 3 + drivers/block/Kconfig | 7 +- drivers/block/Makefile | 2 + drivers/block/blk-uclass.c | 1 + drivers/block/blk_ramdisk.c | 187 +++++++++++++++++++++++++++++++ drivers/block/ramdisk-uclass.c | 14 +++ include/dm/uclass-id.h | 1 + include/ramdisk.h | 32 ++++++ lib/efi_loader/efi_device_path.c | 25 +++++ 9 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 drivers/block/blk_ramdisk.c create mode 100644 drivers/block/ramdisk-uclass.c create mode 100644 include/ramdisk.h
diff --git a/disk/part.c b/disk/part.c index 35300df590..d0cee3cc03 100644 --- a/disk/part.c +++ b/disk/part.c @@ -152,6 +152,9 @@ void dev_print(struct blk_desc *dev_desc) case UCLASS_EFI_MEDIA: printf("EFI media Block Device %d\n", dev_desc->devnum); break;
case UCLASS_RAM_DISK:
printf("RAM Disk Block Device %d\n", dev_desc->devnum);
break; case UCLASS_INVALID: puts("device type unknown\n"); return;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 5a1aeb3d2b..ab56ef3406 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -2,7 +2,7 @@ config BLK bool # "Support block devices" depends on DM default y if MMC || USB || SCSI || NVME || IDE || AHCI || SATA
default y if EFI_MEDIA || VIRTIO_BLK || PVBLOCK
default y if EFI_MEDIA || VIRTIO_BLK || PVBLOCK || RAM_DISK help Enable support for block devices, such as SCSI, MMC and USB flash sticks. These provide a block-level interface which permits
@@ -255,3 +255,8 @@ config SYS_64BIT_LBA help Make the block subsystem use 64bit sector addresses, rather than the default of 32bit.
+config RAM_DISK
bool "Enable RAM disk"
help
This option enables to mount the RAM disk.
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index a161d145fd..e867c7a126 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -19,3 +19,5 @@ obj-$(CONFIG_BLKMAP) += blkmap.o obj-$(CONFIG_EFI_MEDIA) += efi-media-uclass.o obj-$(CONFIG_EFI_MEDIA_SANDBOX) += sb_efi_media.o obj-$(CONFIG_EFI_MEDIA_BLK) += efi_blk.o +obj-$(CONFIG_RAM_DISK) += blk_ramdisk.o +obj-$(CONFIG_RAM_DISK) += ramdisk-uclass.o diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 614b975e25..ea411fe674 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -34,6 +34,7 @@ static struct { { UCLASS_VIRTIO, "virtio" }, { UCLASS_PVBLOCK, "pvblock" }, { UCLASS_BLKMAP, "blkmap" },
{ UCLASS_RAM_DISK, "ramdisk" },
};
static enum uclass_id uclass_name_to_iftype(const char *uclass_idname)
diff --git a/drivers/block/blk_ramdisk.c b/drivers/block/blk_ramdisk.c new file mode 100644 index 0000000000..8016837a80 --- /dev/null +++ b/drivers/block/blk_ramdisk.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- RAM Disk block device driver
- Copyright (c) 2023, Linaro Limited
- */
+#include <blk.h> +#include <common.h> +#include <dm.h> +#include <log.h> +#include <part.h> +#include <ramdisk.h> +#include <dm/device-internal.h> +#include <dm/root.h>
+#if (IS_ENABLED(CONFIG_EFI_LOADER)) +#include <efi_loader.h> +#endif
+#define MEM_BLOCK_SIZE_SHIFT 9 /* 512 bytes */
+/**
- ramdisk_read() - read from block device
- @dev: device
- @blknr: first block to be read
- @blkcnt: number of blocks to read
- @buffer: output buffer
- Return: number of blocks transferred
- */
+static ulong ramdisk_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
void *buffer)
+{
u8 *start;
struct ramdisk_blk_plat *plat = dev_get_plat(dev);
log_debug("read buf=%p, block=%lx, count=%lx: ", buffer, (ulong)blknr,
(ulong)blkcnt);
if (!buffer)
return 0;
if (blknr + blkcnt > (plat->size >> MEM_BLOCK_SIZE_SHIFT))
return 0;
start = plat->start + (blknr << MEM_BLOCK_SIZE_SHIFT);
memmove(buffer, start, blkcnt << MEM_BLOCK_SIZE_SHIFT);
return blkcnt;
+}
+/**
- ramdisk_write() - write to block device
- @dev: device
- @blknr: first block to be write
- @blkcnt: number of blocks to write
- @buffer: input buffer
- Return: number of blocks transferred
- */
+static ulong ramdisk_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
const void *buffer)
+{
u8 *start;
struct ramdisk_blk_plat *plat = dev_get_plat(dev);
log_debug("write buf=%p, block=%lx, count=%lx: ", buffer, (ulong)blknr,
(ulong)blkcnt);
if (!buffer)
return 0;
if (blknr + blkcnt > (plat->size >> MEM_BLOCK_SIZE_SHIFT))
return 0;
start = plat->start + (blknr << MEM_BLOCK_SIZE_SHIFT);
memmove(start, buffer, blkcnt << MEM_BLOCK_SIZE_SHIFT);
return blkcnt;
+}
+static const struct blk_ops ramdisk_blk_ops = {
.read = ramdisk_read,
.write = ramdisk_write,
+};
+U_BOOT_DRIVER(ramdisk_blk) = {
.name = "ramdisk_blk",
.id = UCLASS_BLK,
.ops = &ramdisk_blk_ops,
.plat_auto = sizeof(struct ramdisk_blk_plat),
+};
+/*
- ramdisk_mount - mount ramdisk
- @start_address: The base address of registered RAM disk
- @size: The size of registered RAM disk
- @guid: The type of registered RAM disk
- Return: Pointer to the udevice strucure, return NULL if failed
- */
+struct udevice *ramdisk_mount(u64 start_address, u64 size, void *guid) +{
int ret;
char name[20];
struct udevice *parent, *bdev;
static struct ramdisk_blk_plat *plat;
if (!start_address || !size)
return NULL;
ret = device_bind(dm_root(), DM_DRIVER_GET(ramdisk), "ramdisk", NULL,
ofnode_null(), &parent);
if (ret) {
log_err("bind ramdisk error\n");
return NULL;
}
snprintf(name, sizeof(name), "ramdisk%d", dev_seq(parent));
device_set_name(parent, name);
ret = blk_create_device(parent, "ramdisk_blk", "ramdisk_blk",
UCLASS_RAM_DISK, dev_seq(parent),
1 << MEM_BLOCK_SIZE_SHIFT,
(size >> MEM_BLOCK_SIZE_SHIFT) - 1, &bdev);
if (ret) {
log_err("ramdisk create block device failed\n");
goto err;
}
snprintf(name, sizeof(name), "ramdisk_blk#%d", dev_seq(parent));
device_set_name(bdev, name);
plat = dev_get_plat(bdev);
plat->start = (u8 *)start_address;
plat->size = size;
+#if (IS_ENABLED(CONFIG_EFI_LOADER))
if (guid)
guidcpy(&plat->disk_type_guid, guid);
+#endif
ret = blk_probe_or_unbind(bdev);
if (ret) {
log_err("ramdisk probe error\n");
goto err;
}
return bdev;
+err:
if (parent) {
ret = device_remove(parent, DM_REMOVE_NORMAL);
if (ret)
return NULL;
ret = device_unbind(parent);
}
return NULL;
+}
+/*
- ramdisk_unmount - unmount ramdisk
- @dev: The device to be unmounted
- Return: 0 if success, negative value if error
- */
+int ramdisk_unmount(struct udevice *dev) +{
int ret;
struct udevice *parent;
if (!dev)
return -EINVAL;
parent = dev->parent;
ret = device_remove(parent, DM_REMOVE_NORMAL);
if (ret)
return ret;
ret = device_unbind(parent);
return ret;
+}
+U_BOOT_DRIVER(ramdisk) = {
.name = "ramdisk",
.id = UCLASS_RAM_DISK,
+}; diff --git a/drivers/block/ramdisk-uclass.c b/drivers/block/ramdisk-uclass.c new file mode 100644 index 0000000000..f1bf68f635 --- /dev/null +++ b/drivers/block/ramdisk-uclass.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- RAM Disk block device driver
- Copyright (c) 2023, Linaro Limited
- */
+#include <common.h> +#include <dm.h>
+UCLASS_DRIVER(ramdisk) = {
.name = "ramdisk",
.id = UCLASS_RAM_DISK,
+}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 307ad6931c..42b4907b1f 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -109,6 +109,7 @@ enum uclass_id { UCLASS_PWRSEQ, /* Power sequence device */ UCLASS_QFW, /* QEMU firmware config device */ UCLASS_RAM, /* RAM controller */
UCLASS_RAM_DISK, /* RAM disk device */ UCLASS_REBOOT_MODE, /* Reboot mode */ UCLASS_REGULATOR, /* Regulator device */ UCLASS_REMOTEPROC, /* Remote Processor device */
diff --git a/include/ramdisk.h b/include/ramdisk.h new file mode 100644 index 0000000000..71383be5b8 --- /dev/null +++ b/include/ramdisk.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- ramdisk support
- Copyright (c) 2023, Linaro Limited
- */
+#ifndef _RAMDISK_H +#define _RAMDISK_H
+#ifdef CONFIG_EFI_LOADER +#include <efi.h> +#endif
+/**
- struct ramdisk_blk_plat - attributes of a block device
- @handle: handle of the controller on which this driver is installed
- @io: block io protocol proxied by this driver
- */
+struct ramdisk_blk_plat {
u8 *start;
u64 size;
+#if (IS_ENABLED(CONFIG_EFI_LOADER))
efi_guid_t disk_type_guid;
+#endif +};
+struct udevice *ramdisk_mount(u64 start_address, u64 size, void *guid); +int ramdisk_unmount(struct udevice *dev);
+#endif diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 04ebb449ca..1f16bda6ac 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -17,6 +17,7 @@ #include <nvme.h> #include <efi_loader.h> #include <part.h> +#include <ramdisk.h> #include <uuid.h> #include <asm-generic/unaligned.h> #include <linux/compat.h> /* U16_MAX */ @@ -568,6 +569,11 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) */ return dp_size(dev->parent) + sizeof(struct efi_device_path_vendor) + 1; +#endif +#ifdef CONFIG_RAM_DISK
case UCLASS_RAM_DISK:
What is the difference to UCLASS_BLKMAP?
[PATCH v2 0/9] blk: blkmap: Composable virtual block devices https://lore.kernel.org/u-boot/20230216153355.448302-1-tobias@waldekranz.com...
I was not aware of the blkmap when I created this series. This patch is duplicated, please drop this series.
Thanks, Masahisa Kojima
Best regards
Heinrich
return dp_size(dev->parent)
#endif default: return dp_size(dev->parent);+ sizeof(struct efi_device_path_ram_disk_path) + 1;
@@ -766,6 +772,25 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) dp->controller_number = desc->lun; return &dp[1]; } +#endif +#if defined(CONFIG_RAM_DISK)
case UCLASS_RAM_DISK: {
struct ramdisk_blk_plat *plat = dev_get_plat(dev);
struct efi_device_path_ram_disk_path *dp =
dp_fill(buf, dev->parent);
dp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_RAM_DISK_PATH;
dp->dp.length =
sizeof(struct efi_device_path_ram_disk_path);
put_unaligned_le64((u64)plat->start,
&dp->starting_address);
put_unaligned_le64((u64)(plat->start + plat->size - 1),
&dp->ending_address);
guidcpy(&dp->disk_type_guid, &plat->disk_type_guid);
dp->disk_instance = 0;
return &dp[1];
#endif default: debug("%s(%u) %s: unhandled parent class: %s (%u)\n",}