Message ID | 20200701162959.9814-13-vicooodin@gmail.com |
---|---|
State | New |
Headers | show |
Series | Add new board: Xen guest for ARM64 | expand |
Hi Heinrich, On Thu, 2020-07-02 at 06:17 +0200, Heinrich Schuchardt wrote: > On 7/1/20 6:29 PM, Anastasiia Lukianenko wrote: > > From: Anastasiia Lukianenko <anastasiia_lukianenko at epam.com> > > > > Add initial infrastructure for Xen para-virtualized block device. > > This includes compile-time configuration and the skeleton for > > the future driver implementation. > > Add new class UCLASS_PVBLOCK which is going to be a parent for > > virtual block devices. > > Add new interface type IF_TYPE_PVBLOCK. > > > > Implement basic driver setup by reading XenStore configuration. > > Please, add documenation for the board in doc/board/. Ok, will add. > > > > > Signed-off-by: Andrii Anisov <andrii_anisov at epam.com> > > Signed-off-by: Anastasiia Lukianenko < > > anastasiia_lukianenko at epam.com> > > Signed-off-by: Oleksandr Andrushchenko < > > oleksandr_andrushchenko at epam.com> > > --- > > cmd/Kconfig | 7 ++ > > cmd/Makefile | 1 + > > cmd/pvblock.c | 31 ++++++++ > > common/board_r.c | 14 ++++ > > configs/xenguest_arm64_defconfig | 4 + > > disk/part.c | 4 + > > drivers/Kconfig | 2 + > > drivers/block/blk-uclass.c | 2 + > > drivers/xen/Kconfig | 10 +++ > > drivers/xen/Makefile | 2 + > > drivers/xen/pvblock.c | 121 > > +++++++++++++++++++++++++++++++ > > include/blk.h | 1 + > > include/configs/xenguest_arm64.h | 8 ++ > > include/dm/uclass-id.h | 1 + > > include/pvblock.h | 12 +++ > > 15 files changed, 220 insertions(+) > > create mode 100644 cmd/pvblock.c > > create mode 100644 drivers/xen/Kconfig > > create mode 100644 drivers/xen/pvblock.c > > create mode 100644 include/pvblock.h > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > index 192b3b262f..f28576947b 100644 > > --- a/cmd/Kconfig > > +++ b/cmd/Kconfig > > @@ -1335,6 +1335,13 @@ config CMD_USB_MASS_STORAGE > > help > > USB mass storage support > > > > +config CMD_PVBLOCK > > + bool "Xen para-virtualized block device" > > + depends on XEN > > + select PVBLOCK > > + help > > + Xen para-virtualized block device support > > + > > config CMD_VIRTIO > > bool "virtio" > > depends on VIRTIO > > diff --git a/cmd/Makefile b/cmd/Makefile > > index 974ad48b0a..117284a28c 100644 > > --- a/cmd/Makefile > > +++ b/cmd/Makefile > > @@ -169,6 +169,7 @@ obj-$(CONFIG_CMD_DFU) += dfu.o > > obj-$(CONFIG_CMD_GPT) += gpt.o > > obj-$(CONFIG_CMD_ETHSW) += ethsw.o > > obj-$(CONFIG_CMD_AXI) += axi.o > > +obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o > > > > # Power > > obj-$(CONFIG_CMD_PMIC) += pmic.o > > diff --git a/cmd/pvblock.c b/cmd/pvblock.c > > new file mode 100644 > > index 0000000000..7dbb243a74 > > --- /dev/null > > +++ b/cmd/pvblock.c > > @@ -0,0 +1,31 @@ > > +/* > > + * SPDX-License-Identifier: GPL-2.0+ > > SPDX should be in first line and formatted as described in > > https://urldefense.com/v3/__https://www.kernel.org/doc/html/latest/process/license-rules.html*license-identifier-syntax__;Iw!!GF_29dbcQIUBPA!l97PRX7YWb0RSRfrhKECVdFblqlOu73YTMPut6YwlXMfrLzvQrqF56fQO2MjT5c6kJT1Mqk$ > Ok, will fix. > > > > + * > > + * (C) Copyright 2020 EPAM Systems Inc. > > + * > > + * XEN para-virtualized block device support > > + */ > > + > > +#include <blk.h> > > +#include <common.h> > > +#include <command.h> > > + > > +/* Current I/O Device */ > > +static int pvblock_curr_device; > > + > > +int do_pvblock(struct cmd_tbl *cmdtp, int flag, int argc, char > > *const argv[]) > > +{ > > + return blk_common_cmd(argc, argv, IF_TYPE_PVBLOCK, > > + &pvblock_curr_device); > > +} > > + > > +U_BOOT_CMD(pvblock, 5, 1, do_pvblock, > > + "Xen para-virtualized block device", > > + "info - show available block devices\n" > > + "pvblock device [dev] - show or set current device\n" > > + "pvblock part [dev] - print partition table of one or all > > devices\n" > > + "pvblock read addr blk# cnt\n" > > + "pvblock write addr blk# cnt - read/write `cnt'" > > + " blocks starting at block `blk#'\n" > > + " to/from memory address `addr'"); > > + > > diff --git a/common/board_r.c b/common/board_r.c > > index fd36edb4e5..40cd0e5d3c 100644 > > --- a/common/board_r.c > > +++ b/common/board_r.c > > @@ -49,6 +49,7 @@ > > #include <nand.h> > > #include <of_live.h> > > #include <onenand_uboot.h> > > +#include <pvblock.h> > > #include <scsi.h> > > #include <serial.h> > > #include <status_led.h> > > @@ -470,6 +471,16 @@ static int initr_xen(void) > > return 0; > > } > > #endif > > + > > +#ifdef CONFIG_PVBLOCK > > +static int initr_pvblock(void) > > +{ > > + puts("PVBLOCK: "); > > + pvblock_init(); > > + return 0; > > +} > > +#endif > > + > > /* > > * Tell if it's OK to load the environment early in boot. > > * > > @@ -780,6 +791,9 @@ static init_fnc_t init_sequence_r[] = { > > #endif > > #ifdef CONFIG_XEN > > initr_xen, > > +#endif > > +#ifdef CONFIG_PVBLOCK > > + initr_pvblock, > > #endif > > initr_env, > > #ifdef CONFIG_SYS_BOOTPARAMS_LEN > > diff --git a/configs/xenguest_arm64_defconfig > > b/configs/xenguest_arm64_defconfig > > index 45559a161b..46473c251d 100644 > > --- a/configs/xenguest_arm64_defconfig > > +++ b/configs/xenguest_arm64_defconfig > > @@ -14,6 +14,8 @@ CONFIG_CMD_BOOTD=n > > CONFIG_CMD_BOOTEFI=n > > CONFIG_CMD_BOOTEFI_HELLO_COMPILE=n > > CONFIG_CMD_ELF=n > > +CONFIG_CMD_EXT4=y > > +CONFIG_CMD_FAT=y > > CONFIG_CMD_GO=n > > CONFIG_CMD_RUN=n > > CONFIG_CMD_IMI=n > > @@ -41,6 +43,8 @@ CONFIG_CMD_LZMADEC=n > > CONFIG_CMD_SAVEENV=n > > CONFIG_CMD_UMS=n > > > > +CONFIG_CMD_PVBLOCK=y > > + > > #CONFIG_USB=n > > # CONFIG_ISO_PARTITION is not set > > > > diff --git a/disk/part.c b/disk/part.c > > index f6a31025dc..b69fd345f3 100644 > > --- a/disk/part.c > > +++ b/disk/part.c > > @@ -149,6 +149,7 @@ void dev_print (struct blk_desc *dev_desc) > > case IF_TYPE_MMC: > > case IF_TYPE_USB: > > case IF_TYPE_NVME: > > + case IF_TYPE_PVBLOCK: > > printf ("Vendor: %s Rev: %s Prod: %s\n", > > dev_desc->vendor, > > dev_desc->revision, > > @@ -288,6 +289,9 @@ static void print_part_header(const char *type, > > struct blk_desc *dev_desc) > > case IF_TYPE_NVME: > > puts ("NVMe"); > > break; > > + case IF_TYPE_PVBLOCK: > > + puts("PV BLOCK"); > > + break; > > case IF_TYPE_VIRTIO: > > puts("VirtIO"); > > break; > > diff --git a/drivers/Kconfig b/drivers/Kconfig > > index e34a22708c..65076aab03 100644 > > --- a/drivers/Kconfig > > +++ b/drivers/Kconfig > > @@ -132,6 +132,8 @@ source "drivers/w1-eeprom/Kconfig" > > > > source "drivers/watchdog/Kconfig" > > > > +source "drivers/xen/Kconfig" > > + > > config PHYS_TO_BUS > > bool "Custom physical to bus address mapping" > > help > > diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk- > > uclass.c > > index b19375cbc8..6cfabbca24 100644 > > --- a/drivers/block/blk-uclass.c > > +++ b/drivers/block/blk-uclass.c > > @@ -28,6 +28,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] > > = { > > [IF_TYPE_NVME] = "nvme", > > [IF_TYPE_EFI] = "efi", > > [IF_TYPE_VIRTIO] = "virtio", > > + [IF_TYPE_PVBLOCK] = "pvblock", > > }; > > > > static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { > > @@ -43,6 +44,7 @@ static enum uclass_id > > if_type_uclass_id[IF_TYPE_COUNT] = { > > [IF_TYPE_NVME] = UCLASS_NVME, > > [IF_TYPE_EFI] = UCLASS_EFI, > > [IF_TYPE_VIRTIO] = UCLASS_VIRTIO, > > + [IF_TYPE_PVBLOCK] = UCLASS_PVBLOCK, > > }; > > > > static enum if_type if_typename_to_iftype(const char *if_typename) > > diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig > > new file mode 100644 > > index 0000000000..6ad2a93668 > > --- /dev/null > > +++ b/drivers/xen/Kconfig > > @@ -0,0 +1,10 @@ > > +config PVBLOCK > > + bool "Xen para-virtualized block device" > > + depends on DM > > + select BLK > > + select HAVE_BLOCK_DEVICE > > + help > > + This driver implements the front-end of the Xen virtual > > + block device driver. It communicates with a back-end driver > > + in another domain which drives the actual block device. > > + > > diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile > > index 243b13277a..87157df69b 100644 > > --- a/drivers/xen/Makefile > > +++ b/drivers/xen/Makefile > > @@ -6,3 +6,5 @@ obj-y += hypervisor.o > > obj-y += events.o > > obj-y += xenbus.o > > obj-y += gnttab.o > > + > > +obj-$(CONFIG_PVBLOCK) += pvblock.o > > diff --git a/drivers/xen/pvblock.c b/drivers/xen/pvblock.c > > new file mode 100644 > > index 0000000000..057add9753 > > --- /dev/null > > +++ b/drivers/xen/pvblock.c > > @@ -0,0 +1,121 @@ > > +/* > > + * SPDX-License-Identifier: GPL-2.0+ > > + * > > + * (C) Copyright 2020 EPAM Systems Inc. > > + */ > > +#include <blk.h> > > +#include <common.h> > > +#include <dm.h> > > +#include <dm/device-internal.h> > > + > > +#define DRV_NAME "pvblock" > > +#define DRV_NAME_BLK "pvblock_blk" > > + > > +struct blkfront_dev { > > + char dummy; > > +}; > > + > > +static int init_blkfront(unsigned int devid, struct blkfront_dev > > *dev) > > +{ > > + return 0; > > +} > > + > > +static void shutdown_blkfront(struct blkfront_dev *dev) > > +{ > > +} > > + > > +ulong pvblock_blk_read(struct udevice *udev, lbaint_t blknr, > > lbaint_t blkcnt, > > + void *buffer) > > +{ > > + return 0; > > +} > > + > > +ulong pvblock_blk_write(struct udevice *udev, lbaint_t blknr, > > lbaint_t blkcnt, > > + const void *buffer) > > +{ > > + return 0; > > +} > > + > > +static int pvblock_blk_bind(struct udevice *udev) > > +{ > > + return 0; > > +} > > + > > +static int pvblock_blk_probe(struct udevice *udev) > > +{ > > + struct blkfront_dev *blk_dev = dev_get_priv(udev); > > + int ret; > > + > > + ret = init_blkfront(0, blk_dev); > > + if (ret < 0) > > + return ret; > > + return 0; > > +} > > + > > +static int pvblock_blk_remove(struct udevice *udev) > > +{ > > + struct blkfront_dev *blk_dev = dev_get_priv(udev); > > + > > + shutdown_blkfront(blk_dev); > > + return 0; > > +} > > + > > +static const struct blk_ops pvblock_blk_ops = { > > + .read = pvblock_blk_read, > > + .write = pvblock_blk_write, > > +}; > > + > > +U_BOOT_DRIVER(pvblock_blk) = { > > + .name = DRV_NAME_BLK, > > + .id = UCLASS_BLK, > > + .ops = &pvblock_blk_ops, > > + .bind = pvblock_blk_bind, > > + .probe = pvblock_blk_probe, > > + .remove = pvblock_blk_remove, > > + .priv_auto_alloc_size = sizeof(struct blkfront_dev), > > + .flags = DM_FLAG_OS_PREPARE, > > +}; > > + > > +/***************************************************************** > > ************** > > + * Para-virtual block device class > > + > > ******************************************************************* > > ************/ > > + > > +void pvblock_init(void) > > +{ > > + struct driver_info info; > > + struct udevice *udev; > > + struct uclass *uc; > > + int ret; > > + > > + /* > > + * At this point Xen drivers have already initialized, > > + * so we can instantiate the class driver and enumerate > > + * virtual block devices. > > + */ > > + info.name = DRV_NAME; > > + ret = device_bind_by_name(gd->dm_root, false, &info, &udev); > > + if (ret < 0) > > + printf("Failed to bind " DRV_NAME ", ret: %d\n", ret); > > + > > + /* Bootstrap virtual block devices class driver */ > > + ret = uclass_get(UCLASS_PVBLOCK, &uc); > > + if (ret) > > + return; > > + uclass_foreach_dev_probe(UCLASS_PVBLOCK, udev); > > +} > > + > > +static int pvblock_probe(struct udevice *udev) > > +{ > > + return 0; > > +} > > + > > +U_BOOT_DRIVER(pvblock_drv) = { > > + .name = DRV_NAME, > > + .id = UCLASS_PVBLOCK, > > + .probe = pvblock_probe, > > +}; > > + > > +UCLASS_DRIVER(pvblock) = { > > + .name = DRV_NAME, > > + .id = UCLASS_PVBLOCK, > > +}; > > diff --git a/include/blk.h b/include/blk.h > > index abcd4bedbb..9ee10fb80e 100644 > > --- a/include/blk.h > > +++ b/include/blk.h > > @@ -33,6 +33,7 @@ enum if_type { > > IF_TYPE_HOST, > > IF_TYPE_NVME, > > IF_TYPE_EFI, > > + IF_TYPE_PVBLOCK, > > IF_TYPE_VIRTIO, > > > > IF_TYPE_COUNT, /* Number of interface > > types */ > > diff --git a/include/configs/xenguest_arm64.h > > b/include/configs/xenguest_arm64.h > > index 467dabf1e5..2c0d3d64fb 100644 > > --- a/include/configs/xenguest_arm64.h > > +++ b/include/configs/xenguest_arm64.h > > @@ -42,4 +42,12 @@ > > #define CONFIG_CMDLINE_TAG 1 > > #define CONFIG_INITRD_TAG 1 > > > > +#define CONFIG_CMD_RUN > > + > > +#undef CONFIG_EXTRA_ENV_SETTINGS > > +#define CONFIG_EXTRA_ENV_SETTINGS \ > > + "loadimage=ext4load pvblock 0 0x90000000 /boot/Image;\0" \ > > + "pvblockboot=run loadimage;" \ > > + "booti 0x90000000 - 0x88000000;\0" > > + > > #endif /* __XENGUEST_ARM64_H */ > > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h > > index 7837d459f1..4bf7501204 100644 > > --- a/include/dm/uclass-id.h > > +++ b/include/dm/uclass-id.h > > @@ -121,6 +121,7 @@ enum uclass_id { > > UCLASS_W1, /* Dallas 1-Wire bus */ > > UCLASS_W1_EEPROM, /* one-wire EEPROMs */ > > UCLASS_WDT, /* Watchdog Timer driver */ > > + UCLASS_PVBLOCK, /* Xen virtual block device */ > > > > UCLASS_COUNT, > > UCLASS_INVALID = -1, > > diff --git a/include/pvblock.h b/include/pvblock.h > > new file mode 100644 > > index 0000000000..e3bb8ff9a7 > > --- /dev/null > > +++ b/include/pvblock.h > > @@ -0,0 +1,12 @@ > > +/* > > + * SPDX-License-Identifier: GPL-2.0+ > > see above > > Please, use scripts/checkpatch.pl before submitting patches. We used it, but did not know when to stop :) > > Best regards > > Heinrich Best regards, Anastasiia > > > + * > > + * (C) 2020 EPAM Systems Inc. > > + */ > > + > > +#ifndef _PVBLOCK_H > > +#define _PVBLOCK_H > > + > > +void pvblock_init(void); > > + > > +#endif /* _PVBLOCK_H */ > > > >
Hi Heinrich, On Thu, 2020-07-02 at 06:29 +0200, Heinrich Schuchardt wrote: > On 7/1/20 6:29 PM, Anastasiia Lukianenko wrote: > > From: Anastasiia Lukianenko <anastasiia_lukianenko at epam.com> > > > > Add initial infrastructure for Xen para-virtualized block device. > > This includes compile-time configuration and the skeleton for > > the future driver implementation. > > Add new class UCLASS_PVBLOCK which is going to be a parent for > > virtual block devices. > > We already have virtual block devices: virtio_blk, efi_blk. > > They work fine using the exising UCLASS_BLK. Why do we need a new > uclass? > During the implementation we had a discussion with Simon Glass on that [1]. PVBLOCK could be just a UCLASS_BLK driver with the parent being gd->dm_root, but in this case most of the file system/block device commands fail to work as those expect that pvblock driver must be a parent device and pvblock blk device must be its child to comply to U-boot driver architecture. When we bind a new driver [2], we need to specify it's parent. There is no UCLASS_BLK device available at that moment, therefore it is possible to use only a UCLASS_ROOT device, but parent and child interface types must be the same [3]. So, then we need interface to be defined as [IF_TYPE_PVBLOCK] = UCLASS_ROOT which doesn't seem to be right. Thereby, we created a new UCLASS_PVBLOCK class for para-virtual block devices [4]. The driver class provides methods for accessing the "bus" and actually implements the ops for reading and writing. But, we don't have a "bus" or a common transport as virtio has, so we are a bit different with that respect from the drivers you mentioned. [1] - https://www.mail-archive.com/u-boot at lists.denx.de/msg371956.html [2] - https://github.com/xen-troops/u-boot/blob/master/drivers/xen/pvblock.c#L697 [3] - https://github.com/xen-troops/u-boot/blob/master/drivers/block/blk-uclass.c#L124 [4] - https://github.com/xen-troops/u-boot/blob/master/drivers/block/blk-uclass.c#L47 > > Add new interface type IF_TYPE_PVBLOCK. > > > > Implement basic driver setup by reading XenStore configuration. > > > > Signed-off-by: Andrii Anisov <andrii_anisov at epam.com> > > Signed-off-by: Anastasiia Lukianenko < > > anastasiia_lukianenko at epam.com> > > Signed-off-by: Oleksandr Andrushchenko < > > oleksandr_andrushchenko at epam.com> > > --- > > cmd/Kconfig | 7 ++ > > cmd/Makefile | 1 + > > cmd/pvblock.c | 31 ++++++++ > > common/board_r.c | 14 ++++ > > configs/xenguest_arm64_defconfig | 4 + > > disk/part.c | 4 + > > drivers/Kconfig | 2 + > > drivers/block/blk-uclass.c | 2 + > > drivers/xen/Kconfig | 10 +++ > > drivers/xen/Makefile | 2 + > > drivers/xen/pvblock.c | 121 > > +++++++++++++++++++++++++++++++ > > include/blk.h | 1 + > > include/configs/xenguest_arm64.h | 8 ++ > > include/dm/uclass-id.h | 1 + > > include/pvblock.h | 12 +++ > > 15 files changed, 220 insertions(+) > > create mode 100644 cmd/pvblock.c > > create mode 100644 drivers/xen/Kconfig > > create mode 100644 drivers/xen/pvblock.c > > create mode 100644 include/pvblock.h > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > index 192b3b262f..f28576947b 100644 > > --- a/cmd/Kconfig > > +++ b/cmd/Kconfig > > @@ -1335,6 +1335,13 @@ config CMD_USB_MASS_STORAGE > > help > > USB mass storage support > > > > +config CMD_PVBLOCK > > + bool "Xen para-virtualized block device" > > + depends on XEN > > + select PVBLOCK > > + help > > + Xen para-virtualized block device support > > + > > config CMD_VIRTIO > > bool "virtio" > > depends on VIRTIO > > diff --git a/cmd/Makefile b/cmd/Makefile > > index 974ad48b0a..117284a28c 100644 > > --- a/cmd/Makefile > > +++ b/cmd/Makefile > > @@ -169,6 +169,7 @@ obj-$(CONFIG_CMD_DFU) += dfu.o > > obj-$(CONFIG_CMD_GPT) += gpt.o > > obj-$(CONFIG_CMD_ETHSW) += ethsw.o > > obj-$(CONFIG_CMD_AXI) += axi.o > > +obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o > > > > # Power > > obj-$(CONFIG_CMD_PMIC) += pmic.o > > diff --git a/cmd/pvblock.c b/cmd/pvblock.c > > new file mode 100644 > > index 0000000000..7dbb243a74 > > --- /dev/null > > +++ b/cmd/pvblock.c > > @@ -0,0 +1,31 @@ > > +/* > > + * SPDX-License-Identifier: GPL-2.0+ > > Please, correct the formatting. > > https://urldefense.com/v3/__https://www.kernel.org/doc/html/latest/process/license-rules.html*license-identifier-syntax__;Iw!!GF_29dbcQIUBPA!jxsFCyOKmFzfwm6JpWhcYhyr_qGk_okiGw-S0zzuQwWAleeoT0qjgG6bmf0_OfcJMo3d-dM$ > > Ok. > > + * > > + * (C) Copyright 2020 EPAM Systems Inc. > > + * > > + * XEN para-virtualized block device support > > + */ > > + > > +#include <blk.h> > > +#include <common.h> > > +#include <command.h> > > + > > +/* Current I/O Device */ > > +static int pvblock_curr_device; > > + > > +int do_pvblock(struct cmd_tbl *cmdtp, int flag, int argc, char > > *const argv[]) > > +{ > > + return blk_common_cmd(argc, argv, IF_TYPE_PVBLOCK, > > + &pvblock_curr_device); > > +} > > + > > +U_BOOT_CMD(pvblock, 5, 1, do_pvblock, > > + "Xen para-virtualized block device", > > + "info - show available block devices\n" > > + "pvblock device [dev] - show or set current device\n" > > + "pvblock part [dev] - print partition table of one or all > > devices\n" > > + "pvblock read addr blk# cnt\n" > > + "pvblock write addr blk# cnt - read/write `cnt'" > > + " blocks starting at block `blk#'\n" > > + " to/from memory address `addr'"); > > + > > diff --git a/common/board_r.c b/common/board_r.c > > index fd36edb4e5..40cd0e5d3c 100644 > > --- a/common/board_r.c > > +++ b/common/board_r.c > > @@ -49,6 +49,7 @@ > > #include <nand.h> > > #include <of_live.h> > > #include <onenand_uboot.h> > > +#include <pvblock.h> > > #include <scsi.h> > > #include <serial.h> > > #include <status_led.h> > > @@ -470,6 +471,16 @@ static int initr_xen(void) > > return 0; > > } > > #endif > > + > > +#ifdef CONFIG_PVBLOCK > > +static int initr_pvblock(void) > > +{ > > + puts("PVBLOCK: "); > > + pvblock_init(); > > + return 0; > > +} > > +#endif > > + > > /* > > * Tell if it's OK to load the environment early in boot. > > * > > @@ -780,6 +791,9 @@ static init_fnc_t init_sequence_r[] = { > > #endif > > #ifdef CONFIG_XEN > > initr_xen, > > +#endif > > +#ifdef CONFIG_PVBLOCK > > + initr_pvblock, > > #endif > > initr_env, > > #ifdef CONFIG_SYS_BOOTPARAMS_LEN > > diff --git a/configs/xenguest_arm64_defconfig > > b/configs/xenguest_arm64_defconfig > > index 45559a161b..46473c251d 100644 > > --- a/configs/xenguest_arm64_defconfig > > +++ b/configs/xenguest_arm64_defconfig > > @@ -14,6 +14,8 @@ CONFIG_CMD_BOOTD=n > > CONFIG_CMD_BOOTEFI=n > > CONFIG_CMD_BOOTEFI_HELLO_COMPILE=n > > CONFIG_CMD_ELF=n > > +CONFIG_CMD_EXT4=y > > +CONFIG_CMD_FAT=y > > CONFIG_CMD_GO=n > > CONFIG_CMD_RUN=n > > CONFIG_CMD_IMI=n > > @@ -41,6 +43,8 @@ CONFIG_CMD_LZMADEC=n > > CONFIG_CMD_SAVEENV=n > > CONFIG_CMD_UMS=n > > > > +CONFIG_CMD_PVBLOCK=y > > + > > #CONFIG_USB=n > > # CONFIG_ISO_PARTITION is not set > > > > diff --git a/disk/part.c b/disk/part.c > > index f6a31025dc..b69fd345f3 100644 > > --- a/disk/part.c > > +++ b/disk/part.c > > @@ -149,6 +149,7 @@ void dev_print (struct blk_desc *dev_desc) > > case IF_TYPE_MMC: > > case IF_TYPE_USB: > > case IF_TYPE_NVME: > > + case IF_TYPE_PVBLOCK: > > printf ("Vendor: %s Rev: %s Prod: %s\n", > > dev_desc->vendor, > > dev_desc->revision, > > @@ -288,6 +289,9 @@ static void print_part_header(const char *type, > > struct blk_desc *dev_desc) > > case IF_TYPE_NVME: > > puts ("NVMe"); > > break; > > + case IF_TYPE_PVBLOCK: > > + puts("PV BLOCK"); > > + break; > > case IF_TYPE_VIRTIO: > > puts("VirtIO"); > > break; > > diff --git a/drivers/Kconfig b/drivers/Kconfig > > index e34a22708c..65076aab03 100644 > > --- a/drivers/Kconfig > > +++ b/drivers/Kconfig > > @@ -132,6 +132,8 @@ source "drivers/w1-eeprom/Kconfig" > > > > source "drivers/watchdog/Kconfig" > > > > +source "drivers/xen/Kconfig" > > + > > config PHYS_TO_BUS > > bool "Custom physical to bus address mapping" > > help > > diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk- > > uclass.c > > index b19375cbc8..6cfabbca24 100644 > > --- a/drivers/block/blk-uclass.c > > +++ b/drivers/block/blk-uclass.c > > @@ -28,6 +28,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] > > = { > > [IF_TYPE_NVME] = "nvme", > > [IF_TYPE_EFI] = "efi", > > [IF_TYPE_VIRTIO] = "virtio", > > + [IF_TYPE_PVBLOCK] = "pvblock", > > }; > > > > static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { > > @@ -43,6 +44,7 @@ static enum uclass_id > > if_type_uclass_id[IF_TYPE_COUNT] = { > > [IF_TYPE_NVME] = UCLASS_NVME, > > [IF_TYPE_EFI] = UCLASS_EFI, > > [IF_TYPE_VIRTIO] = UCLASS_VIRTIO, > > + [IF_TYPE_PVBLOCK] = UCLASS_PVBLOCK, > > }; > > > > static enum if_type if_typename_to_iftype(const char *if_typename) > > diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig > > new file mode 100644 > > index 0000000000..6ad2a93668 > > --- /dev/null > > +++ b/drivers/xen/Kconfig > > @@ -0,0 +1,10 @@ > > +config PVBLOCK > > + bool "Xen para-virtualized block device" > > + depends on DM > > + select BLK > > + select HAVE_BLOCK_DEVICE > > + help > > + This driver implements the front-end of the Xen virtual > > + block device driver. It communicates with a back-end driver > > + in another domain which drives the actual block device. > > + > > diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile > > index 243b13277a..87157df69b 100644 > > --- a/drivers/xen/Makefile > > +++ b/drivers/xen/Makefile > > @@ -6,3 +6,5 @@ obj-y += hypervisor.o > > obj-y += events.o > > obj-y += xenbus.o > > obj-y += gnttab.o > > + > > +obj-$(CONFIG_PVBLOCK) += pvblock.o > > diff --git a/drivers/xen/pvblock.c b/drivers/xen/pvblock.c > > new file mode 100644 > > index 0000000000..057add9753 > > --- /dev/null > > +++ b/drivers/xen/pvblock.c > > @@ -0,0 +1,121 @@ > > +/* > > + * SPDX-License-Identifier: GPL-2.0+ > > See above. > Ok, will fix. > > + * > > + * (C) Copyright 2020 EPAM Systems Inc. > > + */ > > +#include <blk.h> > > +#include <common.h> > > +#include <dm.h> > > +#include <dm/device-internal.h> > > + > > +#define DRV_NAME "pvblock" > > +#define DRV_NAME_BLK "pvblock_blk" > > + > > +struct blkfront_dev { > > + char dummy; > > +}; > > + > > +static int init_blkfront(unsigned int devid, struct blkfront_dev > > *dev) > > +{ > > + return 0; > > +} > > + > > +static void shutdown_blkfront(struct blkfront_dev *dev) > > +{ > > +} > > + > > +ulong pvblock_blk_read(struct udevice *udev, lbaint_t blknr, > > lbaint_t blkcnt, > > + void *buffer) > > +{ > > + return 0; > > +} > > + > > +ulong pvblock_blk_write(struct udevice *udev, lbaint_t blknr, > > lbaint_t blkcnt, > > + const void *buffer) > > +{ > > + return 0; > > +} > > + > > +static int pvblock_blk_bind(struct udevice *udev) > > +{ > > + return 0; > > +} > > + > > +static int pvblock_blk_probe(struct udevice *udev) > > +{ > > + struct blkfront_dev *blk_dev = dev_get_priv(udev); > > + int ret; > > + > > + ret = init_blkfront(0, blk_dev); > > + if (ret < 0) > > + return ret; > > + return 0; > > +} > > + > > +static int pvblock_blk_remove(struct udevice *udev) > > +{ > > + struct blkfront_dev *blk_dev = dev_get_priv(udev); > > + > > + shutdown_blkfront(blk_dev); > > + return 0; > > +} > > + > > +static const struct blk_ops pvblock_blk_ops = { > > + .read = pvblock_blk_read, > > + .write = pvblock_blk_write, > > +}; > > + > > +U_BOOT_DRIVER(pvblock_blk) = { > > + .name = DRV_NAME_BLK, > > + .id = UCLASS_BLK, > > + .ops = &pvblock_blk_ops, > > + .bind = pvblock_blk_bind, > > + .probe = pvblock_blk_probe, > > + .remove = pvblock_blk_remove, > > + .priv_auto_alloc_size = sizeof(struct blkfront_dev), > > + .flags = DM_FLAG_OS_PREPARE, > > +}; > > + > > +/***************************************************************** > > ************** > > + * Para-virtual block device class > > + > > ******************************************************************* > > ************/ > > + > > +void pvblock_init(void) > > +{ > > + struct driver_info info; > > + struct udevice *udev; > > + struct uclass *uc; > > + int ret; > > + > > + /* > > + * At this point Xen drivers have already initialized, > > + * so we can instantiate the class driver and enumerate > > + * virtual block devices. > > + */ > > + info.name = DRV_NAME; > > + ret = device_bind_by_name(gd->dm_root, false, &info, &udev); > > + if (ret < 0) > > + printf("Failed to bind " DRV_NAME ", ret: %d\n", ret); > > + > > + /* Bootstrap virtual block devices class driver */ > > + ret = uclass_get(UCLASS_PVBLOCK, &uc); > > + if (ret) > > + return; > > + uclass_foreach_dev_probe(UCLASS_PVBLOCK, udev); > > +} > > + > > +static int pvblock_probe(struct udevice *udev) > > +{ > > + return 0; > > +} > > + > > +U_BOOT_DRIVER(pvblock_drv) = { > > + .name = DRV_NAME, > > + .id = UCLASS_PVBLOCK, > > + .probe = pvblock_probe, > > +}; > > + > > +UCLASS_DRIVER(pvblock) = { > > + .name = DRV_NAME, > > + .id = UCLASS_PVBLOCK, > > +}; > > diff --git a/include/blk.h b/include/blk.h > > index abcd4bedbb..9ee10fb80e 100644 > > --- a/include/blk.h > > +++ b/include/blk.h > > @@ -33,6 +33,7 @@ enum if_type { > > IF_TYPE_HOST, > > IF_TYPE_NVME, > > IF_TYPE_EFI, > > + IF_TYPE_PVBLOCK, > > IF_TYPE_VIRTIO, > > > > IF_TYPE_COUNT, /* Number of interface > > types */ > > diff --git a/include/configs/xenguest_arm64.h > > b/include/configs/xenguest_arm64.h > > index 467dabf1e5..2c0d3d64fb 100644 > > --- a/include/configs/xenguest_arm64.h > > +++ b/include/configs/xenguest_arm64.h > > @@ -42,4 +42,12 @@ > > #define CONFIG_CMDLINE_TAG 1 > > #define CONFIG_INITRD_TAG 1 > > > > +#define CONFIG_CMD_RUN > > + > > +#undef CONFIG_EXTRA_ENV_SETTINGS > > +#define CONFIG_EXTRA_ENV_SETTINGS \ > > + "loadimage=ext4load pvblock 0 0x90000000 /boot/Image;\0" \ > > + "pvblockboot=run loadimage;" \ > > + "booti 0x90000000 - 0x88000000;\0" > > + > > #endif /* __XENGUEST_ARM64_H */ > > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h > > index 7837d459f1..4bf7501204 100644 > > --- a/include/dm/uclass-id.h > > +++ b/include/dm/uclass-id.h > > @@ -121,6 +121,7 @@ enum uclass_id { > > UCLASS_W1, /* Dallas 1-Wire bus */ > > UCLASS_W1_EEPROM, /* one-wire EEPROMs */ > > UCLASS_WDT, /* Watchdog Timer driver */ > > + UCLASS_PVBLOCK, /* Xen virtual block device */ > > > > UCLASS_COUNT, > > UCLASS_INVALID = -1, > > diff --git a/include/pvblock.h b/include/pvblock.h > > new file mode 100644 > > index 0000000000..e3bb8ff9a7 > > --- /dev/null > > +++ b/include/pvblock.h > > @@ -0,0 +1,12 @@ > > +/* > > + * SPDX-License-Identifier: GPL-2.0+ > > See above. > > scripts/checkpatch.pl is your friend. > > > + * > > + * (C) 2020 EPAM Systems Inc. > > + */ > > + > > +#ifndef _PVBLOCK_H > > +#define _PVBLOCK_H > > + > > Document you functions as described in > > https://urldefense.com/v3/__https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html*function-documentation__;Iw!!GF_29dbcQIUBPA!jxsFCyOKmFzfwm6JpWhcYhyr_qGk_okiGw-S0zzuQwWAleeoT0qjgG6bmf0_OfcJcWTT8IY$ > > > > Include the documentation in the HTML documentation generated by > > make htmldocs. Ok, will add. > > Best regards > > Heinrich > Best regards, Anastasiia > > +void pvblock_init(void); > > + > > +#endif /* _PVBLOCK_H */ > > > >
diff --git a/cmd/Kconfig b/cmd/Kconfig index 192b3b262f..f28576947b 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1335,6 +1335,13 @@ config CMD_USB_MASS_STORAGE help USB mass storage support +config CMD_PVBLOCK + bool "Xen para-virtualized block device" + depends on XEN + select PVBLOCK + help + Xen para-virtualized block device support + config CMD_VIRTIO bool "virtio" depends on VIRTIO diff --git a/cmd/Makefile b/cmd/Makefile index 974ad48b0a..117284a28c 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -169,6 +169,7 @@ obj-$(CONFIG_CMD_DFU) += dfu.o obj-$(CONFIG_CMD_GPT) += gpt.o obj-$(CONFIG_CMD_ETHSW) += ethsw.o obj-$(CONFIG_CMD_AXI) += axi.o +obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o # Power obj-$(CONFIG_CMD_PMIC) += pmic.o diff --git a/cmd/pvblock.c b/cmd/pvblock.c new file mode 100644 index 0000000000..7dbb243a74 --- /dev/null +++ b/cmd/pvblock.c @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + * + * (C) Copyright 2020 EPAM Systems Inc. + * + * XEN para-virtualized block device support + */ + +#include <blk.h> +#include <common.h> +#include <command.h> + +/* Current I/O Device */ +static int pvblock_curr_device; + +int do_pvblock(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + return blk_common_cmd(argc, argv, IF_TYPE_PVBLOCK, + &pvblock_curr_device); +} + +U_BOOT_CMD(pvblock, 5, 1, do_pvblock, + "Xen para-virtualized block device", + "info - show available block devices\n" + "pvblock device [dev] - show or set current device\n" + "pvblock part [dev] - print partition table of one or all devices\n" + "pvblock read addr blk# cnt\n" + "pvblock write addr blk# cnt - read/write `cnt'" + " blocks starting at block `blk#'\n" + " to/from memory address `addr'"); + diff --git a/common/board_r.c b/common/board_r.c index fd36edb4e5..40cd0e5d3c 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -49,6 +49,7 @@ #include <nand.h> #include <of_live.h> #include <onenand_uboot.h> +#include <pvblock.h> #include <scsi.h> #include <serial.h> #include <status_led.h> @@ -470,6 +471,16 @@ static int initr_xen(void) return 0; } #endif + +#ifdef CONFIG_PVBLOCK +static int initr_pvblock(void) +{ + puts("PVBLOCK: "); + pvblock_init(); + return 0; +} +#endif + /* * Tell if it's OK to load the environment early in boot. * @@ -780,6 +791,9 @@ static init_fnc_t init_sequence_r[] = { #endif #ifdef CONFIG_XEN initr_xen, +#endif +#ifdef CONFIG_PVBLOCK + initr_pvblock, #endif initr_env, #ifdef CONFIG_SYS_BOOTPARAMS_LEN diff --git a/configs/xenguest_arm64_defconfig b/configs/xenguest_arm64_defconfig index 45559a161b..46473c251d 100644 --- a/configs/xenguest_arm64_defconfig +++ b/configs/xenguest_arm64_defconfig @@ -14,6 +14,8 @@ CONFIG_CMD_BOOTD=n CONFIG_CMD_BOOTEFI=n CONFIG_CMD_BOOTEFI_HELLO_COMPILE=n CONFIG_CMD_ELF=n +CONFIG_CMD_EXT4=y +CONFIG_CMD_FAT=y CONFIG_CMD_GO=n CONFIG_CMD_RUN=n CONFIG_CMD_IMI=n @@ -41,6 +43,8 @@ CONFIG_CMD_LZMADEC=n CONFIG_CMD_SAVEENV=n CONFIG_CMD_UMS=n +CONFIG_CMD_PVBLOCK=y + #CONFIG_USB=n # CONFIG_ISO_PARTITION is not set diff --git a/disk/part.c b/disk/part.c index f6a31025dc..b69fd345f3 100644 --- a/disk/part.c +++ b/disk/part.c @@ -149,6 +149,7 @@ void dev_print (struct blk_desc *dev_desc) case IF_TYPE_MMC: case IF_TYPE_USB: case IF_TYPE_NVME: + case IF_TYPE_PVBLOCK: printf ("Vendor: %s Rev: %s Prod: %s\n", dev_desc->vendor, dev_desc->revision, @@ -288,6 +289,9 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc) case IF_TYPE_NVME: puts ("NVMe"); break; + case IF_TYPE_PVBLOCK: + puts("PV BLOCK"); + break; case IF_TYPE_VIRTIO: puts("VirtIO"); break; diff --git a/drivers/Kconfig b/drivers/Kconfig index e34a22708c..65076aab03 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -132,6 +132,8 @@ source "drivers/w1-eeprom/Kconfig" source "drivers/watchdog/Kconfig" +source "drivers/xen/Kconfig" + config PHYS_TO_BUS bool "Custom physical to bus address mapping" help diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index b19375cbc8..6cfabbca24 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -28,6 +28,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = { [IF_TYPE_NVME] = "nvme", [IF_TYPE_EFI] = "efi", [IF_TYPE_VIRTIO] = "virtio", + [IF_TYPE_PVBLOCK] = "pvblock", }; static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { @@ -43,6 +44,7 @@ static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { [IF_TYPE_NVME] = UCLASS_NVME, [IF_TYPE_EFI] = UCLASS_EFI, [IF_TYPE_VIRTIO] = UCLASS_VIRTIO, + [IF_TYPE_PVBLOCK] = UCLASS_PVBLOCK, }; static enum if_type if_typename_to_iftype(const char *if_typename) diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig new file mode 100644 index 0000000000..6ad2a93668 --- /dev/null +++ b/drivers/xen/Kconfig @@ -0,0 +1,10 @@ +config PVBLOCK + bool "Xen para-virtualized block device" + depends on DM + select BLK + select HAVE_BLOCK_DEVICE + help + This driver implements the front-end of the Xen virtual + block device driver. It communicates with a back-end driver + in another domain which drives the actual block device. + diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 243b13277a..87157df69b 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -6,3 +6,5 @@ obj-y += hypervisor.o obj-y += events.o obj-y += xenbus.o obj-y += gnttab.o + +obj-$(CONFIG_PVBLOCK) += pvblock.o diff --git a/drivers/xen/pvblock.c b/drivers/xen/pvblock.c new file mode 100644 index 0000000000..057add9753 --- /dev/null +++ b/drivers/xen/pvblock.c @@ -0,0 +1,121 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + * + * (C) Copyright 2020 EPAM Systems Inc. + */ +#include <blk.h> +#include <common.h> +#include <dm.h> +#include <dm/device-internal.h> + +#define DRV_NAME "pvblock" +#define DRV_NAME_BLK "pvblock_blk" + +struct blkfront_dev { + char dummy; +}; + +static int init_blkfront(unsigned int devid, struct blkfront_dev *dev) +{ + return 0; +} + +static void shutdown_blkfront(struct blkfront_dev *dev) +{ +} + +ulong pvblock_blk_read(struct udevice *udev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + return 0; +} + +ulong pvblock_blk_write(struct udevice *udev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +{ + return 0; +} + +static int pvblock_blk_bind(struct udevice *udev) +{ + return 0; +} + +static int pvblock_blk_probe(struct udevice *udev) +{ + struct blkfront_dev *blk_dev = dev_get_priv(udev); + int ret; + + ret = init_blkfront(0, blk_dev); + if (ret < 0) + return ret; + return 0; +} + +static int pvblock_blk_remove(struct udevice *udev) +{ + struct blkfront_dev *blk_dev = dev_get_priv(udev); + + shutdown_blkfront(blk_dev); + return 0; +} + +static const struct blk_ops pvblock_blk_ops = { + .read = pvblock_blk_read, + .write = pvblock_blk_write, +}; + +U_BOOT_DRIVER(pvblock_blk) = { + .name = DRV_NAME_BLK, + .id = UCLASS_BLK, + .ops = &pvblock_blk_ops, + .bind = pvblock_blk_bind, + .probe = pvblock_blk_probe, + .remove = pvblock_blk_remove, + .priv_auto_alloc_size = sizeof(struct blkfront_dev), + .flags = DM_FLAG_OS_PREPARE, +}; + +/******************************************************************************* + * Para-virtual block device class + *******************************************************************************/ + +void pvblock_init(void) +{ + struct driver_info info; + struct udevice *udev; + struct uclass *uc; + int ret; + + /* + * At this point Xen drivers have already initialized, + * so we can instantiate the class driver and enumerate + * virtual block devices. + */ + info.name = DRV_NAME; + ret = device_bind_by_name(gd->dm_root, false, &info, &udev); + if (ret < 0) + printf("Failed to bind " DRV_NAME ", ret: %d\n", ret); + + /* Bootstrap virtual block devices class driver */ + ret = uclass_get(UCLASS_PVBLOCK, &uc); + if (ret) + return; + uclass_foreach_dev_probe(UCLASS_PVBLOCK, udev); +} + +static int pvblock_probe(struct udevice *udev) +{ + return 0; +} + +U_BOOT_DRIVER(pvblock_drv) = { + .name = DRV_NAME, + .id = UCLASS_PVBLOCK, + .probe = pvblock_probe, +}; + +UCLASS_DRIVER(pvblock) = { + .name = DRV_NAME, + .id = UCLASS_PVBLOCK, +}; diff --git a/include/blk.h b/include/blk.h index abcd4bedbb..9ee10fb80e 100644 --- a/include/blk.h +++ b/include/blk.h @@ -33,6 +33,7 @@ enum if_type { IF_TYPE_HOST, IF_TYPE_NVME, IF_TYPE_EFI, + IF_TYPE_PVBLOCK, IF_TYPE_VIRTIO, IF_TYPE_COUNT, /* Number of interface types */ diff --git a/include/configs/xenguest_arm64.h b/include/configs/xenguest_arm64.h index 467dabf1e5..2c0d3d64fb 100644 --- a/include/configs/xenguest_arm64.h +++ b/include/configs/xenguest_arm64.h @@ -42,4 +42,12 @@ #define CONFIG_CMDLINE_TAG 1 #define CONFIG_INITRD_TAG 1 +#define CONFIG_CMD_RUN + +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + "loadimage=ext4load pvblock 0 0x90000000 /boot/Image;\0" \ + "pvblockboot=run loadimage;" \ + "booti 0x90000000 - 0x88000000;\0" + #endif /* __XENGUEST_ARM64_H */ diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 7837d459f1..4bf7501204 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -121,6 +121,7 @@ enum uclass_id { UCLASS_W1, /* Dallas 1-Wire bus */ UCLASS_W1_EEPROM, /* one-wire EEPROMs */ UCLASS_WDT, /* Watchdog Timer driver */ + UCLASS_PVBLOCK, /* Xen virtual block device */ UCLASS_COUNT, UCLASS_INVALID = -1, diff --git a/include/pvblock.h b/include/pvblock.h new file mode 100644 index 0000000000..e3bb8ff9a7 --- /dev/null +++ b/include/pvblock.h @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + * + * (C) 2020 EPAM Systems Inc. + */ + +#ifndef _PVBLOCK_H +#define _PVBLOCK_H + +void pvblock_init(void); + +#endif /* _PVBLOCK_H */