[RFC 00/22] efi_loader: more tightly integrate UEFI disks to device model

The purpose of this RPC is to reignite the discussion about how UEFI subystem would best be integrated into U-Boot device model. In the past, I poposed a couple of patch series, the latest one[1], while Heinrich revealed his idea[2], and the approach taken here is something between them, with a focus on block device handlings.
# The code is a PoC and not well tested yet.
Disks in UEFI world: ==================== In general in UEFI world, accessing to any device is performed through a 'protocol' interface which are installed to (or associated with) the device's UEFI handle (or an opaque pointer to UEFI object data). Protocols are implemented by either the UEFI system itself or UEFI drivers.
For block IO's, it is a device which has EFI_BLOCK_IO_PROTOCOL (efi_disk hereafter). Currently, every efi_disk may have one of two origins: a.U-Boot's block devices or related partitions (lib/efi_loader/efi_disk.c) b.UEFI objects which are implemented as a block device by UEFI drivers. (lib/efi_driver/efi_block_device.c)
All the efi_diskss as (a) will be enumelated and created only once at UEFI subsystem initialization (efi_disk_register()), which is triggered by first executing one of UEFI-related U-Boot commands, like "bootefi", "setenv -e" or "efidebug". EFI_BLOCK_IO_PROTOCOL is implemented by UEFI system using blk_desc(->ops) in the corresponding udevice(UCLASS_BLK).
On the other hand, efi_disk as (b) will be created each time UEFI boot services' connect_controller() is executed in UEFI app which, as a (device) controller, gives the method to access the device's data, ie. EFI_BLOCK_IO_PROTOCOL.
more details >>>
Internally, connect_controller() search for UEFI driver that can support this controller/protocol, 'efi_block' driver(UCLASS_EFI) in this case, then calls the driver's 'bind' interface, which eventually installs the controller's EFI_BLOCK_IO_PROTOCOL to efi_disk object. 'efi_block' driver also create a corresponding udevice(UCLASS_BLK) for * creating additional partitions efi_disk's, and * supporting a file system (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL) on it. <<< <<<
Issues: ======= 1. While an efi_disk represents a device equally for either a whole disk or a partition in UEFI world, the device model treats only a whole disk as a real block device or udevice(UCLASS_BLK).
2. efi_disk holds and makes use of "blk_desc" data even though blk_desc in plat_data is supposed to be private and not to be accessed outside the device model. # This issue, though, exists for all the implmenetation of U-Boot # file systems as well.
For efi_disk(a), 3. A block device can be enumelated dynamically by 'scanning' a device bus in U-Boot, but UEFI subsystem is not able to update efi_disks accordingly. For examples, => scsi rescan; efidebug devices => usb start; efidebug devices ... (A) (A) doesn't show any usb devices detected.
=> scsi rescan; efidebug boot add -b 0 TEST scsi 0:1 ... => scsi rescan ... (B) => bootefi bootmgr ... (C) (C) may de-reference a bogus blk_desc pointer which has been freed by (B). (Please note that "scsi rescan" removes all udevices/blk_desc and then re-create them even if nothing is changed on a bus.)
For efi_disk(b), 4. A controller (handle), combined with efi_block driver, has no corresponding udevice as a parent of efi_disks in DM tree, unlike, say, a scsi controller, even though it provides methods for block io perations. 5. There is no way supported to remove efi_disk's even after disconnect_controller() is called.
My approach in this RFC: ======================== Due to functional differences in semantics, it would be difficult to identify "udevice" structure as a handle in UEFI world. Instead, we will have to somehow maintain a relationship between a udevice and a handle.
1-1. add a dedicated uclass, UCLASS_PARTITION, for partitions Currently, the uclass for paritions is not a UCLASS_BLK. It can be possible to define partitions as UCLASS_BLK (with IF_TYPE_PARTION?), but I'm afraid that it may introduce some chaos since udevice(UCLASS_BLK) is tightly coupled with 'struct blk_desc' data which is still used as a "structure to a whole disk" in a lot of interfaces. (I hope that you understand what it means.)
In DM tree, a UCLASS_PARTITON instance has a UCLASS_BLK parent: For instance, UCLASS_SCSI --- UCLASS_BLK --- UCLASS_PARTITION (IF_TYPE_SCSI) | +- struct blk_desc +- struct disk_part +- scsi_blk_ops +- blk_part_ops
1-2. create partition udevices in the context of device_probe() part_init() is already called in blk_post_probe(). See the commit d0851c893706 ("blk: Call part_init() in the post_probe() method"). Why not enumelate partitions as well in there.
2. add new block access interfaces, which takes "udevice" as a target device, in U-Boot and use those functions to implement efi_disk operations (i.e. EFI_BLOCK_IO_PROTOCOL).
3-1. maintain a bi-directional link by adding - a UEFI handle pointer in "struct udevice" - a udevice pointer in UEFI handle (in fact, in "struct efi_disk_obj")
3-2. use device model's post_probe/pre_remove hook to synchronize the lifetime of efi_disk objects in UEFI world with the device model.
4. I have no answer to issue(4) and (5) yet.
Patchs: ======= For easy understandings, patches may be categorized into seperate groups of changes.
Patch#1-#9: DM: create udevices for partitions Patch#11,#12: UEFI: use udevice interfaces Patch#13-#16: UEFI: sync up with the device model for adding Patch#17-#19: UEFI: sync up with the device model for removing For removal case, we may need more consideration since removing handles unconditionally may end up breaking integrity of handles (some may still be held and referenced to by a UEFI app). Patch#20-#22: UEFI: align efi_driver with changes by the integration
[1] https://lists.denx.de/pipermail/u-boot/2019-February/357923.html [2] https://lists.denx.de/pipermail/u-boot/2021-June/452297.html
AKASHI Takahiro (22): scsi: call device_probe() after scanning usb: storage: call device_probe() after scanning mmc: call device_probe() after scanning nvme: call device_probe() after scanning sata: call device_probe() after scanning block: ide: call device_probe() after scanning dm: blk: add UCLASS_PARTITION dm: blk: add a device-probe hook for scanning disk partitions dm: blk: add read/write interfaces with udevice efi_loader: disk: use udevice instead of blk_desc dm: add a hidden link to efi object efi_loader: remove !CONFIG_BLK code from efi_disk efi_loader: disk: a helper function to create efi_disk objects from udevice dm: blk: call efi's device-probe hook efi_loader: cleanup after efi_disk-dm integration efi_loader: add efi_remove_handle() efi_loader: efi_disk: a helper function to delete efi_disk objects dm: blk: call efi's device-removal hook efi_driver: align with efi_disk-dm integration efi_driver: cleanup after efi_disk-dm integration efi_selftest: block device: adjust dp for a test disk (TEST) let dm-tree unchanged after block_io testing is done
common/usb_storage.c | 6 + drivers/ata/dwc_ahsata.c | 10 + drivers/ata/fsl_sata.c | 11 + drivers/ata/sata_mv.c | 9 + drivers/ata/sata_sil.c | 12 + drivers/block/blk-uclass.c | 249 ++++++++++++++++ drivers/block/ide.c | 6 + drivers/mmc/mmc-uclass.c | 7 + drivers/nvme/nvme.c | 6 + drivers/scsi/scsi.c | 10 + include/blk.h | 15 + include/dm/device.h | 4 + include/dm/uclass-id.h | 1 + include/efi_loader.h | 8 +- lib/efi_driver/efi_block_device.c | 30 +- lib/efi_loader/efi_boottime.c | 8 + lib/efi_loader/efi_device_path.c | 29 ++ lib/efi_loader/efi_disk.c | 286 ++++++++++--------- lib/efi_loader/efi_setup.c | 5 - lib/efi_selftest/efi_selftest_block_device.c | 28 +- 20 files changed, 566 insertions(+), 174 deletions(-)

In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- disk/part.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/disk/part.c b/disk/part.c index a6a8f7052bd3..b330103a5bc0 100644 --- a/disk/part.c +++ b/disk/part.c @@ -427,7 +427,8 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, * Always should be done, otherwise hw partition 0 will return stale * data after displaying a non-zero hw partition. */ - part_init(*dev_desc); + if ((*dev_desc)->if_type == IF_TYPE_MMC) + part_init(*dev_desc); #endif
cleanup:

On 10/1/21 7:01 AM, AKASHI Takahiro wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
disk/part.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/disk/part.c b/disk/part.c index a6a8f7052bd3..b330103a5bc0 100644 --- a/disk/part.c +++ b/disk/part.c @@ -427,7 +427,8 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, * Always should be done, otherwise hw partition 0 will return stale * data after displaying a non-zero hw partition. */
- part_init(*dev_desc);
- if ((*dev_desc)->if_type == IF_TYPE_MMC)
part_init(*dev_desc);
For an eMMC the following logical levels exist:
* device * hardware partition * software partition
Linux might show the following:
/dev/mmcblk0 - user data area /dev/mmcblk0boot0 - boot hardware partition 0 /dev/mmcblk0boot1 - boot hardware partition 1 /dev/mmcblk0rpmb - replay protected memory block
How are the different hardware partition modeled in the UEFI device path? Should each hardware partition be a separate udevice?
For NOR flash we also have an extra level:
=> setenv mtdparts mtdparts=30bb0000.qspi:1m(U-Boot),512k(Env),512k(DTB),2m(User_FS),12m(Data_FS),4m(Factory_FS),34m(Ramdisk),10m(Linux) => mtd
device nor0 <30bb0000.qspi>, # parts = 8 #: name size offset mask_flags 0: U-Boot 0x00100000 0x00000000 0 1: Env 0x00080000 0x00100000 0 2: DTB 0x00080000 0x00180000 0 3: User_FS 0x00200000 0x00200000 0 4: Data_FS 0x00c00000 0x00400000 0 5: Factory_FS 0x00400000 0x01000000 0 6: Ramdisk 0x02200000 0x01400000 0 7: Linux 0x00a00000 0x03600000 0
active partition: nor0,0 - (U-Boot) 0x00100000 @ 0x00000000
Has part_info() to be called here too? What is the if_type? What are the devicepaths for these partitions?
Best regards
Heinrich
#endif
cleanup:

On 10/1/21 08:41, Heinrich Schuchardt wrote:
On 10/1/21 7:01 AM, AKASHI Takahiro wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
disk/part.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/disk/part.c b/disk/part.c index a6a8f7052bd3..b330103a5bc0 100644 --- a/disk/part.c +++ b/disk/part.c @@ -427,7 +427,8 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, * Always should be done, otherwise hw partition 0 will return stale * data after displaying a non-zero hw partition. */ - part_init(*dev_desc); + if ((*dev_desc)->if_type == IF_TYPE_MMC) + part_init(*dev_desc);
For an eMMC the following logical levels exist:
- device
- hardware partition
- software partition
Linux might show the following:
/dev/mmcblk0 - user data area /dev/mmcblk0boot0 - boot hardware partition 0 /dev/mmcblk0boot1 - boot hardware partition 1 /dev/mmcblk0rpmb - replay protected memory block
How are the different hardware partition modeled in the UEFI device path?
This is a list of block devices with their Linux name and the device path in EDK II as seen on my MacchicatoBIN board:
/dev/mmcblk0 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,00006EF00000000000)/eMMC(0x0)/Ctrl(0x0)
/dev/mmcblk0p1 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,00006EF00000000000)/eMMC(0x0)/Ctrl(0x0)/HD(1,GPT,C53259E6-9B1D-40CD-B4EF-39520011EF2B,0x2000,0x3FE001)
/dev/mmcblk0p2 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,00006EF00000000000)/eMMC(0x0)/Ctrl(0x0)/HD(2,GPT,A0AE9901-B847-4150-B947-6C8FF69529A7,0x400800,0xA8F7DF)
/dev/mmcblk0boot0 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,00006EF00000000000)/eMMC(0x0)/Ctrl(0x1)
/dev/mmcblk0boot1 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,00006EF00000000000)/eMMC(0x0)/Ctrl(0x2)
Should each hardware partition be a separate udevice?
We need a udevice matching the hardware partition. These child devices should be created when the eMMC device is probed.
Best regards
Heinrich
For NOR flash we also have an extra level:
=> setenv mtdparts mtdparts=30bb0000.qspi:1m(U-Boot),512k(Env),512k(DTB),2m(User_FS),12m(Data_FS),4m(Factory_FS),34m(Ramdisk),10m(Linux)
=> mtd
device nor0 <30bb0000.qspi>, # parts = 8 #: name size offset mask_flags 0: U-Boot 0x00100000 0x00000000 0 1: Env 0x00080000 0x00100000 0 2: DTB 0x00080000 0x00180000 0 3: User_FS 0x00200000 0x00200000 0 4: Data_FS 0x00c00000 0x00400000 0 5: Factory_FS 0x00400000 0x01000000 0 6: Ramdisk 0x02200000 0x01400000 0 7: Linux 0x00a00000 0x03600000 0
active partition: nor0,0 - (U-Boot) 0x00100000 @ 0x00000000
Has part_info() to be called here too? What is the if_type? What are the devicepaths for these partitions?
Best regards
Heinrich
#endif
cleanup:

Heinrich,
On Fri, Oct 01, 2021 at 08:41:52AM +0200, Heinrich Schuchardt wrote:
On 10/1/21 7:01 AM, AKASHI Takahiro wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
disk/part.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/disk/part.c b/disk/part.c index a6a8f7052bd3..b330103a5bc0 100644 --- a/disk/part.c +++ b/disk/part.c @@ -427,7 +427,8 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, * Always should be done, otherwise hw partition 0 will return stale * data after displaying a non-zero hw partition. */
- part_init(*dev_desc);
- if ((*dev_desc)->if_type == IF_TYPE_MMC)
part_init(*dev_desc);
For an eMMC the following logical levels exist:
- device
- hardware partition
- software partition
Linux might show the following:
/dev/mmcblk0 - user data area /dev/mmcblk0boot0 - boot hardware partition 0 /dev/mmcblk0boot1 - boot hardware partition 1 /dev/mmcblk0rpmb - replay protected memory block
How are the different hardware partition modeled in the UEFI device path? Should each hardware partition be a separate udevice?
For NOR flash we also have an extra level:
=> setenv mtdparts mtdparts=30bb0000.qspi:1m(U-Boot),512k(Env),512k(DTB),2m(User_FS),12m(Data_FS),4m(Factory_FS),34m(Ramdisk),10m(Linux) => mtd
device nor0 <30bb0000.qspi>, # parts = 8 #: name size offset mask_flags 0: U-Boot 0x00100000 0x00000000 0 1: Env 0x00080000 0x00100000 0 2: DTB 0x00080000 0x00180000 0 3: User_FS 0x00200000 0x00200000 0 4: Data_FS 0x00c00000 0x00400000 0 5: Factory_FS 0x00400000 0x01000000 0 6: Ramdisk 0x02200000 0x01400000 0 7: Linux 0x00a00000 0x03600000 0
active partition: nor0,0 - (U-Boot) 0x00100000 @ 0x00000000
Has part_info() to be called here too? What is the if_type? What are the devicepaths for these partitions?
You have good points. MMC's hw partitions and mtd's "environment variable-based" partitions are quite different from the rest of table-based software partitions in terms of U-Boot block device implementation. Both neither are handled by part_info() (under disk/* framework) nor have dedicated "if_type's".
Even if we might have to address those issues at the end, I would like to keep them out of my scope for now as it requires a lot of extra work.
# I wonder if we should support mtdparts partitions on U-Boot UEFI # as it is a quite U-Boot specific feature.
-Takahiro Akashi
Best regards
Heinrich
#endif
cleanup:

On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
disk/part.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/disk/part.c b/disk/part.c index a6a8f7052bd3..b330103a5bc0 100644 --- a/disk/part.c +++ b/disk/part.c @@ -427,7 +427,8 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, * Always should be done, otherwise hw partition 0 will return stale * data after displaying a non-zero hw partition. */
part_init(*dev_desc);
if ((*dev_desc)->if_type == IF_TYPE_MMC)
part_init(*dev_desc);
#endif
cleanup:
2.33.0

Hi Peter,
On Fri, Oct 01, 2021 at 12:48:24PM +0100, Peter Robinson wrote:
On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
Yeah, maybe. But under the current implementation, IIUC, neither UFS nor NVME supports hw partitions as both drivers do not provide a "select_hwpart" function in blk_ops. (UFS is seen as an instance of SCSI.)
-Takahiro Akashi
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
disk/part.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/disk/part.c b/disk/part.c index a6a8f7052bd3..b330103a5bc0 100644 --- a/disk/part.c +++ b/disk/part.c @@ -427,7 +427,8 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, * Always should be done, otherwise hw partition 0 will return stale * data after displaying a non-zero hw partition. */
part_init(*dev_desc);
if ((*dev_desc)->if_type == IF_TYPE_MMC)
part_init(*dev_desc);
#endif
cleanup:
2.33.0

On 10/1/21 13:48, Peter Robinson wrote:
On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
An NVMe device may expose multiple namespaces. blk_create_devicef() is called for each namespace.
A SCSI device may have multiple LUNs. blk_create_devicef() is called for each LUN.
This is what the tree shown by 'dm tree' with on NVMe namespace and one LUN.
Class Index Driver Name --------------------------------------------------------------------- root 0 root_driver root_driver simple_bus 0 simple_bus |- soc spi 1 sifive_spi | |- spi@10050000 mmc 0 mmc_spi | | `- mmc@0 blk 0 mmc_blk | | `- mmc@0.blk pci 0 pcie_sifive | |- pcie@e00000000 pci 1 pci_bridge_drv | | `- pci_0:0.0 pci 2 pci_bridge_drv | | `- pci_1:0.0 pci 5 pci_bridge_drv | | |- pci_2:3.0 ahci 0 ahci_pci | | | `- ahci_pci scsi 0 ahci_scsi | | | `- ahci_scsi blk 2 scsi_blk | | | `- ahci_scsi.id0lun0 pci 6 pci_bridge_drv | | |- pci_2:4.0 nvme 0 nvme | | | `- nvme#0 blk 1 nvme-blk | | | `- nvme#0.blk#1
Namespaces and LUNs are modeled as block devices (class = 'blk').
Best regards
Heinrich
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
disk/part.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/disk/part.c b/disk/part.c index a6a8f7052bd3..b330103a5bc0 100644 --- a/disk/part.c +++ b/disk/part.c @@ -427,7 +427,8 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, * Always should be done, otherwise hw partition 0 will return stale * data after displaying a non-zero hw partition. */
part_init(*dev_desc);
if ((*dev_desc)->if_type == IF_TYPE_MMC)
part_init(*dev_desc);
#endif
cleanup:
-- 2.33.0

Hi Heinrich,
On Mon, 11 Oct 2021 at 04:07, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/1/21 13:48, Peter Robinson wrote:
On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
An NVMe device may expose multiple namespaces. blk_create_devicef() is called for each namespace.
A SCSI device may have multiple LUNs. blk_create_devicef() is called for each LUN.
This is what the tree shown by 'dm tree' with on NVMe namespace and one LUN.
Class Index Driver Name
root 0 root_driver root_driver simple_bus 0 simple_bus |- soc spi 1 sifive_spi | |- spi@10050000 mmc 0 mmc_spi | | `- mmc@0 blk 0 mmc_blk | | `- mmc@0.blk pci 0 pcie_sifive | |- pcie@e00000000 pci 1 pci_bridge_drv | | `- pci_0:0.0 pci 2 pci_bridge_drv | | `- pci_1:0.0 pci 5 pci_bridge_drv | | |- pci_2:3.0 ahci 0 ahci_pci | | | `- ahci_pci scsi 0 ahci_scsi | | | `- ahci_scsi blk 2 scsi_blk | | | `- ahci_scsi.id0lun0 pci 6 pci_bridge_drv | | |- pci_2:4.0 nvme 0 nvme | | | `- nvme#0 blk 1 nvme-blk | | | `- nvme#0.blk#1
Namespaces and LUNs are modeled as block devices (class = 'blk').
So multiple block devices per NVMe device? I did not know that was supported.
We need a sandbox driver for NVMe as it has no tests at present. Since it has no tests, I don't think we can expect people to know how to maintain whatever functionality is there.
[..]
Regards, Simon

On 10/11/21 16:32, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 04:07, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/1/21 13:48, Peter Robinson wrote:
On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
An NVMe device may expose multiple namespaces. blk_create_devicef() is called for each namespace.
A SCSI device may have multiple LUNs. blk_create_devicef() is called for each LUN.
This is what the tree shown by 'dm tree' with on NVMe namespace and one LUN.
Class Index Driver Name
root 0 root_driver root_driver simple_bus 0 simple_bus |- soc spi 1 sifive_spi | |- spi@10050000 mmc 0 mmc_spi | | `- mmc@0 blk 0 mmc_blk | | `- mmc@0.blk pci 0 pcie_sifive | |- pcie@e00000000 pci 1 pci_bridge_drv | | `- pci_0:0.0 pci 2 pci_bridge_drv | | `- pci_1:0.0 pci 5 pci_bridge_drv | | |- pci_2:3.0 ahci 0 ahci_pci | | | `- ahci_pci scsi 0 ahci_scsi | | | `- ahci_scsi blk 2 scsi_blk | | | `- ahci_scsi.id0lun0 pci 6 pci_bridge_drv | | |- pci_2:4.0 nvme 0 nvme | | | `- nvme#0 blk 1 nvme-blk | | | `- nvme#0.blk#1
Namespaces and LUNs are modeled as block devices (class = 'blk').
So multiple block devices per NVMe device? I did not know that was supported.
We need a sandbox driver for NVMe as it has no tests at present. Since it has no tests, I don't think we can expect people to know how to maintain whatever functionality is there.
NVMe drives with multiple namespaces exist for servers but not for consumer NVMe drives.
In QEMU you can define an NVMe device with multiple namespaces. Cf. https://qemu.readthedocs.io/en/latest/system/devices/nvme.html?highlight=nam...
So for a first glimpse at the handling I suggest to use QEMU.
Best regards
Heinrich

Hi Heinrich,
On Mon, 11 Oct 2021 at 09:09, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:32, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 04:07, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/1/21 13:48, Peter Robinson wrote:
On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
An NVMe device may expose multiple namespaces. blk_create_devicef() is called for each namespace.
A SCSI device may have multiple LUNs. blk_create_devicef() is called for each LUN.
This is what the tree shown by 'dm tree' with on NVMe namespace and one LUN.
Class Index Driver Name
root 0 root_driver root_driver simple_bus 0 simple_bus |- soc spi 1 sifive_spi | |- spi@10050000 mmc 0 mmc_spi | | `- mmc@0 blk 0 mmc_blk | | `- mmc@0.blk pci 0 pcie_sifive | |- pcie@e00000000 pci 1 pci_bridge_drv | | `- pci_0:0.0 pci 2 pci_bridge_drv | | `- pci_1:0.0 pci 5 pci_bridge_drv | | |- pci_2:3.0 ahci 0 ahci_pci | | | `- ahci_pci scsi 0 ahci_scsi | | | `- ahci_scsi blk 2 scsi_blk | | | `- ahci_scsi.id0lun0 pci 6 pci_bridge_drv | | |- pci_2:4.0 nvme 0 nvme | | | `- nvme#0 blk 1 nvme-blk | | | `- nvme#0.blk#1
Namespaces and LUNs are modeled as block devices (class = 'blk').
So multiple block devices per NVMe device? I did not know that was supported.
We need a sandbox driver for NVMe as it has no tests at present. Since it has no tests, I don't think we can expect people to know how to maintain whatever functionality is there.
NVMe drives with multiple namespaces exist for servers but not for consumer NVMe drives.
In QEMU you can define an NVMe device with multiple namespaces. Cf. https://qemu.readthedocs.io/en/latest/system/devices/nvme.html?highlight=nam...
So for a first glimpse at the handling I suggest to use QEMU.
Well that's fine, but every uclass must have a test and a sandbox emulator as well.
Regards, Simon

Simon, Heinrich,
On Mon, Oct 11, 2021 at 10:14:02AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:09, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:32, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 04:07, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/1/21 13:48, Peter Robinson wrote:
On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
An NVMe device may expose multiple namespaces. blk_create_devicef() is called for each namespace.
A SCSI device may have multiple LUNs. blk_create_devicef() is called for each LUN.
This is what the tree shown by 'dm tree' with on NVMe namespace and one LUN.
Class Index Driver Name
root 0 root_driver root_driver simple_bus 0 simple_bus |- soc spi 1 sifive_spi | |- spi@10050000 mmc 0 mmc_spi | | `- mmc@0 blk 0 mmc_blk | | `- mmc@0.blk pci 0 pcie_sifive | |- pcie@e00000000 pci 1 pci_bridge_drv | | `- pci_0:0.0 pci 2 pci_bridge_drv | | `- pci_1:0.0 pci 5 pci_bridge_drv | | |- pci_2:3.0 ahci 0 ahci_pci | | | `- ahci_pci scsi 0 ahci_scsi | | | `- ahci_scsi blk 2 scsi_blk | | | `- ahci_scsi.id0lun0 pci 6 pci_bridge_drv | | |- pci_2:4.0 nvme 0 nvme | | | `- nvme#0 blk 1 nvme-blk | | | `- nvme#0.blk#1
Namespaces and LUNs are modeled as block devices (class = 'blk').
So multiple block devices per NVMe device? I did not know that was supported.
We need a sandbox driver for NVMe as it has no tests at present. Since it has no tests, I don't think we can expect people to know how to maintain whatever functionality is there.
NVMe drives with multiple namespaces exist for servers but not for consumer NVMe drives.
In QEMU you can define an NVMe device with multiple namespaces. Cf. https://qemu.readthedocs.io/en/latest/system/devices/nvme.html?highlight=nam...
So for a first glimpse at the handling I suggest to use QEMU.
Well that's fine, but every uclass must have a test and a sandbox emulator as well.
Wait, it seems that you're discussing a different thing from my patch.
While I don't know whether NVMe namespaces are a kind of "HW partitions", we don't care much here as long as any namespace can be handled simply as a normal block device, like scsi LUN's, in terms of U-Boot driver model.
# On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). # See do_mmcrpmb() in cmd/mmc.c
So I hope that *your* discussion doesn't make any difference to my patch. Right?
-Takahiro Akashi
Regards, Simon

On 10/12/21 05:26, AKASHI Takahiro wrote:
Simon, Heinrich,
On Mon, Oct 11, 2021 at 10:14:02AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:09, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:32, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 04:07, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/1/21 13:48, Peter Robinson wrote:
On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > In blk_get_device_by_str(), the comment says: "Updates the partition table > for the specified hw partition." > Since hw partition is supported only on MMC, it makes no sense to do so > for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
An NVMe device may expose multiple namespaces. blk_create_devicef() is called for each namespace.
A SCSI device may have multiple LUNs. blk_create_devicef() is called for each LUN.
This is what the tree shown by 'dm tree' with on NVMe namespace and one LUN.
Class Index Driver Name
root 0 root_driver root_driver simple_bus 0 simple_bus |- soc spi 1 sifive_spi | |- spi@10050000 mmc 0 mmc_spi | | `- mmc@0 blk 0 mmc_blk | | `- mmc@0.blk pci 0 pcie_sifive | |- pcie@e00000000 pci 1 pci_bridge_drv | | `- pci_0:0.0 pci 2 pci_bridge_drv | | `- pci_1:0.0 pci 5 pci_bridge_drv | | |- pci_2:3.0 ahci 0 ahci_pci | | | `- ahci_pci scsi 0 ahci_scsi | | | `- ahci_scsi blk 2 scsi_blk | | | `- ahci_scsi.id0lun0 pci 6 pci_bridge_drv | | |- pci_2:4.0 nvme 0 nvme | | | `- nvme#0 blk 1 nvme-blk | | | `- nvme#0.blk#1
Namespaces and LUNs are modeled as block devices (class = 'blk').
So multiple block devices per NVMe device? I did not know that was supported.
We need a sandbox driver for NVMe as it has no tests at present. Since it has no tests, I don't think we can expect people to know how to maintain whatever functionality is there.
NVMe drives with multiple namespaces exist for servers but not for consumer NVMe drives.
In QEMU you can define an NVMe device with multiple namespaces. Cf. https://qemu.readthedocs.io/en/latest/system/devices/nvme.html?highlight=nam...
So for a first glimpse at the handling I suggest to use QEMU.
Well that's fine, but every uclass must have a test and a sandbox emulator as well.
Wait, it seems that you're discussing a different thing from my patch.
While I don't know whether NVMe namespaces are a kind of "HW partitions", we don't care much here as long as any namespace can be handled simply as a normal block device, like scsi LUN's, in terms of U-Boot driver model.
# On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). # See do_mmcrpmb() in cmd/mmc.c
Each hardware partition should be a block device (class blk) which is mirrored in the UEFI world by a CTRL() device. It is not necessary for parent device to be a block device.
Best regards
Heinrich
So I hope that *your* discussion doesn't make any difference to my patch. Right?
-Takahiro Akashi
Regards, Simon

On Tue, Oct 12, 2021 at 03:30:26PM +0200, Heinrich Schuchardt wrote:
On 10/12/21 05:26, AKASHI Takahiro wrote:
Simon, Heinrich,
On Mon, Oct 11, 2021 at 10:14:02AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:09, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:32, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 04:07, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/1/21 13:48, Peter Robinson wrote: > On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro > takahiro.akashi@linaro.org wrote: > > > > In blk_get_device_by_str(), the comment says: "Updates the partition table > > for the specified hw partition." > > Since hw partition is supported only on MMC, it makes no sense to do so > > for other devices. > > Is it not also supported on UFS, and I believe it may also be an > option in the NVME spec too.
An NVMe device may expose multiple namespaces. blk_create_devicef() is called for each namespace.
A SCSI device may have multiple LUNs. blk_create_devicef() is called for each LUN.
This is what the tree shown by 'dm tree' with on NVMe namespace and one LUN.
Class Index Driver Name
root 0 root_driver root_driver simple_bus 0 simple_bus |- soc spi 1 sifive_spi | |- spi@10050000 mmc 0 mmc_spi | | `- mmc@0 blk 0 mmc_blk | | `- mmc@0.blk pci 0 pcie_sifive | |- pcie@e00000000 pci 1 pci_bridge_drv | | `- pci_0:0.0 pci 2 pci_bridge_drv | | `- pci_1:0.0 pci 5 pci_bridge_drv | | |- pci_2:3.0 ahci 0 ahci_pci | | | `- ahci_pci scsi 0 ahci_scsi | | | `- ahci_scsi blk 2 scsi_blk | | | `- ahci_scsi.id0lun0 pci 6 pci_bridge_drv | | |- pci_2:4.0 nvme 0 nvme | | | `- nvme#0 blk 1 nvme-blk | | | `- nvme#0.blk#1
Namespaces and LUNs are modeled as block devices (class = 'blk').
So multiple block devices per NVMe device? I did not know that was supported.
We need a sandbox driver for NVMe as it has no tests at present. Since it has no tests, I don't think we can expect people to know how to maintain whatever functionality is there.
NVMe drives with multiple namespaces exist for servers but not for consumer NVMe drives.
In QEMU you can define an NVMe device with multiple namespaces. Cf. https://qemu.readthedocs.io/en/latest/system/devices/nvme.html?highlight=nam...
So for a first glimpse at the handling I suggest to use QEMU.
Well that's fine, but every uclass must have a test and a sandbox emulator as well.
Wait, it seems that you're discussing a different thing from my patch.
While I don't know whether NVMe namespaces are a kind of "HW partitions", we don't care much here as long as any namespace can be handled simply as a normal block device, like scsi LUN's, in terms of U-Boot driver model.
# On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). # See do_mmcrpmb() in cmd/mmc.c
Each hardware partition should be a block device (class blk) which is mirrored in the UEFI world by a CTRL() device.
Yes, whether it is mirrored or not, a hw partition is to be a separate udevice from its associated raw device.
It is not necessary for parent device to be a block device.
I'm not sure what 'parent device' means here, but I guess that it is the raw MMC device (as a controller handle in UEFI terminology which is set to provide BLOCK_IO_PROTOCOL), isn't it?
-Takahiro Akashi
Best regards
Heinrich
So I hope that *your* discussion doesn't make any difference to my patch. Right?
-Takahiro Akashi
Regards, Simon

Hi Takahiro,
On Mon, 11 Oct 2021 at 21:26, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon, Heinrich,
On Mon, Oct 11, 2021 at 10:14:02AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:09, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:32, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 04:07, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/1/21 13:48, Peter Robinson wrote:
On Fri, Oct 1, 2021 at 6:03 AM AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > In blk_get_device_by_str(), the comment says: "Updates the partition table > for the specified hw partition." > Since hw partition is supported only on MMC, it makes no sense to do so > for other devices.
Is it not also supported on UFS, and I believe it may also be an option in the NVME spec too.
An NVMe device may expose multiple namespaces. blk_create_devicef() is called for each namespace.
A SCSI device may have multiple LUNs. blk_create_devicef() is called for each LUN.
This is what the tree shown by 'dm tree' with on NVMe namespace and one LUN.
Class Index Driver Name
root 0 root_driver root_driver simple_bus 0 simple_bus |- soc spi 1 sifive_spi | |- spi@10050000 mmc 0 mmc_spi | | `- mmc@0 blk 0 mmc_blk | | `- mmc@0.blk pci 0 pcie_sifive | |- pcie@e00000000 pci 1 pci_bridge_drv | | `- pci_0:0.0 pci 2 pci_bridge_drv | | `- pci_1:0.0 pci 5 pci_bridge_drv | | |- pci_2:3.0 ahci 0 ahci_pci | | | `- ahci_pci scsi 0 ahci_scsi | | | `- ahci_scsi blk 2 scsi_blk | | | `- ahci_scsi.id0lun0 pci 6 pci_bridge_drv | | |- pci_2:4.0 nvme 0 nvme | | | `- nvme#0 blk 1 nvme-blk | | | `- nvme#0.blk#1
Namespaces and LUNs are modeled as block devices (class = 'blk').
So multiple block devices per NVMe device? I did not know that was supported.
We need a sandbox driver for NVMe as it has no tests at present. Since it has no tests, I don't think we can expect people to know how to maintain whatever functionality is there.
NVMe drives with multiple namespaces exist for servers but not for consumer NVMe drives.
In QEMU you can define an NVMe device with multiple namespaces. Cf. https://qemu.readthedocs.io/en/latest/system/devices/nvme.html?highlight=nam...
So for a first glimpse at the handling I suggest to use QEMU.
Well that's fine, but every uclass must have a test and a sandbox emulator as well.
Wait, it seems that you're discussing a different thing from my patch.
While I don't know whether NVMe namespaces are a kind of "HW partitions", we don't care much here as long as any namespace can be handled simply as a normal block device, like scsi LUN's, in terms of U-Boot driver model.
# On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). # See do_mmcrpmb() in cmd/mmc.c
So I hope that *your* discussion doesn't make any difference to my patch. Right?
From my POV the patch is fine, which is why I added the review tag.
We should continue the discussion on BLK versus PARTITION.
Regards, Simon

On Thu, 30 Sept 2021 at 23:02, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In blk_get_device_by_str(), the comment says: "Updates the partition table for the specified hw partition." Since hw partition is supported only on MMC, it makes no sense to do so for other devices.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
disk/part.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

Every time a scsi bus/port is scanned and a new block device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/scsi/scsi.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index d93d24192853..4865b5a86fd5 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -595,6 +595,16 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose) ata_swap_buf_le16((u16 *)&bdesc->revision, sizeof(bd.revision) / 2); }
+ ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + /* TODO: undo create */ + + ret = device_unbind(bdev); + + return ret; + } + if (verbose) { printf(" Device %d: ", bdesc->devnum); dev_print(bdesc);

On Thu, 30 Sept 2021 at 23:02, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time a scsi bus/port is scanned and a new block device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/scsi/scsi.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Every time a scsi bus/port is scanned and a new block device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/scsi/scsi.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index d93d24192853..4865b5a86fd5 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -595,6 +595,16 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose) ata_swap_buf_le16((u16 *)&bdesc->revision, sizeof(bd.revision) / 2); }
+ ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + /* TODO: undo create */ + + ret = device_unbind(bdev); + + return ret; + } + if (verbose) { printf(" Device %d: ", bdesc->devnum); dev_print(bdesc);

Every time a usb bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- common/usb_storage.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/common/usb_storage.c b/common/usb_storage.c index 946c6b2b323a..5f294f17491f 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -239,6 +239,12 @@ static int usb_stor_probe_device(struct usb_device *udev) if (ret) return ret; } + + ret = device_probe(dev); + if (ret) { + device_unbind(dev); + return ret; + } } #else /* We don't have space to even probe if we hit the maximum */

Every time a mmc bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/mmc/mmc-uclass.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 3ee92d03ca23..07b5c1736439 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -418,6 +418,13 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) bdesc->part_type = cfg->part_type; mmc->dev = dev; mmc->user_speed_mode = MMC_MODES_END; + + ret = device_probe(dev); + if (ret) { + device_unbind(dev); + return ret; + } + return 0; }

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time a mmc bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/mmc/mmc-uclass.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 3ee92d03ca23..07b5c1736439 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -418,6 +418,13 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) bdesc->part_type = cfg->part_type; mmc->dev = dev; mmc->user_speed_mode = MMC_MODES_END;
ret = device_probe(dev);
if (ret) {
device_unbind(dev);
return ret;
}
We cannot probe a device within a bind() method. Can this be moved to mmc_blk_probe(), perhaps?
Regards, Simon

On Sun, Oct 10, 2021 at 08:14:09AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time a mmc bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/mmc/mmc-uclass.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 3ee92d03ca23..07b5c1736439 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -418,6 +418,13 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) bdesc->part_type = cfg->part_type; mmc->dev = dev; mmc->user_speed_mode = MMC_MODES_END;
ret = device_probe(dev);
if (ret) {
device_unbind(dev);
return ret;
}
We cannot probe a device within a bind() method. Can this be moved to mmc_blk_probe(), perhaps?
Ok, I will fix it.
Thanks, -Takahiro Akashi
Regards, Simon

Every time a usb bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- common/usb_storage.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/common/usb_storage.c b/common/usb_storage.c index 946c6b2b323a..5f294f17491f 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -239,6 +239,12 @@ static int usb_stor_probe_device(struct usb_device *udev) if (ret) return ret; } + + ret = device_probe(dev); + if (ret) { + device_unbind(dev); + return ret; + } } #else /* We don't have space to even probe if we hit the maximum */

On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time a usb bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
common/usb_storage.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Every time a mmc bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/mmc/mmc-uclass.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 3ee92d03ca23..07b5c1736439 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -418,6 +418,13 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) bdesc->part_type = cfg->part_type; mmc->dev = dev; mmc->user_speed_mode = MMC_MODES_END; + + ret = device_probe(dev); + if (ret) { + device_unbind(dev); + return ret; + } + return 0; }

Every time a nvme bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/nvme/nvme.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index f6465ea7f482..975bbc6dc3b7 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -909,6 +909,12 @@ static int nvme_probe(struct udevice *udev) -1, 512, 0, &ns_udev); if (ret) goto free_id; + + ret = device_probe(ns_udev); + if (ret) { + device_unbind(ns_udev); + goto free_id; + } }
free(id);

Every time a nvme bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/nvme/nvme.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index f6465ea7f482..975bbc6dc3b7 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -909,6 +909,12 @@ static int nvme_probe(struct udevice *udev) -1, 512, 0, &ns_udev); if (ret) goto free_id; + + ret = device_probe(ns_udev); + if (ret) { + device_unbind(ns_udev); + goto free_id; + } }
free(id);

On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time a nvme bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/nvme/nvme.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Every time a sata bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/ata/dwc_ahsata.c | 10 ++++++++++ drivers/ata/fsl_sata.c | 11 +++++++++++ drivers/ata/sata_mv.c | 9 +++++++++ drivers/ata/sata_sil.c | 12 ++++++++++++ 4 files changed, 42 insertions(+)
diff --git a/drivers/ata/dwc_ahsata.c b/drivers/ata/dwc_ahsata.c index 6d42548087b3..6a51c70d1170 100644 --- a/drivers/ata/dwc_ahsata.c +++ b/drivers/ata/dwc_ahsata.c @@ -1026,6 +1026,16 @@ int dwc_ahsata_scan(struct udevice *dev) return ret; }
+ ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + /* TODO: undo create */ + + device_unbind(bdev); + + return ret; + } + return 0; }
diff --git a/drivers/ata/fsl_sata.c b/drivers/ata/fsl_sata.c index e44db0a37458..346e9298b4c5 100644 --- a/drivers/ata/fsl_sata.c +++ b/drivers/ata/fsl_sata.c @@ -982,6 +982,17 @@ static int fsl_ata_probe(struct udevice *dev) failed_number++; continue; } + + ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + ret = fsl_unbind_device(blk); + if (ret) + return ret; + + failed_number++; + continue; + } }
if (failed_number == nr_ports) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 003222d47be6..09b735779ebf 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1099,6 +1099,15 @@ static int sata_mv_probe(struct udevice *dev) continue; }
+ ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + /* TODO: undo create */ + + device_unbind(bdev); + continue; + } + /* If we got here, the current SATA port was probed * successfully, so set the probe status to successful. */ diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index dda712f42cb2..295f7ca72303 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -864,6 +864,18 @@ static int sil_pci_probe(struct udevice *dev) failed_number++; continue; } + + ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + ret = sil_unbind_device(blk); + device_unbind(bdev); + if (ret) + return ret; + + failed_number++; + continue; + } }
if (failed_number == sata_info.maxport)

Every time an ide bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/ide.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/block/ide.c b/drivers/block/ide.c index c99076c6f45d..31aaed09ab70 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -1151,6 +1151,12 @@ static int ide_probe(struct udevice *udev) blksz, size, &blk_dev); if (ret) return ret; + + ret = device_probe(blk_dev); + if (ret) { + device_unbind(blk_dev); + return ret; + } } }

Every time a sata bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/ata/dwc_ahsata.c | 10 ++++++++++ drivers/ata/fsl_sata.c | 11 +++++++++++ drivers/ata/sata_mv.c | 9 +++++++++ drivers/ata/sata_sil.c | 12 ++++++++++++ 4 files changed, 42 insertions(+)
diff --git a/drivers/ata/dwc_ahsata.c b/drivers/ata/dwc_ahsata.c index 6d42548087b3..6a51c70d1170 100644 --- a/drivers/ata/dwc_ahsata.c +++ b/drivers/ata/dwc_ahsata.c @@ -1026,6 +1026,16 @@ int dwc_ahsata_scan(struct udevice *dev) return ret; }
+ ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + /* TODO: undo create */ + + device_unbind(bdev); + + return ret; + } + return 0; }
diff --git a/drivers/ata/fsl_sata.c b/drivers/ata/fsl_sata.c index e44db0a37458..346e9298b4c5 100644 --- a/drivers/ata/fsl_sata.c +++ b/drivers/ata/fsl_sata.c @@ -982,6 +982,17 @@ static int fsl_ata_probe(struct udevice *dev) failed_number++; continue; } + + ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + ret = fsl_unbind_device(blk); + if (ret) + return ret; + + failed_number++; + continue; + } }
if (failed_number == nr_ports) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 003222d47be6..09b735779ebf 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1099,6 +1099,15 @@ static int sata_mv_probe(struct udevice *dev) continue; }
+ ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + /* TODO: undo create */ + + device_unbind(bdev); + continue; + } + /* If we got here, the current SATA port was probed * successfully, so set the probe status to successful. */ diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index dda712f42cb2..295f7ca72303 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -864,6 +864,18 @@ static int sil_pci_probe(struct udevice *dev) failed_number++; continue; } + + ret = device_probe(bdev); + if (ret < 0) { + debug("Can't probe\n"); + ret = sil_unbind_device(blk); + device_unbind(bdev); + if (ret) + return ret; + + failed_number++; + continue; + } }
if (failed_number == sata_info.maxport)

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time a sata bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/ata/dwc_ahsata.c | 10 ++++++++++ drivers/ata/fsl_sata.c | 11 +++++++++++ drivers/ata/sata_mv.c | 9 +++++++++ drivers/ata/sata_sil.c | 12 ++++++++++++ 4 files changed, 42 insertions(+)
diff --git a/drivers/ata/dwc_ahsata.c b/drivers/ata/dwc_ahsata.c index 6d42548087b3..6a51c70d1170 100644 --- a/drivers/ata/dwc_ahsata.c +++ b/drivers/ata/dwc_ahsata.c @@ -1026,6 +1026,16 @@ int dwc_ahsata_scan(struct udevice *dev) return ret; }
ret = device_probe(bdev);
if (ret < 0) {
debug("Can't probe\n");
/* TODO: undo create */
device_unbind(bdev);
It looks like this one has the wrong variable name.
[..]
Regards, Simon

On Sun, Oct 10, 2021 at 08:14:12AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time a sata bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/ata/dwc_ahsata.c | 10 ++++++++++ drivers/ata/fsl_sata.c | 11 +++++++++++ drivers/ata/sata_mv.c | 9 +++++++++ drivers/ata/sata_sil.c | 12 ++++++++++++ 4 files changed, 42 insertions(+)
diff --git a/drivers/ata/dwc_ahsata.c b/drivers/ata/dwc_ahsata.c index 6d42548087b3..6a51c70d1170 100644 --- a/drivers/ata/dwc_ahsata.c +++ b/drivers/ata/dwc_ahsata.c @@ -1026,6 +1026,16 @@ int dwc_ahsata_scan(struct udevice *dev) return ret; }
ret = device_probe(bdev);
if (ret < 0) {
debug("Can't probe\n");
/* TODO: undo create */
device_unbind(bdev);
It looks like this one has the wrong variable name.
Ah, it was a copy-and-paste thing :) I will fix it.
Thanks, -Takahiro Akashi
[..]
Regards, Simon

Every time an ide bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/ide.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/block/ide.c b/drivers/block/ide.c index c99076c6f45d..31aaed09ab70 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -1151,6 +1151,12 @@ static int ide_probe(struct udevice *udev) blksz, size, &blk_dev); if (ret) return ret; + + ret = device_probe(blk_dev); + if (ret) { + device_unbind(blk_dev); + return ret; + } } }

On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time an ide bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/ide.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
I'm starting to wonder if you can create a function that does the probe and unbind? Something in the blk interface, perhaps? It would reduce the duplicated code and provide a standard way of bringing up a new device.
Perhaps blk_device_complete() ?
Regards, Simon

On Sun, Oct 10, 2021 at 08:14:13AM -0600, Simon Glass wrote:
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time an ide bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/ide.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
I'm starting to wonder if you can create a function that does the probe and unbind? Something in the blk interface, perhaps? It would reduce the duplicated code and provide a standard way of bringing up a new device.
That is exactly what Ilias suggested but I'm a bit declined to do :)
Common 'scanning' code looks like: blk_create_devicef(... , &dev); desc = dev_get_uclass_data(dev); initialize some members in desc as well as device-specific info --- (A) (now dev can be accessible.) ret = device_probe(dev); if (ret) { de-initialize *dev* --- (B) device_unbind() }
Basically (B) is supposed to undo (A) which may or may not exist, depending on types of block devices.
So I'm not 100% sure that a combination of device_probe() and device_unbind() will fit to all the device types. (The only cases that I have noticed are fsl_sata.c and sata_sil.c. Both have their own xxx_unbind_device(), but they simply call device_remove() and device_unbind(), though. So no worry?)
-Takahiro Akashi
Perhaps blk_device_complete() ?
Regards, Simon

Hi Takahiro,
On Sun, 10 Oct 2021 at 19:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 10, 2021 at 08:14:13AM -0600, Simon Glass wrote:
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time an ide bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/ide.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
I'm starting to wonder if you can create a function that does the probe and unbind? Something in the blk interface, perhaps? It would reduce the duplicated code and provide a standard way of bringing up a new device.
That is exactly what Ilias suggested but I'm a bit declined to do :)
Common 'scanning' code looks like: blk_create_devicef(... , &dev); desc = dev_get_uclass_data(dev); initialize some members in desc as well as device-specific info --- (A) (now dev can be accessible.) ret = device_probe(dev); if (ret) { de-initialize *dev* --- (B) device_unbind() }
Basically (B) is supposed to undo (A) which may or may not exist, depending on types of block devices.
So I'm not 100% sure that a combination of device_probe() and device_unbind() will fit to all the device types. (The only cases that I have noticed are fsl_sata.c and sata_sil.c. Both have their own xxx_unbind_device(), but they simply call device_remove() and device_unbind(), though. So no worry?)
Yes I agree it would be a very strange function. But at least it would have the benefit of grouping the code together under a particular name, something like blk_back_out_bind(), but that's not a good name....it just feels like this might get refactored in the future and having the code in one place might be handy.
Regards, Simon

On Mon, Oct 11, 2021 at 08:54:13AM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 19:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 10, 2021 at 08:14:13AM -0600, Simon Glass wrote:
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time an ide bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/ide.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
I'm starting to wonder if you can create a function that does the probe and unbind? Something in the blk interface, perhaps? It would reduce the duplicated code and provide a standard way of bringing up a new device.
That is exactly what Ilias suggested but I'm a bit declined to do :)
Common 'scanning' code looks like: blk_create_devicef(... , &dev); desc = dev_get_uclass_data(dev); initialize some members in desc as well as device-specific info --- (A) (now dev can be accessible.) ret = device_probe(dev); if (ret) { de-initialize *dev* --- (B) device_unbind() }
Basically (B) is supposed to undo (A) which may or may not exist, depending on types of block devices.
So I'm not 100% sure that a combination of device_probe() and device_unbind() will fit to all the device types. (The only cases that I have noticed are fsl_sata.c and sata_sil.c. Both have their own xxx_unbind_device(), but they simply call device_remove() and device_unbind(), though. So no worry?)
Yes I agree it would be a very strange function. But at least it would have the benefit of grouping the code together under a particular name, something like blk_back_out_bind(), but that's not a good name....it just feels like this might get refactored in the future and having the code in one place might be handy.
naming is hard! try_device_probe() maybe?
Cheers /Ilias
Regards, Simon

On Tue, Oct 12, 2021 at 08:53:54AM +0300, Ilias Apalodimas wrote:
On Mon, Oct 11, 2021 at 08:54:13AM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 19:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 10, 2021 at 08:14:13AM -0600, Simon Glass wrote:
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Every time an ide bus/port is scanned and a new device is detected, we want to call device_probe() as it will give us a chance to run additional post-processings for some purposes.
In particular, support for creating partitions on a device will be added.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/ide.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
I'm starting to wonder if you can create a function that does the probe and unbind? Something in the blk interface, perhaps? It would reduce the duplicated code and provide a standard way of bringing up a new device.
That is exactly what Ilias suggested but I'm a bit declined to do :)
Common 'scanning' code looks like: blk_create_devicef(... , &dev); desc = dev_get_uclass_data(dev); initialize some members in desc as well as device-specific info --- (A) (now dev can be accessible.) ret = device_probe(dev); if (ret) { de-initialize *dev* --- (B) device_unbind() }
Basically (B) is supposed to undo (A) which may or may not exist, depending on types of block devices.
So I'm not 100% sure that a combination of device_probe() and device_unbind() will fit to all the device types. (The only cases that I have noticed are fsl_sata.c and sata_sil.c. Both have their own xxx_unbind_device(), but they simply call device_remove() and device_unbind(), though. So no worry?)
Yes I agree it would be a very strange function. But at least it would have the benefit of grouping the code together under a particular name, something like blk_back_out_bind(), but that's not a good name....it just feels like this might get refactored in the future and having the code in one place might be handy.
naming is hard! try_device_probe() maybe?
Indeed. A name should come later. So I will temporarily use blk_probe_or_unbind() :-)
-Takahiro Akashi
Cheers /Ilias
Regards, Simon

UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{ + int part, count; + struct blk_desc *desc = dev_get_uclass_plat(parent); + struct disk_partition info; + struct disk_part *part_data; + char devname[32]; + struct udevice *dev; + int ret; + + if (!CONFIG_IS_ENABLED(PARTITIONS) || + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) + return 0; + + /* Add devices for each partition */ + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { + if (part_get_info(desc, part, &info)) + continue; + snprintf(devname, sizeof(devname), "%s:%d", parent->name, + part); + + ret = device_bind_driver(parent, "blk_partition", + strdup(devname), &dev); + if (ret) + return ret; + + part_data = dev_get_uclass_plat(dev); + part_data->partnum = part; + part_data->gpt_part_info = info; + count++; + + device_probe(dev); + } + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); + + return 0; +} + static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) && @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), }; + +static ulong blk_part_read(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct udevice *parent; + struct disk_part *part; + const struct blk_ops *ops; + + parent = dev_get_parent(dev); + ops = blk_get_ops(parent); + if (!ops->read) + return -ENOSYS; + + part = dev_get_uclass_plat(dev); + start += part->gpt_part_info.start; + + return ops->read(parent, start, blkcnt, buffer); +} + +static ulong blk_part_write(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + struct udevice *parent; + struct disk_part *part; + const struct blk_ops *ops; + + parent = dev_get_parent(dev); + ops = blk_get_ops(parent); + if (!ops->write) + return -ENOSYS; + + part = dev_get_uclass_plat(dev); + start += part->gpt_part_info.start; + + return ops->write(parent, start, blkcnt, buffer); +} + +static ulong blk_part_erase(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt) +{ + struct udevice *parent; + struct disk_part *part; + const struct blk_ops *ops; + + parent = dev_get_parent(dev); + ops = blk_get_ops(parent); + if (!ops->erase) + return -ENOSYS; + + part = dev_get_uclass_plat(dev); + start += part->gpt_part_info.start; + + return ops->erase(parent, start, blkcnt); +} + +static const struct blk_ops blk_part_ops = { + .read = blk_part_read, + .write = blk_part_write, + .erase = blk_part_erase, +}; + +U_BOOT_DRIVER(blk_partition) = { + .name = "blk_partition", + .id = UCLASS_PARTITION, + .ops = &blk_part_ops, +}; + +UCLASS_DRIVER(partition) = { + .id = UCLASS_PARTITION, + .per_device_plat_auto = sizeof(struct disk_part), + .name = "partition", +}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/** + * blk_create_partitions - Create block devices for disk partitions + * + * Create UCLASS_PARTITION udevices for each of disk partitions in @parent + * + * @parent: Whole disk device + */ +int blk_create_partitions(struct udevice *parent); + /** * blk_unbind_all() - Unbind all device of the given interface type * diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */ + UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */

On 10/1/21 07:01, AKASHI Takahiro wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{
- int part, count;
- struct blk_desc *desc = dev_get_uclass_plat(parent);
- struct disk_partition info;
- struct disk_part *part_data;
- char devname[32];
- struct udevice *dev;
- int ret;
- if (!CONFIG_IS_ENABLED(PARTITIONS) ||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
return 0;
- /* Add devices for each partition */
- for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", parent->name,
part);
ret = device_bind_driver(parent, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
device_probe(dev);
- }
- debug("%s: %d partitions found in %s\n", __func__, count, parent->name);
- return 0;
+}
- static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) &&
@@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), };
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
What device type will the parent have if it is a eMMC hardware partition?
- ops = blk_get_ops(parent);
- if (!ops->read)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
You should check that we do not access the block device past the partition end:
struct blk_desc *desc = dev_get_uclass_plat(parent); if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) return -EFAULT.
- start += part->gpt_part_info.start;
- return ops->read(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->write)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
- return ops->write(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->erase)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
Best regards
Heinrich
- return ops->erase(parent, start, blkcnt);
+}
+static const struct blk_ops blk_part_ops = {
- .read = blk_part_read,
- .write = blk_part_write,
- .erase = blk_part_erase,
+};
+U_BOOT_DRIVER(blk_partition) = {
- .name = "blk_partition",
- .id = UCLASS_PARTITION,
- .ops = &blk_part_ops,
+};
+UCLASS_DRIVER(partition) = {
- .id = UCLASS_PARTITION,
- .per_device_plat_auto = sizeof(struct disk_part),
- .name = "partition",
+}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/**
- blk_create_partitions - Create block devices for disk partitions
- Create UCLASS_PARTITION udevices for each of disk partitions in @parent
- @parent: Whole disk device
- */
+int blk_create_partitions(struct udevice *parent);
- /**
- blk_unbind_all() - Unbind all device of the given interface type
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
- UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */

On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote:
On 10/1/21 07:01, AKASHI Takahiro wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{
- int part, count;
- struct blk_desc *desc = dev_get_uclass_plat(parent);
- struct disk_partition info;
- struct disk_part *part_data;
- char devname[32];
- struct udevice *dev;
- int ret;
- if (!CONFIG_IS_ENABLED(PARTITIONS) ||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
return 0;
- /* Add devices for each partition */
- for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", parent->name,
part);
ret = device_bind_driver(parent, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
device_probe(dev);
- }
- debug("%s: %d partitions found in %s\n", __func__, count, parent->name);
- return 0;
+}
- static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) &&
@@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), };
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
What device type will the parent have if it is a eMMC hardware partition?
- ops = blk_get_ops(parent);
- if (!ops->read)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
You should check that we do not access the block device past the partition end:
Yes, I will fix all of checks.
-Takahiro Akashi
struct blk_desc *desc = dev_get_uclass_plat(parent); if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) return -EFAULT.
- start += part->gpt_part_info.start;
- return ops->read(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->write)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
- return ops->write(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->erase)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
Best regards
Heinrich
- return ops->erase(parent, start, blkcnt);
+}
+static const struct blk_ops blk_part_ops = {
- .read = blk_part_read,
- .write = blk_part_write,
- .erase = blk_part_erase,
+};
+U_BOOT_DRIVER(blk_partition) = {
- .name = "blk_partition",
- .id = UCLASS_PARTITION,
- .ops = &blk_part_ops,
+};
+UCLASS_DRIVER(partition) = {
- .id = UCLASS_PARTITION,
- .per_device_plat_auto = sizeof(struct disk_part),
- .name = "partition",
+}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/**
- blk_create_partitions - Create block devices for disk partitions
- Create UCLASS_PARTITION udevices for each of disk partitions in @parent
- @parent: Whole disk device
- */
+int blk_create_partitions(struct udevice *parent);
- /**
- blk_unbind_all() - Unbind all device of the given interface type
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
- UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */

On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote:
On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote:
On 10/1/21 07:01, AKASHI Takahiro wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{
- int part, count;
- struct blk_desc *desc = dev_get_uclass_plat(parent);
- struct disk_partition info;
- struct disk_part *part_data;
- char devname[32];
- struct udevice *dev;
- int ret;
- if (!CONFIG_IS_ENABLED(PARTITIONS) ||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
return 0;
- /* Add devices for each partition */
- for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", parent->name,
part);
ret = device_bind_driver(parent, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
device_probe(dev);
- }
- debug("%s: %d partitions found in %s\n", __func__, count, parent->name);
- return 0;
+}
- static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) &&
@@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), };
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
What device type will the parent have if it is a eMMC hardware partition?
- ops = blk_get_ops(parent);
- if (!ops->read)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
You should check that we do not access the block device past the partition end:
Yes, I will fix all of checks.
struct blk_desc *desc = dev_get_uclass_plat(parent); if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) return -EFAULT.
- start += part->gpt_part_info.start;
A better solution is: if (start >= part->gpt_part_info.size) return 0;
if ((start + blkcnt) > part->gpt_part_info.size) blkcnt = part->gpt_part_info.size - start; start += part->gpt_part_info.start; instead of returning -EFAULT. (note that start and blkcnt are in "block".)
-Takahiro Akashi
- return ops->read(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->write)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
- return ops->write(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->erase)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
Best regards
Heinrich
- return ops->erase(parent, start, blkcnt);
+}
+static const struct blk_ops blk_part_ops = {
- .read = blk_part_read,
- .write = blk_part_write,
- .erase = blk_part_erase,
+};
+U_BOOT_DRIVER(blk_partition) = {
- .name = "blk_partition",
- .id = UCLASS_PARTITION,
- .ops = &blk_part_ops,
+};
+UCLASS_DRIVER(partition) = {
- .id = UCLASS_PARTITION,
- .per_device_plat_auto = sizeof(struct disk_part),
- .name = "partition",
+}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/**
- blk_create_partitions - Create block devices for disk partitions
- Create UCLASS_PARTITION udevices for each of disk partitions in @parent
- @parent: Whole disk device
- */
+int blk_create_partitions(struct udevice *parent);
- /**
- blk_unbind_all() - Unbind all device of the given interface type
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
- UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */

On 10/8/21 02:51, AKASHI Takahiro wrote:
On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote:
On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote:
On 10/1/21 07:01, AKASHI Takahiro wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{
- int part, count;
- struct blk_desc *desc = dev_get_uclass_plat(parent);
- struct disk_partition info;
- struct disk_part *part_data;
- char devname[32];
- struct udevice *dev;
- int ret;
- if (!CONFIG_IS_ENABLED(PARTITIONS) ||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
return 0;
- /* Add devices for each partition */
- for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", parent->name,
part);
ret = device_bind_driver(parent, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
device_probe(dev);
- }
- debug("%s: %d partitions found in %s\n", __func__, count, parent->name);
- return 0;
+}
- static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) &&
@@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), };
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
What device type will the parent have if it is a eMMC hardware partition?
- ops = blk_get_ops(parent);
- if (!ops->read)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
You should check that we do not access the block device past the partition end:
Yes, I will fix all of checks.
struct blk_desc *desc = dev_get_uclass_plat(parent); if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) return -EFAULT.
- start += part->gpt_part_info.start;
A better solution is: if (start >= part->gpt_part_info.size) return 0;
if ((start + blkcnt) > part->gpt_part_info.size) blkcnt = part->gpt_part_info.size - start; start += part->gpt_part_info.start;
instead of returning -EFAULT. (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid. So we should return an error code here that can be translated into EFI_INVALID_PARAMETER.
Best regards
Heinrich
-Takahiro Akashi
- return ops->read(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->write)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
- return ops->write(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->erase)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
Best regards
Heinrich
- return ops->erase(parent, start, blkcnt);
+}
+static const struct blk_ops blk_part_ops = {
- .read = blk_part_read,
- .write = blk_part_write,
- .erase = blk_part_erase,
+};
+U_BOOT_DRIVER(blk_partition) = {
- .name = "blk_partition",
- .id = UCLASS_PARTITION,
- .ops = &blk_part_ops,
+};
+UCLASS_DRIVER(partition) = {
- .id = UCLASS_PARTITION,
- .per_device_plat_auto = sizeof(struct disk_part),
- .name = "partition",
+}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/**
- blk_create_partitions - Create block devices for disk partitions
- Create UCLASS_PARTITION udevices for each of disk partitions in @parent
- @parent: Whole disk device
- */
+int blk_create_partitions(struct udevice *parent);
- /**
- blk_unbind_all() - Unbind all device of the given interface type
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
- UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */

Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote:
On 10/8/21 02:51, AKASHI Takahiro wrote:
On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote:
On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote:
On 10/1/21 07:01, AKASHI Takahiro wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{
- int part, count;
- struct blk_desc *desc = dev_get_uclass_plat(parent);
- struct disk_partition info;
- struct disk_part *part_data;
- char devname[32];
- struct udevice *dev;
- int ret;
- if (!CONFIG_IS_ENABLED(PARTITIONS) ||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
return 0;
- /* Add devices for each partition */
- for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", parent->name,
part);
ret = device_bind_driver(parent, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
device_probe(dev);
- }
- debug("%s: %d partitions found in %s\n", __func__, count, parent->name);
- return 0;
+}
- static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) &&
@@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), };
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
What device type will the parent have if it is a eMMC hardware partition?
- ops = blk_get_ops(parent);
- if (!ops->read)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
You should check that we do not access the block device past the partition end:
Yes, I will fix all of checks.
struct blk_desc *desc = dev_get_uclass_plat(parent); if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) return -EFAULT.
- start += part->gpt_part_info.start;
A better solution is: if (start >= part->gpt_part_info.size) return 0;
if ((start + blkcnt) > part->gpt_part_info.size) blkcnt = part->gpt_part_info.size - start; start += part->gpt_part_info.start;
instead of returning -EFAULT. (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
-Takahiro Akashi
So we should return an error code here that can be translated into EFI_INVALID_PARAMETER.
Best regards
Heinrich
-Takahiro Akashi
- return ops->read(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->write)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
- return ops->write(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
- struct udevice *parent;
- struct disk_part *part;
- const struct blk_ops *ops;
- parent = dev_get_parent(dev);
- ops = blk_get_ops(parent);
- if (!ops->erase)
return -ENOSYS;
- part = dev_get_uclass_plat(dev);
- start += part->gpt_part_info.start;
here too
Best regards
Heinrich
- return ops->erase(parent, start, blkcnt);
+}
+static const struct blk_ops blk_part_ops = {
- .read = blk_part_read,
- .write = blk_part_write,
- .erase = blk_part_erase,
+};
+U_BOOT_DRIVER(blk_partition) = {
- .name = "blk_partition",
- .id = UCLASS_PARTITION,
- .ops = &blk_part_ops,
+};
+UCLASS_DRIVER(partition) = {
- .id = UCLASS_PARTITION,
- .per_device_plat_auto = sizeof(struct disk_part),
- .name = "partition",
+}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/**
- blk_create_partitions - Create block devices for disk partitions
- Create UCLASS_PARTITION udevices for each of disk partitions in @parent
- @parent: Whole disk device
- */
+int blk_create_partitions(struct udevice *parent);
- /**
- blk_unbind_all() - Unbind all device of the given interface type
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
- UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */

Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote:
On 10/8/21 02:51, AKASHI Takahiro wrote:
On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote:
On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote:
On 10/1/21 07:01, AKASHI Takahiro wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{
int part, count;
struct blk_desc *desc = dev_get_uclass_plat(parent);
struct disk_partition info;
struct disk_part *part_data;
char devname[32];
struct udevice *dev;
int ret;
if (!CONFIG_IS_ENABLED(PARTITIONS) ||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
return 0;
/* Add devices for each partition */
for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", parent->name,
part);
ret = device_bind_driver(parent, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
device_probe(dev);
}
debug("%s: %d partitions found in %s\n", __func__, count, parent->name);
return 0;
+}
- static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) &&
@@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), };
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
What device type will the parent have if it is a eMMC hardware partition?
ops = blk_get_ops(parent);
if (!ops->read)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
You should check that we do not access the block device past the partition end:
Yes, I will fix all of checks.
struct blk_desc *desc = dev_get_uclass_plat(parent); if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) return -EFAULT.
start += part->gpt_part_info.start;
A better solution is: if (start >= part->gpt_part_info.size) return 0;
if ((start + blkcnt) > part->gpt_part_info.size) blkcnt = part->gpt_part_info.size - start; start += part->gpt_part_info.start;
instead of returning -EFAULT. (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Regards, Simon

On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote:
On 10/8/21 02:51, AKASHI Takahiro wrote:
On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote:
On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote:
On 10/1/21 07:01, AKASHI Takahiro wrote: > UCLASS_PARTITION device will be created as a child node of > UCLASS_BLK device. > > Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org > --- > drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ > include/blk.h | 9 +++ > include/dm/uclass-id.h | 1 + > 3 files changed, 121 insertions(+) > > diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c > index 83682dcc181a..dd7f3c0fe31e 100644 > --- a/drivers/block/blk-uclass.c > +++ b/drivers/block/blk-uclass.c > @@ -12,6 +12,7 @@ > #include <log.h> > #include <malloc.h> > #include <part.h> > +#include <string.h> > #include <dm/device-internal.h> > #include <dm/lists.h> > #include <dm/uclass-internal.h> > @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) > return 0; > } > > +int blk_create_partitions(struct udevice *parent) > +{ > + int part, count; > + struct blk_desc *desc = dev_get_uclass_plat(parent); > + struct disk_partition info; > + struct disk_part *part_data; > + char devname[32]; > + struct udevice *dev; > + int ret; > + > + if (!CONFIG_IS_ENABLED(PARTITIONS) || > + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) > + return 0; > + > + /* Add devices for each partition */ > + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { > + if (part_get_info(desc, part, &info)) > + continue; > + snprintf(devname, sizeof(devname), "%s:%d", parent->name, > + part); > + > + ret = device_bind_driver(parent, "blk_partition", > + strdup(devname), &dev); > + if (ret) > + return ret; > + > + part_data = dev_get_uclass_plat(dev); > + part_data->partnum = part; > + part_data->gpt_part_info = info; > + count++; > + > + device_probe(dev); > + } > + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); > + > + return 0; > +} > + > static int blk_post_probe(struct udevice *dev) > { > if (IS_ENABLED(CONFIG_PARTITIONS) && > @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { > .post_probe = blk_post_probe, > .per_device_plat_auto = sizeof(struct blk_desc), > }; > + > +static ulong blk_part_read(struct udevice *dev, lbaint_t start, > + lbaint_t blkcnt, void *buffer) > +{ > + struct udevice *parent; > + struct disk_part *part; > + const struct blk_ops *ops; > + > + parent = dev_get_parent(dev);
What device type will the parent have if it is a eMMC hardware partition?
> + ops = blk_get_ops(parent); > + if (!ops->read) > + return -ENOSYS; > + > + part = dev_get_uclass_plat(dev);
You should check that we do not access the block device past the partition end:
Yes, I will fix all of checks.
struct blk_desc *desc = dev_get_uclass_plat(parent); if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) return -EFAULT.
> + start += part->gpt_part_info.start;
A better solution is: if (start >= part->gpt_part_info.size) return 0;
if ((start + blkcnt) > part->gpt_part_info.size) blkcnt = part->gpt_part_info.size - start; start += part->gpt_part_info.start;
instead of returning -EFAULT. (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
Best regards
Heinrich

Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote:
On 10/8/21 02:51, AKASHI Takahiro wrote:
On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote:
On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: > > > On 10/1/21 07:01, AKASHI Takahiro wrote: >> UCLASS_PARTITION device will be created as a child node of >> UCLASS_BLK device. >> >> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >> --- >> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >> include/blk.h | 9 +++ >> include/dm/uclass-id.h | 1 + >> 3 files changed, 121 insertions(+) >> >> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >> index 83682dcc181a..dd7f3c0fe31e 100644 >> --- a/drivers/block/blk-uclass.c >> +++ b/drivers/block/blk-uclass.c >> @@ -12,6 +12,7 @@ >> #include <log.h> >> #include <malloc.h> >> #include <part.h> >> +#include <string.h> >> #include <dm/device-internal.h> >> #include <dm/lists.h> >> #include <dm/uclass-internal.h> >> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >> return 0; >> } >> >> +int blk_create_partitions(struct udevice *parent) >> +{ >> + int part, count; >> + struct blk_desc *desc = dev_get_uclass_plat(parent); >> + struct disk_partition info; >> + struct disk_part *part_data; >> + char devname[32]; >> + struct udevice *dev; >> + int ret; >> + >> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >> + return 0; >> + >> + /* Add devices for each partition */ >> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >> + if (part_get_info(desc, part, &info)) >> + continue; >> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >> + part); >> + >> + ret = device_bind_driver(parent, "blk_partition", >> + strdup(devname), &dev); >> + if (ret) >> + return ret; >> + >> + part_data = dev_get_uclass_plat(dev); >> + part_data->partnum = part; >> + part_data->gpt_part_info = info; >> + count++; >> + >> + device_probe(dev); >> + } >> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >> + >> + return 0; >> +} >> + >> static int blk_post_probe(struct udevice *dev) >> { >> if (IS_ENABLED(CONFIG_PARTITIONS) && >> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >> .post_probe = blk_post_probe, >> .per_device_plat_auto = sizeof(struct blk_desc), >> }; >> + >> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >> + lbaint_t blkcnt, void *buffer) >> +{ >> + struct udevice *parent; >> + struct disk_part *part; >> + const struct blk_ops *ops; >> + >> + parent = dev_get_parent(dev); > > What device type will the parent have if it is a eMMC hardware partition? > >> + ops = blk_get_ops(parent); >> + if (!ops->read) >> + return -ENOSYS; >> + >> + part = dev_get_uclass_plat(dev); > > You should check that we do not access the block device past the > partition end:
Yes, I will fix all of checks.
> struct blk_desc *desc = dev_get_uclass_plat(parent); > if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) > return -EFAULT. > >> + start += part->gpt_part_info.start;
A better solution is: if (start >= part->gpt_part_info.size) return 0;
if ((start + blkcnt) > part->gpt_part_info.size) blkcnt = part->gpt_part_info.size - start; start += part->gpt_part_info.start;
instead of returning -EFAULT. (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Regards, Simon

On 10/11/21 18:14, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote:
On 10/8/21 02:51, AKASHI Takahiro wrote:
On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: > On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >> >> >> On 10/1/21 07:01, AKASHI Takahiro wrote: >>> UCLASS_PARTITION device will be created as a child node of >>> UCLASS_BLK device. >>> >>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>> --- >>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>> include/blk.h | 9 +++ >>> include/dm/uclass-id.h | 1 + >>> 3 files changed, 121 insertions(+) >>> >>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>> index 83682dcc181a..dd7f3c0fe31e 100644 >>> --- a/drivers/block/blk-uclass.c >>> +++ b/drivers/block/blk-uclass.c >>> @@ -12,6 +12,7 @@ >>> #include <log.h> >>> #include <malloc.h> >>> #include <part.h> >>> +#include <string.h> >>> #include <dm/device-internal.h> >>> #include <dm/lists.h> >>> #include <dm/uclass-internal.h> >>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>> return 0; >>> } >>> >>> +int blk_create_partitions(struct udevice *parent) >>> +{ >>> + int part, count; >>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>> + struct disk_partition info; >>> + struct disk_part *part_data; >>> + char devname[32]; >>> + struct udevice *dev; >>> + int ret; >>> + >>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>> + return 0; >>> + >>> + /* Add devices for each partition */ >>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>> + if (part_get_info(desc, part, &info)) >>> + continue; >>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>> + part); >>> + >>> + ret = device_bind_driver(parent, "blk_partition", >>> + strdup(devname), &dev); >>> + if (ret) >>> + return ret; >>> + >>> + part_data = dev_get_uclass_plat(dev); >>> + part_data->partnum = part; >>> + part_data->gpt_part_info = info; >>> + count++; >>> + >>> + device_probe(dev); >>> + } >>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>> + >>> + return 0; >>> +} >>> + >>> static int blk_post_probe(struct udevice *dev) >>> { >>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>> .post_probe = blk_post_probe, >>> .per_device_plat_auto = sizeof(struct blk_desc), >>> }; >>> + >>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>> + lbaint_t blkcnt, void *buffer) >>> +{ >>> + struct udevice *parent; >>> + struct disk_part *part; >>> + const struct blk_ops *ops; >>> + >>> + parent = dev_get_parent(dev); >> >> What device type will the parent have if it is a eMMC hardware partition? >> >>> + ops = blk_get_ops(parent); >>> + if (!ops->read) >>> + return -ENOSYS; >>> + >>> + part = dev_get_uclass_plat(dev); >> >> You should check that we do not access the block device past the >> partition end: > > Yes, I will fix all of checks. > >> struct blk_desc *desc = dev_get_uclass_plat(parent); >> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >> return -EFAULT. >> >>> + start += part->gpt_part_info.start;
A better solution is: if (start >= part->gpt_part_info.size) return 0;
if ((start + blkcnt) > part->gpt_part_info.size) blkcnt = part->gpt_part_info.size - start; start += part->gpt_part_info.start;
instead of returning -EFAULT. (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Best regards
Heinrich

Hi Heinrich,,
On Mon, 11 Oct 2021 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 18:14, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote:
On 10/8/21 02:51, AKASHI Takahiro wrote: > On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>> >>> >>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>> UCLASS_PARTITION device will be created as a child node of >>>> UCLASS_BLK device. >>>> >>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>> --- >>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>> include/blk.h | 9 +++ >>>> include/dm/uclass-id.h | 1 + >>>> 3 files changed, 121 insertions(+) >>>> >>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>> --- a/drivers/block/blk-uclass.c >>>> +++ b/drivers/block/blk-uclass.c >>>> @@ -12,6 +12,7 @@ >>>> #include <log.h> >>>> #include <malloc.h> >>>> #include <part.h> >>>> +#include <string.h> >>>> #include <dm/device-internal.h> >>>> #include <dm/lists.h> >>>> #include <dm/uclass-internal.h> >>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>> return 0; >>>> } >>>> >>>> +int blk_create_partitions(struct udevice *parent) >>>> +{ >>>> + int part, count; >>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>> + struct disk_partition info; >>>> + struct disk_part *part_data; >>>> + char devname[32]; >>>> + struct udevice *dev; >>>> + int ret; >>>> + >>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>> + return 0; >>>> + >>>> + /* Add devices for each partition */ >>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>> + if (part_get_info(desc, part, &info)) >>>> + continue; >>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>> + part); >>>> + >>>> + ret = device_bind_driver(parent, "blk_partition", >>>> + strdup(devname), &dev); >>>> + if (ret) >>>> + return ret; >>>> + >>>> + part_data = dev_get_uclass_plat(dev); >>>> + part_data->partnum = part; >>>> + part_data->gpt_part_info = info; >>>> + count++; >>>> + >>>> + device_probe(dev); >>>> + } >>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> static int blk_post_probe(struct udevice *dev) >>>> { >>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>> .post_probe = blk_post_probe, >>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>> }; >>>> + >>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>> + lbaint_t blkcnt, void *buffer) >>>> +{ >>>> + struct udevice *parent; >>>> + struct disk_part *part; >>>> + const struct blk_ops *ops; >>>> + >>>> + parent = dev_get_parent(dev); >>> >>> What device type will the parent have if it is a eMMC hardware partition? >>> >>>> + ops = blk_get_ops(parent); >>>> + if (!ops->read) >>>> + return -ENOSYS; >>>> + >>>> + part = dev_get_uclass_plat(dev); >>> >>> You should check that we do not access the block device past the >>> partition end: >> >> Yes, I will fix all of checks. >> >>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>> return -EFAULT. >>> >>>> + start += part->gpt_part_info.start; > > A better solution is: > if (start >= part->gpt_part_info.size) > return 0; > > if ((start + blkcnt) > part->gpt_part_info.size) > blkcnt = part->gpt_part_info.size - start; > start += part->gpt_part_info.start; > instead of returning -EFAULT. > (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I presume you meant to include a BLK device under each PARTITION?
But anyway, I was more thinking of this:
MMC | HWPARTITION rpmb || BLK whole rpmb || PARTITION 1 ||| BLK || PARTITION 2 ||| BLK || PARTITION 3 ||| BLK | HWPARTITION boot0 || BLK (maybe have PARTITION in here too? | HWPARTITION boot1 (maybe have PARTITION in here too? || BLK
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
I'm not quite sure about the terminology here. I'm not even talking about UEFI, really, just how best to model this stuff in U-Boot.
In U-Boot, UCLASS_SCSI should be a SCSI controller, not a device, right? I'm a little worried it is not modelled correctly. After all, what is the parent of a SCSI device?
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Regards, Simon

Simon, Heinrich,
On Mon, Oct 11, 2021 at 11:41:02AM -0600, Simon Glass wrote:
Hi Heinrich,,
On Mon, 11 Oct 2021 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 18:14, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote: > > > On 10/8/21 02:51, AKASHI Takahiro wrote: >> On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >>> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>>> >>>> >>>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>>> UCLASS_PARTITION device will be created as a child node of >>>>> UCLASS_BLK device. >>>>> >>>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>>> --- >>>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>>> include/blk.h | 9 +++ >>>>> include/dm/uclass-id.h | 1 + >>>>> 3 files changed, 121 insertions(+) >>>>> >>>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>>> --- a/drivers/block/blk-uclass.c >>>>> +++ b/drivers/block/blk-uclass.c >>>>> @@ -12,6 +12,7 @@ >>>>> #include <log.h> >>>>> #include <malloc.h> >>>>> #include <part.h> >>>>> +#include <string.h> >>>>> #include <dm/device-internal.h> >>>>> #include <dm/lists.h> >>>>> #include <dm/uclass-internal.h> >>>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>>> return 0; >>>>> } >>>>> >>>>> +int blk_create_partitions(struct udevice *parent) >>>>> +{ >>>>> + int part, count; >>>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>> + struct disk_partition info; >>>>> + struct disk_part *part_data; >>>>> + char devname[32]; >>>>> + struct udevice *dev; >>>>> + int ret; >>>>> + >>>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>>> + return 0; >>>>> + >>>>> + /* Add devices for each partition */ >>>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>>> + if (part_get_info(desc, part, &info)) >>>>> + continue; >>>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>>> + part); >>>>> + >>>>> + ret = device_bind_driver(parent, "blk_partition", >>>>> + strdup(devname), &dev); >>>>> + if (ret) >>>>> + return ret; >>>>> + >>>>> + part_data = dev_get_uclass_plat(dev); >>>>> + part_data->partnum = part; >>>>> + part_data->gpt_part_info = info; >>>>> + count++; >>>>> + >>>>> + device_probe(dev); >>>>> + } >>>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>>> + >>>>> + return 0; >>>>> +} >>>>> + >>>>> static int blk_post_probe(struct udevice *dev) >>>>> { >>>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>>> .post_probe = blk_post_probe, >>>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>>> }; >>>>> + >>>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>>> + lbaint_t blkcnt, void *buffer) >>>>> +{ >>>>> + struct udevice *parent; >>>>> + struct disk_part *part; >>>>> + const struct blk_ops *ops; >>>>> + >>>>> + parent = dev_get_parent(dev); >>>> >>>> What device type will the parent have if it is a eMMC hardware partition? >>>> >>>>> + ops = blk_get_ops(parent); >>>>> + if (!ops->read) >>>>> + return -ENOSYS; >>>>> + >>>>> + part = dev_get_uclass_plat(dev); >>>> >>>> You should check that we do not access the block device past the >>>> partition end: >>> >>> Yes, I will fix all of checks. >>> >>>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>>> return -EFAULT. >>>> >>>>> + start += part->gpt_part_info.start; >> >> A better solution is: >> if (start >= part->gpt_part_info.size) >> return 0; >> >> if ((start + blkcnt) > part->gpt_part_info.size) >> blkcnt = part->gpt_part_info.size - start; >> start += part->gpt_part_info.start; >> instead of returning -EFAULT. >> (note that start and blkcnt are in "block".) > > What is your motivation to support an illegal access? > > We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The > ReadBlocks() and WriteBlocks() services must return > EFI_INVALID_PARAMETER if the read request contains LBAs that are not > valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I presume you meant to include a BLK device under each PARTITION?
I do understand that PARTITION is not BLK, but thinking that there is always one-to-one link between a PARTITION device and a BLK device, what benefit will we see in distinguishing one from the other? I'm afraid that this makes things a bit complicated.
But anyway, I was more thinking of this:
MMC | HWPARTITION rpmb || BLK whole rpmb || PARTITION 1 ||| BLK || PARTITION 2 ||| BLK || PARTITION 3 ||| BLK | HWPARTITION boot0 || BLK (maybe have PARTITION in here too? | HWPARTITION boot1 (maybe have PARTITION in here too? || BLK
I simply wonder why not we see "HWPARTITION" as yet another block device [controller] (like scsi LUN's and/or NVME namespaces as discussed in a thread of "part: call part_init() in blk_get_device_by_str() only for MMC"?).
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
I'm not quite sure about the terminology here. I'm not even talking about UEFI, really, just how best to model this stuff in U-Boot.
Anyhow, if we pursue the direction that you suggested here, we will end up with having one PARTITION *driver* per partition type, efi, dos or iso, under disk/?
# Oops, extra work :)
Thanks, -Takahiro Akashi
In U-Boot, UCLASS_SCSI should be a SCSI controller, not a device, right? I'm a little worried it is not modelled correctly. After all, what is the parent of a SCSI device?
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Regards, Simon

Am 12. Oktober 2021 07:12:59 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org:
Simon, Heinrich,
On Mon, Oct 11, 2021 at 11:41:02AM -0600, Simon Glass wrote:
Hi Heinrich,,
On Mon, 11 Oct 2021 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 18:14, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > Heinrich, > > On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote: >> >> >> On 10/8/21 02:51, AKASHI Takahiro wrote: >>> On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >>>> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>>>> >>>>> >>>>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>>>> UCLASS_PARTITION device will be created as a child node of >>>>>> UCLASS_BLK device. >>>>>> >>>>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>>>> --- >>>>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>>>> include/blk.h | 9 +++ >>>>>> include/dm/uclass-id.h | 1 + >>>>>> 3 files changed, 121 insertions(+) >>>>>> >>>>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>>>> --- a/drivers/block/blk-uclass.c >>>>>> +++ b/drivers/block/blk-uclass.c >>>>>> @@ -12,6 +12,7 @@ >>>>>> #include <log.h> >>>>>> #include <malloc.h> >>>>>> #include <part.h> >>>>>> +#include <string.h> >>>>>> #include <dm/device-internal.h> >>>>>> #include <dm/lists.h> >>>>>> #include <dm/uclass-internal.h> >>>>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>>>> return 0; >>>>>> } >>>>>> >>>>>> +int blk_create_partitions(struct udevice *parent) >>>>>> +{ >>>>>> + int part, count; >>>>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>>> + struct disk_partition info; >>>>>> + struct disk_part *part_data; >>>>>> + char devname[32]; >>>>>> + struct udevice *dev; >>>>>> + int ret; >>>>>> + >>>>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>>>> + return 0; >>>>>> + >>>>>> + /* Add devices for each partition */ >>>>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>>>> + if (part_get_info(desc, part, &info)) >>>>>> + continue; >>>>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>>>> + part); >>>>>> + >>>>>> + ret = device_bind_driver(parent, "blk_partition", >>>>>> + strdup(devname), &dev); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> + >>>>>> + part_data = dev_get_uclass_plat(dev); >>>>>> + part_data->partnum = part; >>>>>> + part_data->gpt_part_info = info; >>>>>> + count++; >>>>>> + >>>>>> + device_probe(dev); >>>>>> + } >>>>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>>>> + >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> static int blk_post_probe(struct udevice *dev) >>>>>> { >>>>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>>>> .post_probe = blk_post_probe, >>>>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>>>> }; >>>>>> + >>>>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>>>> + lbaint_t blkcnt, void *buffer) >>>>>> +{ >>>>>> + struct udevice *parent; >>>>>> + struct disk_part *part; >>>>>> + const struct blk_ops *ops; >>>>>> + >>>>>> + parent = dev_get_parent(dev); >>>>> >>>>> What device type will the parent have if it is a eMMC hardware partition? >>>>> >>>>>> + ops = blk_get_ops(parent); >>>>>> + if (!ops->read) >>>>>> + return -ENOSYS; >>>>>> + >>>>>> + part = dev_get_uclass_plat(dev); >>>>> >>>>> You should check that we do not access the block device past the >>>>> partition end: >>>> >>>> Yes, I will fix all of checks. >>>> >>>>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>>>> return -EFAULT. >>>>> >>>>>> + start += part->gpt_part_info.start; >>> >>> A better solution is: >>> if (start >= part->gpt_part_info.size) >>> return 0; >>> >>> if ((start + blkcnt) > part->gpt_part_info.size) >>> blkcnt = part->gpt_part_info.size - start; >>> start += part->gpt_part_info.start; >>> instead of returning -EFAULT. >>> (note that start and blkcnt are in "block".) >> >> What is your motivation to support an illegal access? >> >> We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The >> ReadBlocks() and WriteBlocks() services must return >> EFI_INVALID_PARAMETER if the read request contains LBAs that are not >> valid. > > I interpreted that 'LBA' was the third parameter to ReadBlocks API, > and that if the starting block is out of partition region, we should > return an error (and if not, we still want to trim IO request to fit > into partition size as other OS's API like linux does). > Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I presume you meant to include a BLK device under each PARTITION?
I do understand that PARTITION is not BLK, but thinking that there is always one-to-one link between a PARTITION device and a BLK device, what benefit will we see in distinguishing one from the other? I'm afraid that this makes things a bit complicated.
But anyway, I was more thinking of this:
MMC | HWPARTITION rpmb || BLK whole rpmb || PARTITION 1 ||| BLK || PARTITION 2 ||| BLK || PARTITION 3 ||| BLK | HWPARTITION boot0 || BLK (maybe have PARTITION in here too? | HWPARTITION boot1 (maybe have PARTITION in here too? || BLK
I simply wonder why not we see "HWPARTITION" as yet another block device [controller] (like scsi LUN's and/or NVME namespaces as discussed in a thread of "part: call part_init() in blk_get_device_by_str() only for MMC"?).
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
I'm not quite sure about the terminology here. I'm not even talking about UEFI, really, just how best to model this stuff in U-Boot.
Anyhow, if we pursue the direction that you suggested here, we will end up with having one PARTITION *driver* per partition type, efi, dos or iso, under disk/?
We already have one driver per partition table type. They just need to be integrated into the DM model. Partitions are defined by first and last block. They don't depend on the type of the partition table. But you need separate drivers per filesystem.
The block device needs a pointer to the partition table driver.
The partition needs a pointer to the filesystem driver.
Best regards
Heinrich
# Oops, extra work :)
Thanks, -Takahiro Akashi
In U-Boot, UCLASS_SCSI should be a SCSI controller, not a device, right? I'm a little worried it is not modelled correctly. After all, what is the parent of a SCSI device?
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Regards, Simon

On Mon, Oct 11, 2021 at 10:14:00AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote:
On 10/8/21 02:51, AKASHI Takahiro wrote:
On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: > On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >> >> >> On 10/1/21 07:01, AKASHI Takahiro wrote: >>> UCLASS_PARTITION device will be created as a child node of >>> UCLASS_BLK device. >>> >>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>> --- >>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>> include/blk.h | 9 +++ >>> include/dm/uclass-id.h | 1 + >>> 3 files changed, 121 insertions(+) >>> >>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>> index 83682dcc181a..dd7f3c0fe31e 100644 >>> --- a/drivers/block/blk-uclass.c >>> +++ b/drivers/block/blk-uclass.c >>> @@ -12,6 +12,7 @@ >>> #include <log.h> >>> #include <malloc.h> >>> #include <part.h> >>> +#include <string.h> >>> #include <dm/device-internal.h> >>> #include <dm/lists.h> >>> #include <dm/uclass-internal.h> >>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>> return 0; >>> } >>> >>> +int blk_create_partitions(struct udevice *parent) >>> +{ >>> + int part, count; >>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>> + struct disk_partition info; >>> + struct disk_part *part_data; >>> + char devname[32]; >>> + struct udevice *dev; >>> + int ret; >>> + >>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>> + return 0; >>> + >>> + /* Add devices for each partition */ >>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>> + if (part_get_info(desc, part, &info)) >>> + continue; >>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>> + part); >>> + >>> + ret = device_bind_driver(parent, "blk_partition", >>> + strdup(devname), &dev); >>> + if (ret) >>> + return ret; >>> + >>> + part_data = dev_get_uclass_plat(dev); >>> + part_data->partnum = part; >>> + part_data->gpt_part_info = info; >>> + count++; >>> + >>> + device_probe(dev); >>> + } >>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>> + >>> + return 0; >>> +} >>> + >>> static int blk_post_probe(struct udevice *dev) >>> { >>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>> .post_probe = blk_post_probe, >>> .per_device_plat_auto = sizeof(struct blk_desc), >>> }; >>> + >>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>> + lbaint_t blkcnt, void *buffer) >>> +{ >>> + struct udevice *parent; >>> + struct disk_part *part; >>> + const struct blk_ops *ops; >>> + >>> + parent = dev_get_parent(dev); >> >> What device type will the parent have if it is a eMMC hardware partition? >> >>> + ops = blk_get_ops(parent); >>> + if (!ops->read) >>> + return -ENOSYS; >>> + >>> + part = dev_get_uclass_plat(dev); >> >> You should check that we do not access the block device past the >> partition end: > > Yes, I will fix all of checks. > >> struct blk_desc *desc = dev_get_uclass_plat(parent); >> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >> return -EFAULT. >> >>> + start += part->gpt_part_info.start;
A better solution is: if (start >= part->gpt_part_info.size) return 0;
if ((start + blkcnt) > part->gpt_part_info.size) blkcnt = part->gpt_part_info.size - start; start += part->gpt_part_info.start;
instead of returning -EFAULT. (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Note that for eMMC devices, hardware partitions are different from partition-table partitions. If you boot a system with an eMMC device up in Linux you typically get mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb, each of which are hardware partitions. It gets tricky in U-Boot in that you can access each of these with 'mmc dev N M' where M defaults to 0 and is the user partition (mmcblkN), 1/2 are boot0/boot1 and 3 is the rpmb area. The 'mmc' command also allows, when possible and implemented, configuring these partitions, again to the extent allowed, documented and implemented.
In terms of modeling, this is akin to how if you use a USB card reader that supports 4 different form-factor cards, you can end up with 4 different devices showing up in Linux (if you have one of the nice card readers that supports multiple cards at once).

On Tue, Oct 12, 2021 at 11:14:17AM -0400, Tom Rini wrote:
On Mon, Oct 11, 2021 at 10:14:00AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote:
On 10/8/21 02:51, AKASHI Takahiro wrote: > On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>> >>> >>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>> UCLASS_PARTITION device will be created as a child node of >>>> UCLASS_BLK device. >>>> >>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>> --- >>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>> include/blk.h | 9 +++ >>>> include/dm/uclass-id.h | 1 + >>>> 3 files changed, 121 insertions(+) >>>> >>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>> --- a/drivers/block/blk-uclass.c >>>> +++ b/drivers/block/blk-uclass.c >>>> @@ -12,6 +12,7 @@ >>>> #include <log.h> >>>> #include <malloc.h> >>>> #include <part.h> >>>> +#include <string.h> >>>> #include <dm/device-internal.h> >>>> #include <dm/lists.h> >>>> #include <dm/uclass-internal.h> >>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>> return 0; >>>> } >>>> >>>> +int blk_create_partitions(struct udevice *parent) >>>> +{ >>>> + int part, count; >>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>> + struct disk_partition info; >>>> + struct disk_part *part_data; >>>> + char devname[32]; >>>> + struct udevice *dev; >>>> + int ret; >>>> + >>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>> + return 0; >>>> + >>>> + /* Add devices for each partition */ >>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>> + if (part_get_info(desc, part, &info)) >>>> + continue; >>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>> + part); >>>> + >>>> + ret = device_bind_driver(parent, "blk_partition", >>>> + strdup(devname), &dev); >>>> + if (ret) >>>> + return ret; >>>> + >>>> + part_data = dev_get_uclass_plat(dev); >>>> + part_data->partnum = part; >>>> + part_data->gpt_part_info = info; >>>> + count++; >>>> + >>>> + device_probe(dev); >>>> + } >>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> static int blk_post_probe(struct udevice *dev) >>>> { >>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>> .post_probe = blk_post_probe, >>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>> }; >>>> + >>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>> + lbaint_t blkcnt, void *buffer) >>>> +{ >>>> + struct udevice *parent; >>>> + struct disk_part *part; >>>> + const struct blk_ops *ops; >>>> + >>>> + parent = dev_get_parent(dev); >>> >>> What device type will the parent have if it is a eMMC hardware partition? >>> >>>> + ops = blk_get_ops(parent); >>>> + if (!ops->read) >>>> + return -ENOSYS; >>>> + >>>> + part = dev_get_uclass_plat(dev); >>> >>> You should check that we do not access the block device past the >>> partition end: >> >> Yes, I will fix all of checks. >> >>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>> return -EFAULT. >>> >>>> + start += part->gpt_part_info.start; > > A better solution is: > if (start >= part->gpt_part_info.size) > return 0; > > if ((start + blkcnt) > part->gpt_part_info.size) > blkcnt = part->gpt_part_info.size - start; > start += part->gpt_part_info.start; > instead of returning -EFAULT. > (note that start and blkcnt are in "block".)
What is your motivation to support an illegal access?
We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The ReadBlocks() and WriteBlocks() services must return EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Note that for eMMC devices, hardware partitions are different from partition-table partitions. If you boot a system with an eMMC device up in Linux you typically get mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb, each of which are hardware partitions. It gets tricky in U-Boot in that you can access each of these with 'mmc dev N M' where M defaults to 0 and is the user partition (mmcblkN), 1/2 are boot0/boot1 and 3 is the rpmb area. The 'mmc' command also allows, when possible and implemented, configuring these partitions, again to the extent allowed, documented and implemented.
Thank you. That is exactly what I tried to mention in my reply at "part: call part_init() in blk_get_device_by_str() only for MMC"
---8<--- # On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). --->8---
The problem with the current U-Boot driver model is that all of "mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb" will be linked to the same udevice. We have to do "mmc dev N M" or call blk_select_hwpart[_devnum]() to distinguish them.
When it comes to UEFI, I hope we can currently support hw partitions in this way: => efidebug add boot -b 1 FOO mmc 0.1 /foo.bin "" (".1" is a key, I have never tried this syntax though.)
But probably its device path won't be properly formatted as expected as Heinrich suggested.
-Takahiro Akashi
In terms of modeling, this is akin to how if you use a USB card reader that supports 4 different form-factor cards, you can end up with 4 different devices showing up in Linux (if you have one of the nice card readers that supports multiple cards at once).
-- Tom

Hi Takahiro,
On Tue, 12 Oct 2021 at 19:32, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Tue, Oct 12, 2021 at 11:14:17AM -0400, Tom Rini wrote:
On Mon, Oct 11, 2021 at 10:14:00AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Heinrich,
On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote: > > > On 10/8/21 02:51, AKASHI Takahiro wrote: >> On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >>> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>>> >>>> >>>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>>> UCLASS_PARTITION device will be created as a child node of >>>>> UCLASS_BLK device. >>>>> >>>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>>> --- >>>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>>> include/blk.h | 9 +++ >>>>> include/dm/uclass-id.h | 1 + >>>>> 3 files changed, 121 insertions(+) >>>>> >>>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>>> --- a/drivers/block/blk-uclass.c >>>>> +++ b/drivers/block/blk-uclass.c >>>>> @@ -12,6 +12,7 @@ >>>>> #include <log.h> >>>>> #include <malloc.h> >>>>> #include <part.h> >>>>> +#include <string.h> >>>>> #include <dm/device-internal.h> >>>>> #include <dm/lists.h> >>>>> #include <dm/uclass-internal.h> >>>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>>> return 0; >>>>> } >>>>> >>>>> +int blk_create_partitions(struct udevice *parent) >>>>> +{ >>>>> + int part, count; >>>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>> + struct disk_partition info; >>>>> + struct disk_part *part_data; >>>>> + char devname[32]; >>>>> + struct udevice *dev; >>>>> + int ret; >>>>> + >>>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>>> + return 0; >>>>> + >>>>> + /* Add devices for each partition */ >>>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>>> + if (part_get_info(desc, part, &info)) >>>>> + continue; >>>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>>> + part); >>>>> + >>>>> + ret = device_bind_driver(parent, "blk_partition", >>>>> + strdup(devname), &dev); >>>>> + if (ret) >>>>> + return ret; >>>>> + >>>>> + part_data = dev_get_uclass_plat(dev); >>>>> + part_data->partnum = part; >>>>> + part_data->gpt_part_info = info; >>>>> + count++; >>>>> + >>>>> + device_probe(dev); >>>>> + } >>>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>>> + >>>>> + return 0; >>>>> +} >>>>> + >>>>> static int blk_post_probe(struct udevice *dev) >>>>> { >>>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>>> .post_probe = blk_post_probe, >>>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>>> }; >>>>> + >>>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>>> + lbaint_t blkcnt, void *buffer) >>>>> +{ >>>>> + struct udevice *parent; >>>>> + struct disk_part *part; >>>>> + const struct blk_ops *ops; >>>>> + >>>>> + parent = dev_get_parent(dev); >>>> >>>> What device type will the parent have if it is a eMMC hardware partition? >>>> >>>>> + ops = blk_get_ops(parent); >>>>> + if (!ops->read) >>>>> + return -ENOSYS; >>>>> + >>>>> + part = dev_get_uclass_plat(dev); >>>> >>>> You should check that we do not access the block device past the >>>> partition end: >>> >>> Yes, I will fix all of checks. >>> >>>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>>> return -EFAULT. >>>> >>>>> + start += part->gpt_part_info.start; >> >> A better solution is: >> if (start >= part->gpt_part_info.size) >> return 0; >> >> if ((start + blkcnt) > part->gpt_part_info.size) >> blkcnt = part->gpt_part_info.size - start; >> start += part->gpt_part_info.start; >> instead of returning -EFAULT. >> (note that start and blkcnt are in "block".) > > What is your motivation to support an illegal access? > > We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The > ReadBlocks() and WriteBlocks() services must return > EFI_INVALID_PARAMETER if the read request contains LBAs that are not > valid.
I interpreted that 'LBA' was the third parameter to ReadBlocks API, and that if the starting block is out of partition region, we should return an error (and if not, we still want to trim IO request to fit into partition size as other OS's API like linux does). Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Note that for eMMC devices, hardware partitions are different from partition-table partitions. If you boot a system with an eMMC device up in Linux you typically get mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb, each of which are hardware partitions. It gets tricky in U-Boot in that you can access each of these with 'mmc dev N M' where M defaults to 0 and is the user partition (mmcblkN), 1/2 are boot0/boot1 and 3 is the rpmb area. The 'mmc' command also allows, when possible and implemented, configuring these partitions, again to the extent allowed, documented and implemented.
Thank you. That is exactly what I tried to mention in my reply at "part: call part_init() in blk_get_device_by_str() only for MMC"
OK so it sounds like we agree that hwpartition and partition are different things.
---8<--- # On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). --->8---
The problem with the current U-Boot driver model is that all of "mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb" will be linked to the same udevice. We have to do "mmc dev N M" or call blk_select_hwpart[_devnum]() to distinguish them.
Here's our chance to rethink this. What should the device hierarchy be for an MMC device? I made a proposal further up the thread.
When it comes to UEFI, I hope we can currently support hw partitions in this way: => efidebug add boot -b 1 FOO mmc 0.1 /foo.bin "" (".1" is a key, I have never tried this syntax though.)
But probably its device path won't be properly formatted as expected as Heinrich suggested.
-Takahiro Akashi
In terms of modeling, this is akin to how if you use a USB card reader that supports 4 different form-factor cards, you can end up with 4 different devices showing up in Linux (if you have one of the nice card readers that supports multiple cards at once).
-- Tom
Regards, Simon

Simon,
On Wed, Oct 13, 2021 at 12:05:58PM -0600, Simon Glass wrote:
Hi Takahiro,
On Tue, 12 Oct 2021 at 19:32, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Tue, Oct 12, 2021 at 11:14:17AM -0400, Tom Rini wrote:
On Mon, Oct 11, 2021 at 10:14:00AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > Heinrich, > > On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote: >> >> >> On 10/8/21 02:51, AKASHI Takahiro wrote: >>> On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >>>> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>>>> >>>>> >>>>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>>>> UCLASS_PARTITION device will be created as a child node of >>>>>> UCLASS_BLK device. >>>>>> >>>>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>>>> --- >>>>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>>>> include/blk.h | 9 +++ >>>>>> include/dm/uclass-id.h | 1 + >>>>>> 3 files changed, 121 insertions(+) >>>>>> >>>>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>>>> --- a/drivers/block/blk-uclass.c >>>>>> +++ b/drivers/block/blk-uclass.c >>>>>> @@ -12,6 +12,7 @@ >>>>>> #include <log.h> >>>>>> #include <malloc.h> >>>>>> #include <part.h> >>>>>> +#include <string.h> >>>>>> #include <dm/device-internal.h> >>>>>> #include <dm/lists.h> >>>>>> #include <dm/uclass-internal.h> >>>>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>>>> return 0; >>>>>> } >>>>>> >>>>>> +int blk_create_partitions(struct udevice *parent) >>>>>> +{ >>>>>> + int part, count; >>>>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>>> + struct disk_partition info; >>>>>> + struct disk_part *part_data; >>>>>> + char devname[32]; >>>>>> + struct udevice *dev; >>>>>> + int ret; >>>>>> + >>>>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>>>> + return 0; >>>>>> + >>>>>> + /* Add devices for each partition */ >>>>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>>>> + if (part_get_info(desc, part, &info)) >>>>>> + continue; >>>>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>>>> + part); >>>>>> + >>>>>> + ret = device_bind_driver(parent, "blk_partition", >>>>>> + strdup(devname), &dev); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> + >>>>>> + part_data = dev_get_uclass_plat(dev); >>>>>> + part_data->partnum = part; >>>>>> + part_data->gpt_part_info = info; >>>>>> + count++; >>>>>> + >>>>>> + device_probe(dev); >>>>>> + } >>>>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>>>> + >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> static int blk_post_probe(struct udevice *dev) >>>>>> { >>>>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>>>> .post_probe = blk_post_probe, >>>>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>>>> }; >>>>>> + >>>>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>>>> + lbaint_t blkcnt, void *buffer) >>>>>> +{ >>>>>> + struct udevice *parent; >>>>>> + struct disk_part *part; >>>>>> + const struct blk_ops *ops; >>>>>> + >>>>>> + parent = dev_get_parent(dev); >>>>> >>>>> What device type will the parent have if it is a eMMC hardware partition? >>>>> >>>>>> + ops = blk_get_ops(parent); >>>>>> + if (!ops->read) >>>>>> + return -ENOSYS; >>>>>> + >>>>>> + part = dev_get_uclass_plat(dev); >>>>> >>>>> You should check that we do not access the block device past the >>>>> partition end: >>>> >>>> Yes, I will fix all of checks. >>>> >>>>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>>>> return -EFAULT. >>>>> >>>>>> + start += part->gpt_part_info.start; >>> >>> A better solution is: >>> if (start >= part->gpt_part_info.size) >>> return 0; >>> >>> if ((start + blkcnt) > part->gpt_part_info.size) >>> blkcnt = part->gpt_part_info.size - start; >>> start += part->gpt_part_info.start; >>> instead of returning -EFAULT. >>> (note that start and blkcnt are in "block".) >> >> What is your motivation to support an illegal access? >> >> We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The >> ReadBlocks() and WriteBlocks() services must return >> EFI_INVALID_PARAMETER if the read request contains LBAs that are not >> valid. > > I interpreted that 'LBA' was the third parameter to ReadBlocks API, > and that if the starting block is out of partition region, we should > return an error (and if not, we still want to trim IO request to fit > into partition size as other OS's API like linux does). > Do you think it's incorrect?
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Note that for eMMC devices, hardware partitions are different from partition-table partitions. If you boot a system with an eMMC device up in Linux you typically get mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb, each of which are hardware partitions. It gets tricky in U-Boot in that you can access each of these with 'mmc dev N M' where M defaults to 0 and is the user partition (mmcblkN), 1/2 are boot0/boot1 and 3 is the rpmb area. The 'mmc' command also allows, when possible and implemented, configuring these partitions, again to the extent allowed, documented and implemented.
Thank you. That is exactly what I tried to mention in my reply at "part: call part_init() in blk_get_device_by_str() only for MMC"
OK so it sounds like we agree that hwpartition and partition are different things.
Yes. Please note, IIUC, that * MMC hw partitions on a device are mapped to one udevice, differentiating them by blk_desc->hwpart. * Each NVME namespace on a device is mapped to a different udevice with a different blk_desc->devnum (and nvme_dev->ns_id). * Each UFS partition (or which is, I suppose, equivalent to scsi LUN) on a device is mapped to a different udevice with a different blk_desc->devnum (and blk_desc->lun).
So even though those type of devices have some kind of hardware partitions, they are modelled differently in U-Boot. (Obviously, I might be wrong here as I'm not quite familiar yet.)
---8<--- # On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). --->8---
The problem with the current U-Boot driver model is that all of "mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb" will be linked to the same udevice. We have to do "mmc dev N M" or call blk_select_hwpart[_devnum]() to distinguish them.
Here's our chance to rethink this. What should the device hierarchy be for an MMC device? I made a proposal further up the thread.
Well,
On Mon, Oct 11, 2021 at 11:41:02AM -0600, Simon Glass wrote:
On Mon, 11 Oct 2021 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Yeah, but there is always 1-to-1 mapping between a partition and a block (for a partition), so I still wonder whether it makes sense to model partitions in the way above.
Alternatively, the following hierarchy also makes some sense. (This is not what I have in my RFC though.) - MMC |- BLK (whole disk with part=0) |- BLK (partition 1) |- BLK (partition 2) |- BLK (partition 3)
or
- MMC |- DISK (whole disk) ||- BLK (partition 0) ||- BLK (partition 1) ||- BLK (partition 2) ||- BLK (partition 3)
Here MMC: provides read/write operations (via blk_ops) DISK: holds a geometry of a whole disk and other info BLK: partition info (+ blk_ops + geo) (part=0 means a while disk)
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I presume you meant to include a BLK device under each PARTITION?
But anyway, I was more thinking of this:
MMC | HWPARTITION rpmb || BLK whole rpmb || PARTITION 1 ||| BLK || PARTITION 2 ||| BLK || PARTITION 3
Do we have any reason to model a RPMB partition as a block device? For linux, at least, mmcblkrpmb looks to be a character device.
||| BLK | HWPARTITION boot0 || BLK (maybe have PARTITION in here too?
I don't know how boot partitions are used on a production system. It's unlikely to have partitions on them given the purpose of "boot" partitions?
| HWPARTITION boot1 (maybe have PARTITION in here too? || BLK
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
I'm not quite sure about the terminology here. I'm not even talking about UEFI, really, just how best to model this stuff in U-Boot.
In UEFI world, each efi_disk has its own device path to identify the device. For example, here is a text representation of device path for a scsi disk partition: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/HD(1,GPT,ce86c5a7-b32a-488f-a346-88fe698e0edc,0x22,0x4c2a)
which is set to be created from a corresponding udevice (more strictly blkc_desc + part).
So the issue Heinrich raised here is a matter of implementation of this conversion (software partitions, and SCSI channels?) as well as a modeling for some device type on U-Boot, i.e. MMC hardware partitions.
-Takahiro Akashi
In U-Boot, UCLASS_SCSI should be a SCSI controller, not a device, right? I'm a little worried it is not modelled correctly. After all, what is the parent of a SCSI device?
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Regards, Simon
---
When it comes to UEFI, I hope we can currently support hw partitions in this way: => efidebug add boot -b 1 FOO mmc 0.1 /foo.bin "" (".1" is a key, I have never tried this syntax though.)
But probably its device path won't be properly formatted as expected as Heinrich suggested.
-Takahiro Akashi
In terms of modeling, this is akin to how if you use a USB card reader that supports 4 different form-factor cards, you can end up with 4 different devices showing up in Linux (if you have one of the nice card readers that supports multiple cards at once).
-- Tom
Regards, Simon

Hi Takahiro,
On Thu, 14 Oct 2021 at 02:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Wed, Oct 13, 2021 at 12:05:58PM -0600, Simon Glass wrote:
Hi Takahiro,
On Tue, 12 Oct 2021 at 19:32, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Tue, Oct 12, 2021 at 11:14:17AM -0400, Tom Rini wrote:
On Mon, Oct 11, 2021 at 10:14:00AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote: > Hi Takahiro, > > On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro > takahiro.akashi@linaro.org wrote: >> >> Heinrich, >> >> On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote: >>> >>> >>> On 10/8/21 02:51, AKASHI Takahiro wrote: >>>> On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >>>>> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>>>>> >>>>>> >>>>>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>>>>> UCLASS_PARTITION device will be created as a child node of >>>>>>> UCLASS_BLK device. >>>>>>> >>>>>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>>>>> --- >>>>>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>>>>> include/blk.h | 9 +++ >>>>>>> include/dm/uclass-id.h | 1 + >>>>>>> 3 files changed, 121 insertions(+) >>>>>>> >>>>>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>>>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>>>>> --- a/drivers/block/blk-uclass.c >>>>>>> +++ b/drivers/block/blk-uclass.c >>>>>>> @@ -12,6 +12,7 @@ >>>>>>> #include <log.h> >>>>>>> #include <malloc.h> >>>>>>> #include <part.h> >>>>>>> +#include <string.h> >>>>>>> #include <dm/device-internal.h> >>>>>>> #include <dm/lists.h> >>>>>>> #include <dm/uclass-internal.h> >>>>>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>>>>> return 0; >>>>>>> } >>>>>>> >>>>>>> +int blk_create_partitions(struct udevice *parent) >>>>>>> +{ >>>>>>> + int part, count; >>>>>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>>>> + struct disk_partition info; >>>>>>> + struct disk_part *part_data; >>>>>>> + char devname[32]; >>>>>>> + struct udevice *dev; >>>>>>> + int ret; >>>>>>> + >>>>>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>>>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>>>>> + return 0; >>>>>>> + >>>>>>> + /* Add devices for each partition */ >>>>>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>>>>> + if (part_get_info(desc, part, &info)) >>>>>>> + continue; >>>>>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>>>>> + part); >>>>>>> + >>>>>>> + ret = device_bind_driver(parent, "blk_partition", >>>>>>> + strdup(devname), &dev); >>>>>>> + if (ret) >>>>>>> + return ret; >>>>>>> + >>>>>>> + part_data = dev_get_uclass_plat(dev); >>>>>>> + part_data->partnum = part; >>>>>>> + part_data->gpt_part_info = info; >>>>>>> + count++; >>>>>>> + >>>>>>> + device_probe(dev); >>>>>>> + } >>>>>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>>>>> + >>>>>>> + return 0; >>>>>>> +} >>>>>>> + >>>>>>> static int blk_post_probe(struct udevice *dev) >>>>>>> { >>>>>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>>>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>>>>> .post_probe = blk_post_probe, >>>>>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>>>>> }; >>>>>>> + >>>>>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>>>>> + lbaint_t blkcnt, void *buffer) >>>>>>> +{ >>>>>>> + struct udevice *parent; >>>>>>> + struct disk_part *part; >>>>>>> + const struct blk_ops *ops; >>>>>>> + >>>>>>> + parent = dev_get_parent(dev); >>>>>> >>>>>> What device type will the parent have if it is a eMMC hardware partition? >>>>>> >>>>>>> + ops = blk_get_ops(parent); >>>>>>> + if (!ops->read) >>>>>>> + return -ENOSYS; >>>>>>> + >>>>>>> + part = dev_get_uclass_plat(dev); >>>>>> >>>>>> You should check that we do not access the block device past the >>>>>> partition end: >>>>> >>>>> Yes, I will fix all of checks. >>>>> >>>>>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>>>>> return -EFAULT. >>>>>> >>>>>>> + start += part->gpt_part_info.start; >>>> >>>> A better solution is: >>>> if (start >= part->gpt_part_info.size) >>>> return 0; >>>> >>>> if ((start + blkcnt) > part->gpt_part_info.size) >>>> blkcnt = part->gpt_part_info.size - start; >>>> start += part->gpt_part_info.start; >>>> instead of returning -EFAULT. >>>> (note that start and blkcnt are in "block".) >>> >>> What is your motivation to support an illegal access? >>> >>> We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The >>> ReadBlocks() and WriteBlocks() services must return >>> EFI_INVALID_PARAMETER if the read request contains LBAs that are not >>> valid. >> >> I interpreted that 'LBA' was the third parameter to ReadBlocks API, >> and that if the starting block is out of partition region, we should >> return an error (and if not, we still want to trim IO request to fit >> into partition size as other OS's API like linux does). >> Do you think it's incorrect? > > [..] > > Related to this patch I think that the partition type should be really > be a child of the media device: > > - MMC > |- BLK > |- PARTITION > |- BLK > |- PARTITION > |- BLK > |- PARTITION > |- BLK > > It seems more natural to me that putting the partitions under the > top-level BLK device, so that BLK remains a 'terminal' device. > > The partition uclass is different from BLK, of course. It could > contain information about the partition such as its partition number > and UUID.
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Note that for eMMC devices, hardware partitions are different from partition-table partitions. If you boot a system with an eMMC device up in Linux you typically get mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb, each of which are hardware partitions. It gets tricky in U-Boot in that you can access each of these with 'mmc dev N M' where M defaults to 0 and is the user partition (mmcblkN), 1/2 are boot0/boot1 and 3 is the rpmb area. The 'mmc' command also allows, when possible and implemented, configuring these partitions, again to the extent allowed, documented and implemented.
Thank you. That is exactly what I tried to mention in my reply at "part: call part_init() in blk_get_device_by_str() only for MMC"
OK so it sounds like we agree that hwpartition and partition are different things.
Yes. Please note, IIUC, that
- MMC hw partitions on a device are mapped to one udevice, differentiating them by blk_desc->hwpart.
- Each NVME namespace on a device is mapped to a different udevice with a different blk_desc->devnum (and nvme_dev->ns_id).
- Each UFS partition (or which is, I suppose, equivalent to scsi LUN) on a device is mapped to a different udevice with a different blk_desc->devnum (and blk_desc->lun).
So even though those type of devices have some kind of hardware partitions, they are modelled differently in U-Boot. (Obviously, I might be wrong here as I'm not quite familiar yet.)
---8<--- # On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). --->8---
The problem with the current U-Boot driver model is that all of "mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb" will be linked to the same udevice. We have to do "mmc dev N M" or call blk_select_hwpart[_devnum]() to distinguish them.
Here's our chance to rethink this. What should the device hierarchy be for an MMC device? I made a proposal further up the thread.
Well,
On Mon, Oct 11, 2021 at 11:41:02AM -0600, Simon Glass wrote:
On Mon, 11 Oct 2021 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
[..]
Related to this patch I think that the partition type should be really be a child of the media device:
- MMC |- BLK |- PARTITION |- BLK |- PARTITION |- BLK |- PARTITION |- BLK
It seems more natural to me that putting the partitions under the top-level BLK device, so that BLK remains a 'terminal' device.
The partition uclass is different from BLK, of course. It could contain information about the partition such as its partition number and UUID.
Yeah, but there is always 1-to-1 mapping between a partition and a block (for a partition), so I still wonder whether it makes sense to model partitions in the way above.
Alternatively, the following hierarchy also makes some sense. (This is not what I have in my RFC though.)
- MMC
|- BLK (whole disk with part=0) |- BLK (partition 1) |- BLK (partition 2) |- BLK (partition 3)
or
- MMC
|- DISK (whole disk) ||- BLK (partition 0) ||- BLK (partition 1) ||- BLK (partition 2) ||- BLK (partition 3)
Here MMC: provides read/write operations (via blk_ops) DISK: holds a geometry of a whole disk and other info BLK: partition info (+ blk_ops + geo) (part=0 means a while disk)
Where does this leave hwpart? Are we giving up on that?
Both of these make some sense to me, although I'm not sure what the second one buys us. Can you explain that? Is it to deal with hwpart?
The name 'disk' is pretty awful though, these days.
If we want to iterate through all the partition tables across all devices, we could do that with a partition uclass. We could support different types of partition (s/w and h/w) with the same device driver.
I think conceptually it is cleaner to have a partition uclass but I do agree that it corresponds 100% to BLK, so maybe there is little value in practice. But which device holds the partition table in its dev_get_priv()?
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I presume you meant to include a BLK device under each PARTITION?
But anyway, I was more thinking of this:
MMC | HWPARTITION rpmb || BLK whole rpmb || PARTITION 1 ||| BLK || PARTITION 2 ||| BLK || PARTITION 3
Do we have any reason to model a RPMB partition as a block device? For linux, at least, mmcblkrpmb looks to be a character device.
||| BLK | HWPARTITION boot0 || BLK (maybe have PARTITION in here too?
I don't know how boot partitions are used on a production system. It's unlikely to have partitions on them given the purpose of "boot" partitions?
That's true. So likely they will not be used.
| HWPARTITION boot1 (maybe have PARTITION in here too? || BLK
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
I'm not quite sure about the terminology here. I'm not even talking about UEFI, really, just how best to model this stuff in U-Boot.
In UEFI world, each efi_disk has its own device path to identify the device. For example, here is a text representation of device path for a scsi disk partition: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/HD(1,GPT,ce86c5a7-b32a-488f-a346-88fe698e0edc,0x22,0x4c2a)
which is set to be created from a corresponding udevice (more strictly blkc_desc + part).
So the issue Heinrich raised here is a matter of implementation of this conversion (software partitions, and SCSI channels?) as well as a modeling for some device type on U-Boot, i.e. MMC hardware partitions.
Yes I see that. It's just that we should get our house in order first, since these discussions didn't happen when the EFI layer was written 6 years ago. If we have a good model for partitions (not just block devices) in U-Boot then it should be easier to map EFI onto it.
Regards, Simon
-Takahiro Akashi
In U-Boot, UCLASS_SCSI should be a SCSI controller, not a device, right? I'm a little worried it is not modelled correctly. After all, what is the parent of a SCSI device?
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Regards, Simon
When it comes to UEFI, I hope we can currently support hw partitions in this way: => efidebug add boot -b 1 FOO mmc 0.1 /foo.bin "" (".1" is a key, I have never tried this syntax though.)
But probably its device path won't be properly formatted as expected as Heinrich suggested.
-Takahiro Akashi
In terms of modeling, this is akin to how if you use a USB card reader that supports 4 different form-factor cards, you can end up with 4 different devices showing up in Linux (if you have one of the nice card readers that supports multiple cards at once).
-- Tom
Regards, Simon

Hi Simon,
I'd like to resume this discussion.
On Thu, Oct 14, 2021 at 02:55:36PM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 14 Oct 2021 at 02:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Wed, Oct 13, 2021 at 12:05:58PM -0600, Simon Glass wrote:
Hi Takahiro,
On Tue, 12 Oct 2021 at 19:32, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Tue, Oct 12, 2021 at 11:14:17AM -0400, Tom Rini wrote:
On Mon, Oct 11, 2021 at 10:14:00AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > On 10/11/21 16:54, Simon Glass wrote: > > Hi Takahiro, > > > > On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro > > takahiro.akashi@linaro.org wrote: > >> > >> Heinrich, > >> > >> On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote: > >>> > >>> > >>> On 10/8/21 02:51, AKASHI Takahiro wrote: > >>>> On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: > >>>>> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: > >>>>>> > >>>>>> > >>>>>> On 10/1/21 07:01, AKASHI Takahiro wrote: > >>>>>>> UCLASS_PARTITION device will be created as a child node of > >>>>>>> UCLASS_BLK device. > >>>>>>> > >>>>>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org > >>>>>>> --- > >>>>>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ > >>>>>>> include/blk.h | 9 +++ > >>>>>>> include/dm/uclass-id.h | 1 + > >>>>>>> 3 files changed, 121 insertions(+) > >>>>>>> > >>>>>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c > >>>>>>> index 83682dcc181a..dd7f3c0fe31e 100644 > >>>>>>> --- a/drivers/block/blk-uclass.c > >>>>>>> +++ b/drivers/block/blk-uclass.c > >>>>>>> @@ -12,6 +12,7 @@ > >>>>>>> #include <log.h> > >>>>>>> #include <malloc.h> > >>>>>>> #include <part.h> > >>>>>>> +#include <string.h> > >>>>>>> #include <dm/device-internal.h> > >>>>>>> #include <dm/lists.h> > >>>>>>> #include <dm/uclass-internal.h> > >>>>>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) > >>>>>>> return 0; > >>>>>>> } > >>>>>>> > >>>>>>> +int blk_create_partitions(struct udevice *parent) > >>>>>>> +{ > >>>>>>> + int part, count; > >>>>>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); > >>>>>>> + struct disk_partition info; > >>>>>>> + struct disk_part *part_data; > >>>>>>> + char devname[32]; > >>>>>>> + struct udevice *dev; > >>>>>>> + int ret; > >>>>>>> + > >>>>>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || > >>>>>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) > >>>>>>> + return 0; > >>>>>>> + > >>>>>>> + /* Add devices for each partition */ > >>>>>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { > >>>>>>> + if (part_get_info(desc, part, &info)) > >>>>>>> + continue; > >>>>>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, > >>>>>>> + part); > >>>>>>> + > >>>>>>> + ret = device_bind_driver(parent, "blk_partition", > >>>>>>> + strdup(devname), &dev); > >>>>>>> + if (ret) > >>>>>>> + return ret; > >>>>>>> + > >>>>>>> + part_data = dev_get_uclass_plat(dev); > >>>>>>> + part_data->partnum = part; > >>>>>>> + part_data->gpt_part_info = info; > >>>>>>> + count++; > >>>>>>> + > >>>>>>> + device_probe(dev); > >>>>>>> + } > >>>>>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); > >>>>>>> + > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> static int blk_post_probe(struct udevice *dev) > >>>>>>> { > >>>>>>> if (IS_ENABLED(CONFIG_PARTITIONS) && > >>>>>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { > >>>>>>> .post_probe = blk_post_probe, > >>>>>>> .per_device_plat_auto = sizeof(struct blk_desc), > >>>>>>> }; > >>>>>>> + > >>>>>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, > >>>>>>> + lbaint_t blkcnt, void *buffer) > >>>>>>> +{ > >>>>>>> + struct udevice *parent; > >>>>>>> + struct disk_part *part; > >>>>>>> + const struct blk_ops *ops; > >>>>>>> + > >>>>>>> + parent = dev_get_parent(dev); > >>>>>> > >>>>>> What device type will the parent have if it is a eMMC hardware partition? > >>>>>> > >>>>>>> + ops = blk_get_ops(parent); > >>>>>>> + if (!ops->read) > >>>>>>> + return -ENOSYS; > >>>>>>> + > >>>>>>> + part = dev_get_uclass_plat(dev); > >>>>>> > >>>>>> You should check that we do not access the block device past the > >>>>>> partition end: > >>>>> > >>>>> Yes, I will fix all of checks. > >>>>> > >>>>>> struct blk_desc *desc = dev_get_uclass_plat(parent); > >>>>>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) > >>>>>> return -EFAULT. > >>>>>> > >>>>>>> + start += part->gpt_part_info.start; > >>>> > >>>> A better solution is: > >>>> if (start >= part->gpt_part_info.size) > >>>> return 0; > >>>> > >>>> if ((start + blkcnt) > part->gpt_part_info.size) > >>>> blkcnt = part->gpt_part_info.size - start; > >>>> start += part->gpt_part_info.start; > >>>> instead of returning -EFAULT. > >>>> (note that start and blkcnt are in "block".) > >>> > >>> What is your motivation to support an illegal access? > >>> > >>> We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The > >>> ReadBlocks() and WriteBlocks() services must return > >>> EFI_INVALID_PARAMETER if the read request contains LBAs that are not > >>> valid. > >> > >> I interpreted that 'LBA' was the third parameter to ReadBlocks API, > >> and that if the starting block is out of partition region, we should > >> return an error (and if not, we still want to trim IO request to fit > >> into partition size as other OS's API like linux does). > >> Do you think it's incorrect? > > > > [..] > > > > Related to this patch I think that the partition type should be really > > be a child of the media device: > > > > - MMC > > |- BLK > > |- PARTITION > > |- BLK > > |- PARTITION > > |- BLK > > |- PARTITION > > |- BLK > > > > It seems more natural to me that putting the partitions under the > > top-level BLK device, so that BLK remains a 'terminal' device. > > > > The partition uclass is different from BLK, of course. It could > > contain information about the partition such as its partition number > > and UUID. > > Do you mean hardware partition here? Otherwise I would not know what BLK > should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Note that for eMMC devices, hardware partitions are different from partition-table partitions. If you boot a system with an eMMC device up in Linux you typically get mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb, each of which are hardware partitions. It gets tricky in U-Boot in that you can access each of these with 'mmc dev N M' where M defaults to 0 and is the user partition (mmcblkN), 1/2 are boot0/boot1 and 3 is the rpmb area. The 'mmc' command also allows, when possible and implemented, configuring these partitions, again to the extent allowed, documented and implemented.
Thank you. That is exactly what I tried to mention in my reply at "part: call part_init() in blk_get_device_by_str() only for MMC"
OK so it sounds like we agree that hwpartition and partition are different things.
Yes. Please note, IIUC, that
- MMC hw partitions on a device are mapped to one udevice, differentiating them by blk_desc->hwpart.
- Each NVME namespace on a device is mapped to a different udevice with a different blk_desc->devnum (and nvme_dev->ns_id).
- Each UFS partition (or which is, I suppose, equivalent to scsi LUN) on a device is mapped to a different udevice with a different blk_desc->devnum (and blk_desc->lun).
So even though those type of devices have some kind of hardware partitions, they are modelled differently in U-Boot. (Obviously, I might be wrong here as I'm not quite familiar yet.)
---8<--- # On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). --->8---
The problem with the current U-Boot driver model is that all of "mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb" will be linked to the same udevice. We have to do "mmc dev N M" or call blk_select_hwpart[_devnum]() to distinguish them.
Here's our chance to rethink this. What should the device hierarchy be for an MMC device? I made a proposal further up the thread.
Well,
On Mon, Oct 11, 2021 at 11:41:02AM -0600, Simon Glass wrote:
On Mon, 11 Oct 2021 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
> [..]
> Related to this patch I think that the partition type should be really > be a child of the media device: > > - MMC > |- BLK > |- PARTITION > |- BLK > |- PARTITION > |- BLK > |- PARTITION > |- BLK > > It seems more natural to me that putting the partitions under the > top-level BLK device, so that BLK remains a 'terminal' device. > > The partition uclass is different from BLK, of course. It could > contain information about the partition such as its partition number > and UUID.
Yeah, but there is always 1-to-1 mapping between a partition and a block (for a partition), so I still wonder whether it makes sense to model partitions in the way above.
Alternatively, the following hierarchy also makes some sense. (This is not what I have in my RFC though.)
- MMC
|- BLK (whole disk with part=0) |- BLK (partition 1) |- BLK (partition 2) |- BLK (partition 3)
or
- MMC
|- DISK (whole disk) ||- BLK (partition 0) ||- BLK (partition 1) ||- BLK (partition 2) ||- BLK (partition 3)
Here MMC: provides read/write operations (via blk_ops) DISK: holds a geometry of a whole disk and other info BLK: partition info (+ blk_ops + geo) (part=0 means a while disk)
Where does this leave hwpart? Are we giving up on that?
No, not at all :) I'm thinking of dealing with hw partitions as independent BLK devices. This is already true for NVME (namespaces) and UFS (LUNs)(not sure, though). For MMC, struct blk_desc has 'hwpart' field to indicate a hw partition and Apparently, it will be easy to have different BLK devices with different hwpart's. (Then we will have to add a probe function for hw partitions.)
Both of these make some sense to me, although I'm not sure what the second one buys us. Can you explain that? Is it to deal with hwpart?
So,
- MMC (bus controller) |- BLK (device/hw partition:user data) ||- DISK (partition 0 == a whole device) ||- DISK (partition 1) ||- DISK (partition 2) ||- DISK (partition 3) |- BLK (device/hw partition:boot0) ||- DISK (partition 0 == a whole device) |- BLK (device/hw partition:boot0) ||- DISK (partition 0 == a whole device) |- BLK (device/hw partition:rpmb) -- this is NOT a 'block' device, though. ||- DISK (partition 0 == a whole device)
MMC: provides access methods (via blk_ops) BLK: represents a physical device and holds a geometry of the whole device and other info DISK: block-access entities with partition info (part=0 means a while disk)
(MMC, BLK are of current implementation.)
To avoid confusion, UCLASS_PARTITION is renamed to UCLASS_DISK with a little modified semantics. The name can be seen aligned with 'disk/' directory for sw partitions. Partition 0 expectedly behaves in the same way as an existing BLK.
With this scheme, I assume that we should thoroughly use new interfaces dev_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buffer); dev_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buffer); for block-level operations with DISK devices. ^^^^
The legacy interfaces with blk_desc's in BLK devices: blk_dread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer) blk_dwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer)l are to be retained, at least, during the transition period (mostly for existing filesystems and commands).
The name 'disk' is pretty awful though, these days.
Think so? Honestly, I'd like to rename BLK to DISK (or BLK_MEDIA) and rename DISK to BLK to reflect their rolls :)
If we want to iterate through all the partition tables across all devices, we could do that with a partition uclass. We could support different types of partition (s/w and h/w) with the same device driver.
I think conceptually it is cleaner to have a partition uclass but I do agree that it corresponds 100% to BLK, so maybe there is little value in practice. But which device holds the partition table in its dev_get_priv()?
Do you think that some device should have "partition table" info in its inner data structure of udevice? BLK-DISK relationship can represent a partition table in some way, and MMC-BLK can model hw partitioning.
Thanks, -Takahiro Akashi
Do you mean hardware partition here? Otherwise I would not know what BLK should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I presume you meant to include a BLK device under each PARTITION?
But anyway, I was more thinking of this:
MMC | HWPARTITION rpmb || BLK whole rpmb || PARTITION 1 ||| BLK || PARTITION 2 ||| BLK || PARTITION 3
Do we have any reason to model a RPMB partition as a block device? For linux, at least, mmcblkrpmb looks to be a character device.
||| BLK | HWPARTITION boot0 || BLK (maybe have PARTITION in here too?
I don't know how boot partitions are used on a production system. It's unlikely to have partitions on them given the purpose of "boot" partitions?
That's true. So likely they will not be used.
| HWPARTITION boot1 (maybe have PARTITION in here too? || BLK
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
I'm not quite sure about the terminology here. I'm not even talking about UEFI, really, just how best to model this stuff in U-Boot.
In UEFI world, each efi_disk has its own device path to identify the device. For example, here is a text representation of device path for a scsi disk partition: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/HD(1,GPT,ce86c5a7-b32a-488f-a346-88fe698e0edc,0x22,0x4c2a)
which is set to be created from a corresponding udevice (more strictly blkc_desc + part).
So the issue Heinrich raised here is a matter of implementation of this conversion (software partitions, and SCSI channels?) as well as a modeling for some device type on U-Boot, i.e. MMC hardware partitions.
Yes I see that. It's just that we should get our house in order first, since these discussions didn't happen when the EFI layer was written 6 years ago. If we have a good model for partitions (not just block devices) in U-Boot then it should be easier to map EFI onto it.
Regards, Simon
-Takahiro Akashi
In U-Boot, UCLASS_SCSI should be a SCSI controller, not a device, right? I'm a little worried it is not modelled correctly. After all, what is the parent of a SCSI device?
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Regards, Simon
When it comes to UEFI, I hope we can currently support hw partitions in this way: => efidebug add boot -b 1 FOO mmc 0.1 /foo.bin "" (".1" is a key, I have never tried this syntax though.)
But probably its device path won't be properly formatted as expected as Heinrich suggested.
-Takahiro Akashi
In terms of modeling, this is akin to how if you use a USB card reader that supports 4 different form-factor cards, you can end up with 4 different devices showing up in Linux (if you have one of the nice card readers that supports multiple cards at once).
-- Tom
Regards, Simon

On 10/28/21 10:52, AKASHI Takahiro wrote:
Hi Simon,
I'd like to resume this discussion.
On Thu, Oct 14, 2021 at 02:55:36PM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 14 Oct 2021 at 02:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Wed, Oct 13, 2021 at 12:05:58PM -0600, Simon Glass wrote:
Hi Takahiro,
On Tue, 12 Oct 2021 at 19:32, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Tue, Oct 12, 2021 at 11:14:17AM -0400, Tom Rini wrote:
On Mon, Oct 11, 2021 at 10:14:00AM -0600, Simon Glass wrote: > Hi Heinrich, > > On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >> >> >> >> On 10/11/21 16:54, Simon Glass wrote: >>> Hi Takahiro, >>> >>> On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro >>> takahiro.akashi@linaro.org wrote: >>>> >>>> Heinrich, >>>> >>>> On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote: >>>>> >>>>> >>>>> On 10/8/21 02:51, AKASHI Takahiro wrote: >>>>>> On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >>>>>>> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>>>>>>> >>>>>>>> >>>>>>>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>>>>>>> UCLASS_PARTITION device will be created as a child node of >>>>>>>>> UCLASS_BLK device. >>>>>>>>> >>>>>>>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>>>>>>> --- >>>>>>>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>>>>>>> include/blk.h | 9 +++ >>>>>>>>> include/dm/uclass-id.h | 1 + >>>>>>>>> 3 files changed, 121 insertions(+) >>>>>>>>> >>>>>>>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>>>>>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>>>>>>> --- a/drivers/block/blk-uclass.c >>>>>>>>> +++ b/drivers/block/blk-uclass.c >>>>>>>>> @@ -12,6 +12,7 @@ >>>>>>>>> #include <log.h> >>>>>>>>> #include <malloc.h> >>>>>>>>> #include <part.h> >>>>>>>>> +#include <string.h> >>>>>>>>> #include <dm/device-internal.h> >>>>>>>>> #include <dm/lists.h> >>>>>>>>> #include <dm/uclass-internal.h> >>>>>>>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>>>>>>> return 0; >>>>>>>>> } >>>>>>>>> >>>>>>>>> +int blk_create_partitions(struct udevice *parent) >>>>>>>>> +{ >>>>>>>>> + int part, count; >>>>>>>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>>>>>> + struct disk_partition info; >>>>>>>>> + struct disk_part *part_data; >>>>>>>>> + char devname[32]; >>>>>>>>> + struct udevice *dev; >>>>>>>>> + int ret; >>>>>>>>> + >>>>>>>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>>>>>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>>>>>>> + return 0; >>>>>>>>> + >>>>>>>>> + /* Add devices for each partition */ >>>>>>>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>>>>>>> + if (part_get_info(desc, part, &info)) >>>>>>>>> + continue; >>>>>>>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>>>>>>> + part); >>>>>>>>> + >>>>>>>>> + ret = device_bind_driver(parent, "blk_partition", >>>>>>>>> + strdup(devname), &dev); >>>>>>>>> + if (ret) >>>>>>>>> + return ret; >>>>>>>>> + >>>>>>>>> + part_data = dev_get_uclass_plat(dev); >>>>>>>>> + part_data->partnum = part; >>>>>>>>> + part_data->gpt_part_info = info; >>>>>>>>> + count++; >>>>>>>>> + >>>>>>>>> + device_probe(dev); >>>>>>>>> + } >>>>>>>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>>>>>>> + >>>>>>>>> + return 0; >>>>>>>>> +} >>>>>>>>> + >>>>>>>>> static int blk_post_probe(struct udevice *dev) >>>>>>>>> { >>>>>>>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>>>>>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>>>>>>> .post_probe = blk_post_probe, >>>>>>>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>>>>>>> }; >>>>>>>>> + >>>>>>>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>>>>>>> + lbaint_t blkcnt, void *buffer) >>>>>>>>> +{ >>>>>>>>> + struct udevice *parent; >>>>>>>>> + struct disk_part *part; >>>>>>>>> + const struct blk_ops *ops; >>>>>>>>> + >>>>>>>>> + parent = dev_get_parent(dev); >>>>>>>> >>>>>>>> What device type will the parent have if it is a eMMC hardware partition? >>>>>>>> >>>>>>>>> + ops = blk_get_ops(parent); >>>>>>>>> + if (!ops->read) >>>>>>>>> + return -ENOSYS; >>>>>>>>> + >>>>>>>>> + part = dev_get_uclass_plat(dev); >>>>>>>> >>>>>>>> You should check that we do not access the block device past the >>>>>>>> partition end: >>>>>>> >>>>>>> Yes, I will fix all of checks. >>>>>>> >>>>>>>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>>>>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>>>>>>> return -EFAULT. >>>>>>>> >>>>>>>>> + start += part->gpt_part_info.start; >>>>>> >>>>>> A better solution is: >>>>>> if (start >= part->gpt_part_info.size) >>>>>> return 0; >>>>>> >>>>>> if ((start + blkcnt) > part->gpt_part_info.size) >>>>>> blkcnt = part->gpt_part_info.size - start; >>>>>> start += part->gpt_part_info.start; >>>>>> instead of returning -EFAULT. >>>>>> (note that start and blkcnt are in "block".) >>>>> >>>>> What is your motivation to support an illegal access? >>>>> >>>>> We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The >>>>> ReadBlocks() and WriteBlocks() services must return >>>>> EFI_INVALID_PARAMETER if the read request contains LBAs that are not >>>>> valid. >>>> >>>> I interpreted that 'LBA' was the third parameter to ReadBlocks API, >>>> and that if the starting block is out of partition region, we should >>>> return an error (and if not, we still want to trim IO request to fit >>>> into partition size as other OS's API like linux does). >>>> Do you think it's incorrect? >>> >>> [..] >>> >>> Related to this patch I think that the partition type should be really >>> be a child of the media device: >>> >>> - MMC >>> |- BLK >>> |- PARTITION >>> |- BLK >>> |- PARTITION >>> |- BLK >>> |- PARTITION >>> |- BLK >>> >>> It seems more natural to me that putting the partitions under the >>> top-level BLK device, so that BLK remains a 'terminal' device. >>> >>> The partition uclass is different from BLK, of course. It could >>> contain information about the partition such as its partition number >>> and UUID. >> >> Do you mean hardware partition here? Otherwise I would not know what BLK >> should model. > > I mean that (I think) we should not use BLK to model partitions. A BLK > should just be a block device. > > I don't see any difference between a partition and a hardware > partition. We presumably end up with a hierarchy though. Do we need a > HWPARTITION uclass so we can handle the hardware partitions > differently?
Note that for eMMC devices, hardware partitions are different from partition-table partitions. If you boot a system with an eMMC device up in Linux you typically get mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb, each of which are hardware partitions. It gets tricky in U-Boot in that you can access each of these with 'mmc dev N M' where M defaults to 0 and is the user partition (mmcblkN), 1/2 are boot0/boot1 and 3 is the rpmb area. The 'mmc' command also allows, when possible and implemented, configuring these partitions, again to the extent allowed, documented and implemented.
Thank you. That is exactly what I tried to mention in my reply at "part: call part_init() in blk_get_device_by_str() only for MMC"
OK so it sounds like we agree that hwpartition and partition are different things.
Yes. Please note, IIUC, that
- MMC hw partitions on a device are mapped to one udevice, differentiating them by blk_desc->hwpart.
- Each NVME namespace on a device is mapped to a different udevice with a different blk_desc->devnum (and nvme_dev->ns_id).
- Each UFS partition (or which is, I suppose, equivalent to scsi LUN) on a device is mapped to a different udevice with a different blk_desc->devnum (and blk_desc->lun).
So even though those type of devices have some kind of hardware partitions, they are modelled differently in U-Boot. (Obviously, I might be wrong here as I'm not quite familiar yet.)
---8<--- # On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). --->8---
The problem with the current U-Boot driver model is that all of "mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb" will be linked to the same udevice. We have to do "mmc dev N M" or call blk_select_hwpart[_devnum]() to distinguish them.
Here's our chance to rethink this. What should the device hierarchy be for an MMC device? I made a proposal further up the thread.
Well,
On Mon, Oct 11, 2021 at 11:41:02AM -0600, Simon Glass wrote:
On Mon, 11 Oct 2021 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
>> [..]
>> Related to this patch I think that the partition type should be really >> be a child of the media device: >> >> - MMC >> |- BLK >> |- PARTITION >> |- BLK >> |- PARTITION >> |- BLK >> |- PARTITION >> |- BLK >> >> It seems more natural to me that putting the partitions under the >> top-level BLK device, so that BLK remains a 'terminal' device. >> >> The partition uclass is different from BLK, of course. It could >> contain information about the partition such as its partition number >> and UUID.
Yeah, but there is always 1-to-1 mapping between a partition and a block (for a partition), so I still wonder whether it makes sense to model partitions in the way above.
Alternatively, the following hierarchy also makes some sense. (This is not what I have in my RFC though.)
- MMC
|- BLK (whole disk with part=0) |- BLK (partition 1) |- BLK (partition 2) |- BLK (partition 3)
or
- MMC
|- DISK (whole disk) ||- BLK (partition 0) ||- BLK (partition 1) ||- BLK (partition 2) ||- BLK (partition 3)
Here MMC: provides read/write operations (via blk_ops) DISK: holds a geometry of a whole disk and other info BLK: partition info (+ blk_ops + geo) (part=0 means a while disk)
Where does this leave hwpart? Are we giving up on that?
No, not at all :) I'm thinking of dealing with hw partitions as independent BLK devices. This is already true for NVME (namespaces) and UFS (LUNs)(not sure, though). For MMC, struct blk_desc has 'hwpart' field to indicate a hw partition and Apparently, it will be easy to have different BLK devices with different hwpart's. (Then we will have to add a probe function for hw partitions.)
Both of these make some sense to me, although I'm not sure what the second one buys us. Can you explain that? Is it to deal with hwpart?
So,
- MMC (bus controller)
|- BLK (device/hw partition:user data) ||- DISK (partition 0 == a whole device) ||- DISK (partition 1) ||- DISK (partition 2) ||- DISK (partition 3) |- BLK (device/hw partition:boot0) ||- DISK (partition 0 == a whole device) |- BLK (device/hw partition:boot0) ||- DISK (partition 0 == a whole device) |- BLK (device/hw partition:rpmb) -- this is NOT a 'block' device, though. ||- DISK (partition 0 == a whole device)
MMC: provides access methods (via blk_ops) BLK: represents a physical device and holds a geometry of the whole device and other info DISK: block-access entities with partition info (part=0 means a while disk) (MMC, BLK are of current implementation.)
Could you, please, add the path from the root, devices without hardware partitions (e.g. IDE, SATA), and devices with LUNs (SCSI) to the tree. Please, also add the device-tree nodes. This will allow us to see the whole picture, and observe how UEFI device paths and the DM tree are matched.
To avoid confusion, UCLASS_PARTITION is renamed to UCLASS_DISK with a little modified semantics. The name can be seen aligned with 'disk/'
Renaming UCLASS_PARTITION to UCLASS_DISK is very confusing. A disk to me is a block device which may have partitions.
directory for sw partitions. Partition 0 expectedly behaves in the same way as an existing BLK.
It will expose block IO and it may expose a file system. The same is valid for the true partitions.
A block device does not expose a file system.
So partition 0 just behaves at it always did in U-Boot.
With this scheme, I assume that we should thoroughly use new interfaces dev_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buffer); dev_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buffer); for block-level operations with DISK devices. ^^^^
The legacy interfaces with blk_desc's in BLK devices: blk_dread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer) blk_dwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer)l are to be retained, at least, during the transition period (mostly for existing filesystems and commands).
The name 'disk' is pretty awful though, these days.
Think so? Honestly, I'd like to rename BLK to DISK (or BLK_MEDIA) and rename DISK to BLK to reflect their rolls :)
Block devices are not necessarily disks. Think of a tape device for instance or a RAM based block device. So renaming BLK to DISK is confusing.
If we want to iterate through all the partition tables across all devices, we could do that with a partition uclass. We could support different types of partition (s/w and h/w) with the same device driver.
Why? You can simply traverse the list of udevices of type SW_PARTITION. There is not need to walk the tree.
In the tree above you made them HW and SW partions different uclasses. For each uclass create a separate driver.
Best regards
Heinrich
I think conceptually it is cleaner to have a partition uclass but I do agree that it corresponds 100% to BLK, so maybe there is little value in practice. But which device holds the partition table in its dev_get_priv()?
Do you think that some device should have "partition table" info in its inner data structure of udevice? BLK-DISK relationship can represent a partition table in some way, and MMC-BLK can model hw partitioning.
Thanks, -Takahiro Akashi
> Do you mean hardware partition here? Otherwise I would not know what BLK > should model.
I mean that (I think) we should not use BLK to model partitions. A BLK should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I presume you meant to include a BLK device under each PARTITION?
But anyway, I was more thinking of this:
MMC | HWPARTITION rpmb || BLK whole rpmb || PARTITION 1 ||| BLK || PARTITION 2 ||| BLK || PARTITION 3
Do we have any reason to model a RPMB partition as a block device? For linux, at least, mmcblkrpmb looks to be a character device.
||| BLK | HWPARTITION boot0 || BLK (maybe have PARTITION in here too?
I don't know how boot partitions are used on a production system. It's unlikely to have partitions on them given the purpose of "boot" partitions?
That's true. So likely they will not be used.
| HWPARTITION boot1 (maybe have PARTITION in here too? || BLK
I don't see any difference between a partition and a hardware partition. We presumably end up with a hierarchy though. Do we need a HWPARTITION uclass so we can handle the hardware partitions differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
I'm not quite sure about the terminology here. I'm not even talking about UEFI, really, just how best to model this stuff in U-Boot.
In UEFI world, each efi_disk has its own device path to identify the device. For example, here is a text representation of device path for a scsi disk partition: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/HD(1,GPT,ce86c5a7-b32a-488f-a346-88fe698e0edc,0x22,0x4c2a)
which is set to be created from a corresponding udevice (more strictly blkc_desc + part).
So the issue Heinrich raised here is a matter of implementation of this conversion (software partitions, and SCSI channels?) as well as a modeling for some device type on U-Boot, i.e. MMC hardware partitions.
Yes I see that. It's just that we should get our house in order first, since these discussions didn't happen when the EFI layer was written 6 years ago. If we have a good model for partitions (not just block devices) in U-Boot then it should be easier to map EFI onto it.
Regards, Simon
-Takahiro Akashi
In U-Boot, UCLASS_SCSI should be a SCSI controller, not a device, right? I'm a little worried it is not modelled correctly. After all, what is the parent of a SCSI device?
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Regards, Simon
When it comes to UEFI, I hope we can currently support hw partitions in this way: => efidebug add boot -b 1 FOO mmc 0.1 /foo.bin "" (".1" is a key, I have never tried this syntax though.)
But probably its device path won't be properly formatted as expected as Heinrich suggested.
-Takahiro Akashi
In terms of modeling, this is akin to how if you use a USB card reader that supports 4 different form-factor cards, you can end up with 4 different devices showing up in Linux (if you have one of the nice card readers that supports multiple cards at once).
-- Tom
Regards, Simon

Hi,
On Thu, 28 Oct 2021 at 04:47, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/28/21 10:52, AKASHI Takahiro wrote:
Hi Simon,
I'd like to resume this discussion.
On Thu, Oct 14, 2021 at 02:55:36PM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 14 Oct 2021 at 02:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Wed, Oct 13, 2021 at 12:05:58PM -0600, Simon Glass wrote:
Hi Takahiro,
On Tue, 12 Oct 2021 at 19:32, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Tue, Oct 12, 2021 at 11:14:17AM -0400, Tom Rini wrote: > On Mon, Oct 11, 2021 at 10:14:00AM -0600, Simon Glass wrote: >> Hi Heinrich, >> >> On Mon, 11 Oct 2021 at 09:02, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >>> >>> >>> >>> On 10/11/21 16:54, Simon Glass wrote: >>>> Hi Takahiro, >>>> >>>> On Sun, 10 Oct 2021 at 20:29, AKASHI Takahiro >>>> takahiro.akashi@linaro.org wrote: >>>>> >>>>> Heinrich, >>>>> >>>>> On Fri, Oct 08, 2021 at 10:23:52AM +0200, Heinrich Schuchardt wrote: >>>>>> >>>>>> >>>>>> On 10/8/21 02:51, AKASHI Takahiro wrote: >>>>>>> On Mon, Oct 04, 2021 at 12:27:59PM +0900, AKASHI Takahiro wrote: >>>>>>>> On Fri, Oct 01, 2021 at 11:30:37AM +0200, Heinrich Schuchardt wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>> On 10/1/21 07:01, AKASHI Takahiro wrote: >>>>>>>>>> UCLASS_PARTITION device will be created as a child node of >>>>>>>>>> UCLASS_BLK device. >>>>>>>>>> >>>>>>>>>> Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org >>>>>>>>>> --- >>>>>>>>>> drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ >>>>>>>>>> include/blk.h | 9 +++ >>>>>>>>>> include/dm/uclass-id.h | 1 + >>>>>>>>>> 3 files changed, 121 insertions(+) >>>>>>>>>> >>>>>>>>>> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >>>>>>>>>> index 83682dcc181a..dd7f3c0fe31e 100644 >>>>>>>>>> --- a/drivers/block/blk-uclass.c >>>>>>>>>> +++ b/drivers/block/blk-uclass.c >>>>>>>>>> @@ -12,6 +12,7 @@ >>>>>>>>>> #include <log.h> >>>>>>>>>> #include <malloc.h> >>>>>>>>>> #include <part.h> >>>>>>>>>> +#include <string.h> >>>>>>>>>> #include <dm/device-internal.h> >>>>>>>>>> #include <dm/lists.h> >>>>>>>>>> #include <dm/uclass-internal.h> >>>>>>>>>> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) >>>>>>>>>> return 0; >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> +int blk_create_partitions(struct udevice *parent) >>>>>>>>>> +{ >>>>>>>>>> + int part, count; >>>>>>>>>> + struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>>>>>>> + struct disk_partition info; >>>>>>>>>> + struct disk_part *part_data; >>>>>>>>>> + char devname[32]; >>>>>>>>>> + struct udevice *dev; >>>>>>>>>> + int ret; >>>>>>>>>> + >>>>>>>>>> + if (!CONFIG_IS_ENABLED(PARTITIONS) || >>>>>>>>>> + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) >>>>>>>>>> + return 0; >>>>>>>>>> + >>>>>>>>>> + /* Add devices for each partition */ >>>>>>>>>> + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { >>>>>>>>>> + if (part_get_info(desc, part, &info)) >>>>>>>>>> + continue; >>>>>>>>>> + snprintf(devname, sizeof(devname), "%s:%d", parent->name, >>>>>>>>>> + part); >>>>>>>>>> + >>>>>>>>>> + ret = device_bind_driver(parent, "blk_partition", >>>>>>>>>> + strdup(devname), &dev); >>>>>>>>>> + if (ret) >>>>>>>>>> + return ret; >>>>>>>>>> + >>>>>>>>>> + part_data = dev_get_uclass_plat(dev); >>>>>>>>>> + part_data->partnum = part; >>>>>>>>>> + part_data->gpt_part_info = info; >>>>>>>>>> + count++; >>>>>>>>>> + >>>>>>>>>> + device_probe(dev); >>>>>>>>>> + } >>>>>>>>>> + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); >>>>>>>>>> + >>>>>>>>>> + return 0; >>>>>>>>>> +} >>>>>>>>>> + >>>>>>>>>> static int blk_post_probe(struct udevice *dev) >>>>>>>>>> { >>>>>>>>>> if (IS_ENABLED(CONFIG_PARTITIONS) && >>>>>>>>>> @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { >>>>>>>>>> .post_probe = blk_post_probe, >>>>>>>>>> .per_device_plat_auto = sizeof(struct blk_desc), >>>>>>>>>> }; >>>>>>>>>> + >>>>>>>>>> +static ulong blk_part_read(struct udevice *dev, lbaint_t start, >>>>>>>>>> + lbaint_t blkcnt, void *buffer) >>>>>>>>>> +{ >>>>>>>>>> + struct udevice *parent; >>>>>>>>>> + struct disk_part *part; >>>>>>>>>> + const struct blk_ops *ops; >>>>>>>>>> + >>>>>>>>>> + parent = dev_get_parent(dev); >>>>>>>>> >>>>>>>>> What device type will the parent have if it is a eMMC hardware partition? >>>>>>>>> >>>>>>>>>> + ops = blk_get_ops(parent); >>>>>>>>>> + if (!ops->read) >>>>>>>>>> + return -ENOSYS; >>>>>>>>>> + >>>>>>>>>> + part = dev_get_uclass_plat(dev); >>>>>>>>> >>>>>>>>> You should check that we do not access the block device past the >>>>>>>>> partition end: >>>>>>>> >>>>>>>> Yes, I will fix all of checks. >>>>>>>> >>>>>>>>> struct blk_desc *desc = dev_get_uclass_plat(parent); >>>>>>>>> if ((start + blkcnt) * desc->blksz < part->gpt_part_info.blksz) >>>>>>>>> return -EFAULT. >>>>>>>>> >>>>>>>>>> + start += part->gpt_part_info.start; >>>>>>> >>>>>>> A better solution is: >>>>>>> if (start >= part->gpt_part_info.size) >>>>>>> return 0; >>>>>>> >>>>>>> if ((start + blkcnt) > part->gpt_part_info.size) >>>>>>> blkcnt = part->gpt_part_info.size - start; >>>>>>> start += part->gpt_part_info.start; >>>>>>> instead of returning -EFAULT. >>>>>>> (note that start and blkcnt are in "block".) >>>>>> >>>>>> What is your motivation to support an illegal access? >>>>>> >>>>>> We will implement the EFI_BLOCK_IO_PROTOCOL based on this function. The >>>>>> ReadBlocks() and WriteBlocks() services must return >>>>>> EFI_INVALID_PARAMETER if the read request contains LBAs that are not >>>>>> valid. >>>>> >>>>> I interpreted that 'LBA' was the third parameter to ReadBlocks API, >>>>> and that if the starting block is out of partition region, we should >>>>> return an error (and if not, we still want to trim IO request to fit >>>>> into partition size as other OS's API like linux does). >>>>> Do you think it's incorrect? >>>> >>>> [..] >>>> >>>> Related to this patch I think that the partition type should be really >>>> be a child of the media device: >>>> >>>> - MMC >>>> |- BLK >>>> |- PARTITION >>>> |- BLK >>>> |- PARTITION >>>> |- BLK >>>> |- PARTITION >>>> |- BLK >>>> >>>> It seems more natural to me that putting the partitions under the >>>> top-level BLK device, so that BLK remains a 'terminal' device. >>>> >>>> The partition uclass is different from BLK, of course. It could >>>> contain information about the partition such as its partition number >>>> and UUID. >>> >>> Do you mean hardware partition here? Otherwise I would not know what BLK >>> should model. >> >> I mean that (I think) we should not use BLK to model partitions. A BLK >> should just be a block device. >> >> I don't see any difference between a partition and a hardware >> partition. We presumably end up with a hierarchy though. Do we need a >> HWPARTITION uclass so we can handle the hardware partitions >> differently? > > Note that for eMMC devices, hardware partitions are different from > partition-table partitions. If you boot a system with an eMMC device up > in Linux you typically get mmcblkN, mmcblkNboot0, mmcblkNboot1 and > mmcblkNrpmb, each of which are hardware partitions. It gets tricky in > U-Boot in that you can access each of these with 'mmc dev N M' where M > defaults to 0 and is the user partition (mmcblkN), 1/2 are boot0/boot1 > and 3 is the rpmb area. The 'mmc' command also allows, when possible > and implemented, configuring these partitions, again to the extent > allowed, documented and implemented.
Thank you. That is exactly what I tried to mention in my reply at "part: call part_init() in blk_get_device_by_str() only for MMC"
OK so it sounds like we agree that hwpartition and partition are different things.
Yes. Please note, IIUC, that
- MMC hw partitions on a device are mapped to one udevice, differentiating them by blk_desc->hwpart.
- Each NVME namespace on a device is mapped to a different udevice with a different blk_desc->devnum (and nvme_dev->ns_id).
- Each UFS partition (or which is, I suppose, equivalent to scsi LUN) on a device is mapped to a different udevice with a different blk_desc->devnum (and blk_desc->lun).
So even though those type of devices have some kind of hardware partitions, they are modelled differently in U-Boot. (Obviously, I might be wrong here as I'm not quite familiar yet.)
---8<--- # On the other hand, we have to explicitly switch "hw partitions" # with blk_select_hwpart_devnum() on MMC devices even though we use # the *same* udevice(blk_desc). --->8---
The problem with the current U-Boot driver model is that all of "mmcblkN, mmcblkNboot0, mmcblkNboot1 and mmcblkNrpmb" will be linked to the same udevice. We have to do "mmc dev N M" or call blk_select_hwpart[_devnum]() to distinguish them.
Here's our chance to rethink this. What should the device hierarchy be for an MMC device? I made a proposal further up the thread.
Well,
On Mon, Oct 11, 2021 at 11:41:02AM -0600, Simon Glass wrote:
On Mon, 11 Oct 2021 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
>>> [..]
>>> Related to this patch I think that the partition type should be really >>> be a child of the media device: >>> >>> - MMC >>> |- BLK >>> |- PARTITION >>> |- BLK >>> |- PARTITION >>> |- BLK >>> |- PARTITION >>> |- BLK >>> >>> It seems more natural to me that putting the partitions under the >>> top-level BLK device, so that BLK remains a 'terminal' device. >>> >>> The partition uclass is different from BLK, of course. It could >>> contain information about the partition such as its partition number >>> and UUID.
Yeah, but there is always 1-to-1 mapping between a partition and a block (for a partition), so I still wonder whether it makes sense to model partitions in the way above.
Alternatively, the following hierarchy also makes some sense. (This is not what I have in my RFC though.)
- MMC
|- BLK (whole disk with part=0) |- BLK (partition 1) |- BLK (partition 2) |- BLK (partition 3)
or
- MMC
|- DISK (whole disk) ||- BLK (partition 0) ||- BLK (partition 1) ||- BLK (partition 2) ||- BLK (partition 3)
Here MMC: provides read/write operations (via blk_ops) DISK: holds a geometry of a whole disk and other info BLK: partition info (+ blk_ops + geo) (part=0 means a while disk)
Where does this leave hwpart? Are we giving up on that?
No, not at all :) I'm thinking of dealing with hw partitions as independent BLK devices. This is already true for NVME (namespaces) and UFS (LUNs)(not sure, though). For MMC, struct blk_desc has 'hwpart' field to indicate a hw partition and Apparently, it will be easy to have different BLK devices with different hwpart's. (Then we will have to add a probe function for hw partitions.)
Both of these make some sense to me, although I'm not sure what the second one buys us. Can you explain that? Is it to deal with hwpart?
So,
- MMC (bus controller)
|- BLK (device/hw partition:user data) ||- DISK (partition 0 == a whole device) ||- DISK (partition 1) ||- DISK (partition 2) ||- DISK (partition 3) |- BLK (device/hw partition:boot0) ||- DISK (partition 0 == a whole device) |- BLK (device/hw partition:boot0) ||- DISK (partition 0 == a whole device) |- BLK (device/hw partition:rpmb) -- this is NOT a 'block' device, though. ||- DISK (partition 0 == a whole device)
MMC: provides access methods (via blk_ops) BLK: represents a physical device and holds a geometry of the whole device and other info DISK: block-access entities with partition info (part=0 means a while disk) (MMC, BLK are of current implementation.)
I agree with Heinrich that we are better to leave BLK as it is, both in name and meaning. I think maybe I am missing the gist of your argument.
If we use UCLASS_PART, for example, can we have that refer to both s/w and h/w partitions, as Herinch seems to allude to below? What would the picture look like the, and would it get us closer to agreement?
- Simon
Could you, please, add the path from the root, devices without hardware partitions (e.g. IDE, SATA), and devices with LUNs (SCSI) to the tree. Please, also add the device-tree nodes. This will allow us to see the whole picture, and observe how UEFI device paths and the DM tree are matched.
To avoid confusion, UCLASS_PARTITION is renamed to UCLASS_DISK with a little modified semantics. The name can be seen aligned with 'disk/'
Renaming UCLASS_PARTITION to UCLASS_DISK is very confusing. A disk to me is a block device which may have partitions.
directory for sw partitions. Partition 0 expectedly behaves in the same way as an existing BLK.
It will expose block IO and it may expose a file system. The same is valid for the true partitions.
A block device does not expose a file system.
So partition 0 just behaves at it always did in U-Boot.
With this scheme, I assume that we should thoroughly use new interfaces dev_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buffer); dev_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buffer); for block-level operations with DISK devices. ^^^^
The legacy interfaces with blk_desc's in BLK devices: blk_dread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer) blk_dwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer)l are to be retained, at least, during the transition period (mostly for existing filesystems and commands).
The name 'disk' is pretty awful though, these days.
Think so? Honestly, I'd like to rename BLK to DISK (or BLK_MEDIA) and rename DISK to BLK to reflect their rolls :)
Block devices are not necessarily disks. Think of a tape device for instance or a RAM based block device. So renaming BLK to DISK is confusing.
If we want to iterate through all the partition tables across all devices, we could do that with a partition uclass. We could support different types of partition (s/w and h/w) with the same device driver.
Why? You can simply traverse the list of udevices of type SW_PARTITION. There is not need to walk the tree.
In the tree above you made them HW and SW partions different uclasses. For each uclass create a separate driver.
Best regards
Heinrich
I think conceptually it is cleaner to have a partition uclass but I do agree that it corresponds 100% to BLK, so maybe there is little value in practice. But which device holds the partition table in its dev_get_priv()?
Do you think that some device should have "partition table" info in its inner data structure of udevice? BLK-DISK relationship can represent a partition table in some way, and MMC-BLK can model hw partitioning.
Thanks, -Takahiro Akashi
>> Do you mean hardware partition here? Otherwise I would not know what BLK >> should model. > > I mean that (I think) we should not use BLK to model partitions. A BLK > should just be a block device.
That is fine. But this implies that a software partition is the child of a block partition and not the other way round. So the tree should like:
MMC |- BLK (user hardware partition) ||- PARTITION 1 (software partition) ||- PARTITION 2 (software partition) |... ||- PARTITION n (software partition) |- BLK (rpmb hardware partition) |- BLK (boot0 hardware partition) |- BLK (boot1 hardware partition)
I presume you meant to include a BLK device under each PARTITION?
But anyway, I was more thinking of this:
MMC | HWPARTITION rpmb || BLK whole rpmb || PARTITION 1 ||| BLK || PARTITION 2 ||| BLK || PARTITION 3
Do we have any reason to model a RPMB partition as a block device? For linux, at least, mmcblkrpmb looks to be a character device.
||| BLK | HWPARTITION boot0 || BLK (maybe have PARTITION in here too?
I don't know how boot partitions are used on a production system. It's unlikely to have partitions on them given the purpose of "boot" partitions?
That's true. So likely they will not be used.
| HWPARTITION boot1 (maybe have PARTITION in here too? || BLK
> > I don't see any difference between a partition and a hardware > partition. We presumably end up with a hierarchy though. Do we need a > HWPARTITION uclass so we can handle the hardware partitions > differently?
Software partitions are defined and discovered via partition tables. Hardware partitions are defined in a hardware specific way.
All software partitions map to HD() device tree nodes in UEFI. An MMC device maps to an eMMC() node MMC hardware partitions are mapped to Ctrl() nodes by EDK II. We should do the same in U-Boot. An SD-card maps to an SD() node. An NVMe namespace maps to a NVMe() node. An SCSI LUN maps to a Scsi() node. SCSI channels of multiple channel controllers are mapped to Ctrl() nodes.
I'm not quite sure about the terminology here. I'm not even talking about UEFI, really, just how best to model this stuff in U-Boot.
In UEFI world, each efi_disk has its own device path to identify the device. For example, here is a text representation of device path for a scsi disk partition: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/Scsi(0,0)/HD(1,GPT,ce86c5a7-b32a-488f-a346-88fe698e0edc,0x22,0x4c2a)
which is set to be created from a corresponding udevice (more strictly blkc_desc + part).
So the issue Heinrich raised here is a matter of implementation of this conversion (software partitions, and SCSI channels?) as well as a modeling for some device type on U-Boot, i.e. MMC hardware partitions.
Yes I see that. It's just that we should get our house in order first, since these discussions didn't happen when the EFI layer was written 6 years ago. If we have a good model for partitions (not just block devices) in U-Boot then it should be easier to map EFI onto it.
Regards, Simon
-Takahiro Akashi
In U-Boot, UCLASS_SCSI should be a SCSI controller, not a device, right? I'm a little worried it is not modelled correctly. After all, what is the parent of a SCSI device?
The simple file protocol is only provided by HD() nodes and not by nodes representing hardware partitions. If the whole hardware partition is formatted as a file system you would still create a HD() node with partition number 0.
Regards, Simon
When it comes to UEFI, I hope we can currently support hw partitions in this way: => efidebug add boot -b 1 FOO mmc 0.1 /foo.bin "" (".1" is a key, I have never tried this syntax though.)
But probably its device path won't be properly formatted as expected as Heinrich suggested.
-Takahiro Akashi
> In terms of modeling, this is akin to how if you use a USB card reader > that supports 4 different form-factor cards, you can end up with 4 > different devices showing up in Linux (if you have one of the nice card > readers that supports multiple cards at once). > > -- > Tom
Regards, Simon

I agree with Heinrich that we are better to leave BLK as it is, both in name and meaning. I think maybe I am missing the gist of your argument.
If we use UCLASS_PART, for example, can we have that refer to both s/w and h/w partitions, as Herinch seems to allude to below? What would the picture look like the, and would it get us closer to agreement?
In the driver model:
A UCLASS is a class of drivers that share the same interface. A UDEVICE is a logical device that belongs to exactly one UCLASS and is accessed through this UCLASS's interface.
A hardware partition is an object that exposes only a single interface for block IO.
A software partition is an object that may expose two interfaces: one for block IO, the other for file IO.
The UEFI model does not have a problem with this because on a handle you can install as many different protocols as you wish. But U-Boot's driver model only allows a single interface per device. Up to now U-Boot has overcome this limitation by creating child devices for the extra interfaces.
We have the following logical levels:
Controller | Block device | Software Partition| File system ----------------+--------------+-------------------+------------ NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 ATA Controller | ATA-Drive | | SCSI Controller | LUN | | MMC Controller | HW-Partition | | MMC Controller | SD-Card | | USB-Node | USB-Drive | |
In the device tree this could be modeled as:
|-- Controller (UCLASS_CTRL) | |-- Block device / HW Partition (UCLASS_BLK) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device (UCLASS_BLK) | |-- File system (UCLASS_FS)
UCLASS_PARTITION_TABLE would be for the drivers in disk/. UCLASS_FS would be for the drivers in fs/. UCLASS_BLK will be for any objects exposing raw block IO. A software partition does the same. It is created by the partition table driver as child of the partition table udevice.
In this model an eMMC device will not be a UCLASS_BLK device because it does not expose block IO. It is the hardware partition that exposes this interface.
The suggested model will allow a clean description of nested partition tables.
In the UEFI world the software partition and its file system must be mapped to a single handle with device path node type HD(). For the parent block device we may create a child handle with partition number 0 (HD(0)). For the partition table we will not create a handle.
Best regards
Heinrich

On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote:
I agree with Heinrich that we are better to leave BLK as it is, both in name and meaning. I think maybe I am missing the gist of your argument.
If we use UCLASS_PART, for example, can we have that refer to both s/w and h/w partitions, as Herinch seems to allude to below? What would the picture look like the, and would it get us closer to agreement?
In the driver model:
A UCLASS is a class of drivers that share the same interface. A UDEVICE is a logical device that belongs to exactly one UCLASS and is accessed through this UCLASS's interface.
Please be careful about "accessed through" which is a quite confusing expression. I don't always agree with this view.
A hardware partition is an object that exposes only a single interface for block IO.
A software partition is an object that may expose two interfaces: one for block IO, the other for file IO.
Are you talking about UEFI world or U-Boot? Definitely, a hw partitions can provide a file system if you want. It's a matter of usage.
I remember that we had some discussion about whether block devices on UEFI system should always have a (sw) partition table or not. But it is a different topic.
The UEFI model does not have a problem with this because on a handle you can install as many different protocols as you wish. But U-Boot's driver model only allows a single interface per device. Up to now U-Boot has overcome this limitation by creating child devices for the extra interfaces.
We have the following logical levels:
Controller | Block device | Software Partition| File system ----------------+--------------+-------------------+------------ NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 ATA Controller | ATA-Drive | | SCSI Controller | LUN | | MMC Controller | HW-Partition | | MMC Controller | SD-Card | | USB-Node | USB-Drive | |
In the device tree this could be modeled as:
|-- Controller (UCLASS_CTRL) | |-- Block device / HW Partition (UCLASS_BLK) (A) | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device (UCLASS_BLK) | |-- File system (UCLASS_FS)
I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. What is the benefit? (A) and (B) always have 1:1 relationship. I also remember that you claimed that not all efi objects(handles and protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding U-Boot counterparts in our 2019 discussion.
If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, which should support other type of hw partitions as well?
|-- eMMC controller (UCLASS_MMC) | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- Block device / HW Partition:user data (UCLASS_BLK) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device / HW Partition:boot0 (UCLASS_BLK) | |-- Block device / HW Partition:boot1 (UCLASS_BLK) ... | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?)
|-- scsi controller (UCLASS_SCSI) | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) ...
(Here I ignored scsi buses/channels which make things more complicated.)
This kind of complex hierarchy doesn't benefit anybody.
-Takahiro Akashi
UCLASS_PARTITION_TABLE would be for the drivers in disk/. UCLASS_FS would be for the drivers in fs/. UCLASS_BLK will be for any objects exposing raw block IO. A software partition does the same. It is created by the partition table driver as child of the partition table udevice.
In this model an eMMC device will not be a UCLASS_BLK device because it does not expose block IO. It is the hardware partition that exposes this interface.
The suggested model will allow a clean description of nested partition tables.
In the UEFI world the software partition and its file system must be mapped to a single handle with device path node type HD(). For the parent block device we may create a child handle with partition number 0 (HD(0)). For the partition table we will not create a handle.
Best regards
Heinrich

Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org:
On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote:
I agree with Heinrich that we are better to leave BLK as it is, both in name and meaning. I think maybe I am missing the gist of your argument.
If we use UCLASS_PART, for example, can we have that refer to both s/w and h/w partitions, as Herinch seems to allude to below? What would the picture look like the, and would it get us closer to agreement?
In the driver model:
A UCLASS is a class of drivers that share the same interface. A UDEVICE is a logical device that belongs to exactly one UCLASS and is accessed through this UCLASS's interface.
Please be careful about "accessed through" which is a quite confusing expression. I don't always agree with this view.
A hardware partition is an object that exposes only a single interface for block IO.
A software partition is an object that may expose two interfaces: one for block IO, the other for file IO.
Are you talking about UEFI world or U-Boot? Definitely, a hw partitions can provide a file system if you want. It's a matter of usage.
I remember that we had some discussion about whether block devices on UEFI system should always have a (sw) partition table or not. But it is a different topic.
The UEFI model does not have a problem with this because on a handle you can install as many different protocols as you wish. But U-Boot's driver model only allows a single interface per device. Up to now U-Boot has overcome this limitation by creating child devices for the extra interfaces.
We have the following logical levels:
Controller | Block device | Software Partition| File system ----------------+--------------+-------------------+------------ NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 ATA Controller | ATA-Drive | | SCSI Controller | LUN | | MMC Controller | HW-Partition | | MMC Controller | SD-Card | | USB-Node | USB-Drive | |
In the device tree this could be modeled as:
|-- Controller (UCLASS_CTRL) | |-- Block device / HW Partition (UCLASS_BLK) (A) | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device (UCLASS_BLK) | |-- File system (UCLASS_FS)
I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. What is the benefit? (A) and (B) always have 1:1 relationship.
No. You can have a bare device without a partition table.
We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices.
I also remember that you claimed that not all efi objects(handles and protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding U-Boot counterparts in our 2019 discussion.
If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, which should support other type of hw partitions as well?
How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device.
|-- eMMC controller (UCLASS_MMC) | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- Block device / HW Partition:user data (UCLASS_BLK) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device / HW Partition:boot0 (UCLASS_BLK) | |-- Block device / HW Partition:boot1 (UCLASS_BLK) ... | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?)
|-- scsi controller (UCLASS_SCSI) | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) ...
(Here I ignored scsi buses/channels which make things more complicated.)
This kind of complex hierarchy doesn't benefit anybody.
All these levels exist already. We simply do not model them yet in the DM way.
The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass.
The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Best regards Heinrich
-Takahiro Akashi
UCLASS_PARTITION_TABLE would be for the drivers in disk/. UCLASS_FS would be for the drivers in fs/. UCLASS_BLK will be for any objects exposing raw block IO. A software partition does the same. It is created by the partition table driver as child of the partition table udevice.
In this model an eMMC device will not be a UCLASS_BLK device because it does not expose block IO. It is the hardware partition that exposes this interface.
The suggested model will allow a clean description of nested partition tables.
In the UEFI world the software partition and its file system must be mapped to a single handle with device path node type HD(). For the parent block device we may create a child handle with partition number 0 (HD(0)). For the partition table we will not create a handle.
Best regards
Heinrich

Hi,
On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org:
On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote:
I agree with Heinrich that we are better to leave BLK as it is, both in name and meaning. I think maybe I am missing the gist of your argument.
If we use UCLASS_PART, for example, can we have that refer to both s/w and h/w partitions, as Herinch seems to allude to below? What would the picture look like the, and would it get us closer to agreement?
In the driver model:
A UCLASS is a class of drivers that share the same interface. A UDEVICE is a logical device that belongs to exactly one UCLASS and is accessed through this UCLASS's interface.
Please be careful about "accessed through" which is a quite confusing expression. I don't always agree with this view.
A hardware partition is an object that exposes only a single interface for block IO.
A software partition is an object that may expose two interfaces: one for block IO, the other for file IO.
Are you talking about UEFI world or U-Boot? Definitely, a hw partitions can provide a file system if you want. It's a matter of usage.
I remember that we had some discussion about whether block devices on UEFI system should always have a (sw) partition table or not. But it is a different topic.
The UEFI model does not have a problem with this because on a handle you can install as many different protocols as you wish. But U-Boot's driver model only allows a single interface per device. Up to now U-Boot has overcome this limitation by creating child devices for the extra interfaces.
We have the following logical levels:
Controller | Block device | Software Partition| File system ----------------+--------------+-------------------+------------ NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 ATA Controller | ATA-Drive | | SCSI Controller | LUN | | MMC Controller | HW-Partition | | MMC Controller | SD-Card | | USB-Node | USB-Drive | |
In the device tree this could be modeled as:
|-- Controller (UCLASS_CTRL) | |-- Block device / HW Partition (UCLASS_BLK) (A) | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device (UCLASS_BLK) | |-- File system (UCLASS_FS)
I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. What is the benefit? (A) and (B) always have 1:1 relationship.
No. You can have a bare device without a partition table.
I can have a DOS partition that covers the whole device, without a partition table. This is supported in U-Boot and Linux.
We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices.
I also remember that you claimed that not all efi objects(handles and protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding U-Boot counterparts in our 2019 discussion.
If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, which should support other type of hw partitions as well?
How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device.
|-- eMMC controller (UCLASS_MMC) | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- Block device / HW Partition:user data (UCLASS_BLK) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device / HW Partition:boot0 (UCLASS_BLK) | |-- Block device / HW Partition:boot1 (UCLASS_BLK) ... | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?)
|-- scsi controller (UCLASS_SCSI) | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) ...
(Here I ignored scsi buses/channels which make things more complicated.)
This kind of complex hierarchy doesn't benefit anybody.
All these levels exist already. We simply do not model them yet in the DM way.
The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass.
The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Yes, the complexity has to go somewhere. With driver model I chose to have a single interface per uclass, since it is simpler to understand, no need to request a protocol for a device, etc.
Our current setup is similar to this
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition*
* although I don't think the MMC code actually supports it - SCSI does though
We want to add devices for the partition table and the filesystem, so could do:
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) | | | |-- Block device (UCLASS_BLK) - partition 1 | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem | | | |-- Block device (UCLASS_BLK) - partition 2 | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition (the whole device)
This is similar to Heinrich's, but without the top-level UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
It is compatible with what we have now and we could enable/disable the extra devices with a Kconfig.
Regards, Simon
UCLASS_PARTITION_TABLE would be for the drivers in disk/. UCLASS_FS would be for the drivers in fs/. UCLASS_BLK will be for any objects exposing raw block IO. A software partition does the same. It is created by the partition table driver as child of the partition table udevice.
In this model an eMMC device will not be a UCLASS_BLK device because it does not expose block IO. It is the hardware partition that exposes this interface.
The suggested model will allow a clean description of nested partition tables.
In the UEFI world the software partition and its file system must be mapped to a single handle with device path node type HD(). For the parent block device we may create a child handle with partition number 0 (HD(0)). For the partition table we will not create a handle.
Best regards
Heinrich

Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org:
On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote:
I agree with Heinrich that we are better to leave BLK as it is, both in name and meaning. I think maybe I am missing the gist of your argument.
If we use UCLASS_PART, for example, can we have that refer to both s/w and h/w partitions, as Herinch seems to allude to below? What would the picture look like the, and would it get us closer to agreement?
In the driver model:
A UCLASS is a class of drivers that share the same interface. A UDEVICE is a logical device that belongs to exactly one UCLASS and is accessed through this UCLASS's interface.
Please be careful about "accessed through" which is a quite confusing expression. I don't always agree with this view.
A hardware partition is an object that exposes only a single interface for block IO.
A software partition is an object that may expose two interfaces: one for block IO, the other for file IO.
Are you talking about UEFI world or U-Boot? Definitely, a hw partitions can provide a file system if you want. It's a matter of usage.
I remember that we had some discussion about whether block devices on UEFI system should always have a (sw) partition table or not. But it is a different topic.
The UEFI model does not have a problem with this because on a handle you can install as many different protocols as you wish. But U-Boot's driver model only allows a single interface per device. Up to now U-Boot has overcome this limitation by creating child devices for the extra interfaces.
We have the following logical levels:
Controller | Block device | Software Partition| File system ----------------+--------------+-------------------+------------ NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 ATA Controller | ATA-Drive | | SCSI Controller | LUN | | MMC Controller | HW-Partition | | MMC Controller | SD-Card | | USB-Node | USB-Drive | |
In the device tree this could be modeled as:
|-- Controller (UCLASS_CTRL) | |-- Block device / HW Partition (UCLASS_BLK) (A) | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device (UCLASS_BLK) | |-- File system (UCLASS_FS)
I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. What is the benefit? (A) and (B) always have 1:1 relationship.
No. You can have a bare device without a partition table.
I can have a DOS partition that covers the whole device, without a partition table. This is supported in U-Boot and Linux.
We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices.
I also remember that you claimed that not all efi objects(handles and protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding U-Boot counterparts in our 2019 discussion.
If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, which should support other type of hw partitions as well?
How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device.
|-- eMMC controller (UCLASS_MMC) | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- Block device / HW Partition:user data (UCLASS_BLK) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device / HW Partition:boot0 (UCLASS_BLK) | |-- Block device / HW Partition:boot1 (UCLASS_BLK) ... | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?)
|-- scsi controller (UCLASS_SCSI) | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) ...
(Here I ignored scsi buses/channels which make things more complicated.)
This kind of complex hierarchy doesn't benefit anybody.
All these levels exist already. We simply do not model them yet in the DM way.
The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass.
The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Yes, the complexity has to go somewhere. With driver model I chose to have a single interface per uclass, since it is simpler to understand, no need to request a protocol for a device, etc.
Our current setup is similar to this
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition*
- although I don't think the MMC code actually supports it - SCSI does though
We want to add devices for the partition table and the filesystem, so could do:
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) | | | |-- Block device (UCLASS_BLK) - partition 1 | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem | | | |-- Block device (UCLASS_BLK) - partition 2 | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition (the whole device)
This is similar to Heinrich's, but without the top-level UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Regards
Heinrich
It is compatible with what we have now and we could enable/disable the extra devices with a Kconfig.
Regards, Simon
UCLASS_PARTITION_TABLE would be for the drivers in disk/. UCLASS_FS would be for the drivers in fs/. UCLASS_BLK will be for any objects exposing raw block IO. A software partition does the same. It is created by the partition table driver as child of the partition table udevice.
In this model an eMMC device will not be a UCLASS_BLK device because it does not expose block IO. It is the hardware partition that exposes this interface.
The suggested model will allow a clean description of nested partition tables.
In the UEFI world the software partition and its file system must be mapped to a single handle with device path node type HD(). For the parent block device we may create a child handle with partition number 0 (HD(0)). For the partition table we will not create a handle.
Best regards
Heinrich

On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote:
Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org:
On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote:
I agree with Heinrich that we are better to leave BLK as it is, both in name and meaning. I think maybe I am missing the gist of your argument.
If we use UCLASS_PART, for example, can we have that refer to both s/w and h/w partitions, as Herinch seems to allude to below? What would the picture look like the, and would it get us closer to agreement?
In the driver model:
A UCLASS is a class of drivers that share the same interface. A UDEVICE is a logical device that belongs to exactly one UCLASS and is accessed through this UCLASS's interface.
Please be careful about "accessed through" which is a quite confusing expression. I don't always agree with this view.
A hardware partition is an object that exposes only a single interface for block IO.
A software partition is an object that may expose two interfaces: one for block IO, the other for file IO.
Are you talking about UEFI world or U-Boot? Definitely, a hw partitions can provide a file system if you want. It's a matter of usage.
I remember that we had some discussion about whether block devices on UEFI system should always have a (sw) partition table or not. But it is a different topic.
The UEFI model does not have a problem with this because on a handle you can install as many different protocols as you wish. But U-Boot's driver model only allows a single interface per device. Up to now U-Boot has overcome this limitation by creating child devices for the extra interfaces.
We have the following logical levels:
Controller | Block device | Software Partition| File system ----------------+--------------+-------------------+------------ NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 ATA Controller | ATA-Drive | | SCSI Controller | LUN | | MMC Controller | HW-Partition | | MMC Controller | SD-Card | | USB-Node | USB-Drive | |
In the device tree this could be modeled as:
|-- Controller (UCLASS_CTRL) | |-- Block device / HW Partition (UCLASS_BLK) (A) | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device (UCLASS_BLK) | |-- File system (UCLASS_FS)
I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. What is the benefit? (A) and (B) always have 1:1 relationship.
No. You can have a bare device without a partition table.
I can have a DOS partition that covers the whole device, without a partition table. This is supported in U-Boot and Linux.
We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices.
I also remember that you claimed that not all efi objects(handles and protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding U-Boot counterparts in our 2019 discussion.
If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, which should support other type of hw partitions as well?
How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device.
|-- eMMC controller (UCLASS_MMC) | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- Block device / HW Partition:user data (UCLASS_BLK) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device / HW Partition:boot0 (UCLASS_BLK) | |-- Block device / HW Partition:boot1 (UCLASS_BLK) ... | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?)
|-- scsi controller (UCLASS_SCSI) | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) ...
(Here I ignored scsi buses/channels which make things more complicated.)
This kind of complex hierarchy doesn't benefit anybody.
All these levels exist already. We simply do not model them yet in the DM way.
The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass.
The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Yes, the complexity has to go somewhere. With driver model I chose to have a single interface per uclass, since it is simpler to understand, no need to request a protocol for a device, etc.
Our current setup is similar to this
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition*
- although I don't think the MMC code actually supports it - SCSI does though
We want to add devices for the partition table and the filesystem, so could do:
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) | | | |-- Block device (UCLASS_BLK) - partition 1 | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem | | | |-- Block device (UCLASS_BLK) - partition 2 | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition (the whole device)
This is similar to Heinrich's, but without the top-level UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Yes. What I meant to say is that, if we don't need a partition table 'udevice' for hw partitions, we don't need such a device for sw partitions neither.
Meanwhile, what about UCLASS_FS? Why do we need this?
-Takahiro Akashi
Regards
Heinrich
It is compatible with what we have now and we could enable/disable the extra devices with a Kconfig.
Regards, Simon
UCLASS_PARTITION_TABLE would be for the drivers in disk/. UCLASS_FS would be for the drivers in fs/. UCLASS_BLK will be for any objects exposing raw block IO. A software partition does the same. It is created by the partition table driver as child of the partition table udevice.
In this model an eMMC device will not be a UCLASS_BLK device because it does not expose block IO. It is the hardware partition that exposes this interface.
The suggested model will allow a clean description of nested partition tables.
In the UEFI world the software partition and its file system must be mapped to a single handle with device path node type HD(). For the parent block device we may create a child handle with partition number 0 (HD(0)). For the partition table we will not create a handle.
Best regards
Heinrich

Hi Takahiro,
On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote:
Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org:
On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote:
> I agree with Heinrich that we are better to leave BLK as it is, both > in name and meaning. I think maybe I am missing the gist of your > argument. > > If we use UCLASS_PART, for example, can we have that refer to both s/w > and h/w partitions, as Herinch seems to allude to below? What would > the picture look like the, and would it get us closer to agreement?
In the driver model:
A UCLASS is a class of drivers that share the same interface. A UDEVICE is a logical device that belongs to exactly one UCLASS and is accessed through this UCLASS's interface.
Please be careful about "accessed through" which is a quite confusing expression. I don't always agree with this view.
A hardware partition is an object that exposes only a single interface for block IO.
A software partition is an object that may expose two interfaces: one for block IO, the other for file IO.
Are you talking about UEFI world or U-Boot? Definitely, a hw partitions can provide a file system if you want. It's a matter of usage.
I remember that we had some discussion about whether block devices on UEFI system should always have a (sw) partition table or not. But it is a different topic.
The UEFI model does not have a problem with this because on a handle you can install as many different protocols as you wish. But U-Boot's driver model only allows a single interface per device. Up to now U-Boot has overcome this limitation by creating child devices for the extra interfaces.
We have the following logical levels:
Controller | Block device | Software Partition| File system ----------------+--------------+-------------------+------------ NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 ATA Controller | ATA-Drive | | SCSI Controller | LUN | | MMC Controller | HW-Partition | | MMC Controller | SD-Card | | USB-Node | USB-Drive | |
In the device tree this could be modeled as:
|-- Controller (UCLASS_CTRL) | |-- Block device / HW Partition (UCLASS_BLK) (A) | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device (UCLASS_BLK) | |-- File system (UCLASS_FS)
I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. What is the benefit? (A) and (B) always have 1:1 relationship.
No. You can have a bare device without a partition table.
I can have a DOS partition that covers the whole device, without a partition table. This is supported in U-Boot and Linux.
We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices.
I also remember that you claimed that not all efi objects(handles and protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding U-Boot counterparts in our 2019 discussion.
If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, which should support other type of hw partitions as well?
How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device.
|-- eMMC controller (UCLASS_MMC) | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- Block device / HW Partition:user data (UCLASS_BLK) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device / HW Partition:boot0 (UCLASS_BLK) | |-- Block device / HW Partition:boot1 (UCLASS_BLK) ... | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?)
|-- scsi controller (UCLASS_SCSI) | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) ...
(Here I ignored scsi buses/channels which make things more complicated.)
This kind of complex hierarchy doesn't benefit anybody.
All these levels exist already. We simply do not model them yet in the DM way.
The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass.
The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Yes, the complexity has to go somewhere. With driver model I chose to have a single interface per uclass, since it is simpler to understand, no need to request a protocol for a device, etc.
Our current setup is similar to this
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition*
- although I don't think the MMC code actually supports it - SCSI does though
We want to add devices for the partition table and the filesystem, so could do:
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) | | | |-- Block device (UCLASS_BLK) - partition 1 | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem | | | |-- Block device (UCLASS_BLK) - partition 2 | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition (the whole device)
This is similar to Heinrich's, but without the top-level UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Yes. What I meant to say is that, if we don't need a partition table 'udevice' for hw partitions, we don't need such a device for sw partitions neither.
Meanwhile, what about UCLASS_FS? Why do we need this?
We don't need it for our current discussion, but if we want to 'open' the filesystem and keep the metadata around, rather than reading it again every time we access a file, we might find it useful. Open files could be children of the FS uclass, perhaps, if we go a step further and create devices for them.
Regards, Simon
It is compatible with what we have now and we could enable/disable the extra devices with a Kconfig.
Regards, Simon
UCLASS_PARTITION_TABLE would be for the drivers in disk/. UCLASS_FS would be for the drivers in fs/. UCLASS_BLK will be for any objects exposing raw block IO. A software partition does the same. It is created by the partition table driver as child of the partition table udevice.
In this model an eMMC device will not be a UCLASS_BLK device because it does not expose block IO. It is the hardware partition that exposes this interface.
The suggested model will allow a clean description of nested partition tables.
In the UEFI world the software partition and its file system must be mapped to a single handle with device path node type HD(). For the parent block device we may create a child handle with partition number 0 (HD(0)). For the partition table we will not create a handle.
Best regards
Heinrich

On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote:
Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org:
On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: > > > > I agree with Heinrich that we are better to leave BLK as it is, both > > in name and meaning. I think maybe I am missing the gist of your > > argument. > > > > If we use UCLASS_PART, for example, can we have that refer to both s/w > > and h/w partitions, as Herinch seems to allude to below? What would > > the picture look like the, and would it get us closer to agreement? > > In the driver model: > > A UCLASS is a class of drivers that share the same interface. > A UDEVICE is a logical device that belongs to exactly one UCLASS and is > accessed through this UCLASS's interface.
Please be careful about "accessed through" which is a quite confusing expression. I don't always agree with this view.
> A hardware partition is an object that exposes only a single interface > for block IO. > > A software partition is an object that may expose two interfaces: one > for block IO, the other for file IO.
Are you talking about UEFI world or U-Boot? Definitely, a hw partitions can provide a file system if you want. It's a matter of usage.
I remember that we had some discussion about whether block devices on UEFI system should always have a (sw) partition table or not. But it is a different topic.
> The UEFI model does not have a problem with this because on a handle you > can install as many different protocols as you wish. But U-Boot's driver > model only allows a single interface per device. Up to now U-Boot has > overcome this limitation by creating child devices for the extra interfaces.
> We have the following logical levels: > > Controller | Block device | Software Partition| File system > ----------------+--------------+-------------------+------------ > NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 > ATA Controller | ATA-Drive | | > SCSI Controller | LUN | | > MMC Controller | HW-Partition | | > MMC Controller | SD-Card | | > USB-Node | USB-Drive | | > > In the device tree this could be modeled as: > > |-- Controller (UCLASS_CTRL) > | |-- Block device / HW Partition (UCLASS_BLK) (A) > | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) > | | |-- Software Partition (UCLASS_BLK) > | | |-- File system (UCLASS_FS) > | | > | |-- Block device (UCLASS_BLK) > | |-- File system (UCLASS_FS)
I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. What is the benefit? (A) and (B) always have 1:1 relationship.
No. You can have a bare device without a partition table.
I can have a DOS partition that covers the whole device, without a partition table. This is supported in U-Boot and Linux.
We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices.
I also remember that you claimed that not all efi objects(handles and protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding U-Boot counterparts in our 2019 discussion.
If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, which should support other type of hw partitions as well?
How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device.
|-- eMMC controller (UCLASS_MMC) | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- Block device / HW Partition:user data (UCLASS_BLK) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | | |-- File system (UCLASS_FS) | | | |-- Block device / HW Partition:boot0 (UCLASS_BLK) | |-- Block device / HW Partition:boot1 (UCLASS_BLK) ... | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?)
|-- scsi controller (UCLASS_SCSI) | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) | | |-- Partition table (UCLASS_PARTITION_TABLE) | | |-- Software Partition (UCLASS_BLK) | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) ...
(Here I ignored scsi buses/channels which make things more complicated.)
This kind of complex hierarchy doesn't benefit anybody.
All these levels exist already. We simply do not model them yet in the DM way.
The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass.
The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Yes, the complexity has to go somewhere. With driver model I chose to have a single interface per uclass, since it is simpler to understand, no need to request a protocol for a device, etc.
Our current setup is similar to this
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition*
- although I don't think the MMC code actually supports it - SCSI does though
We want to add devices for the partition table and the filesystem, so could do:
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) | | | |-- Block device (UCLASS_BLK) - partition 1 | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem | | | |-- Block device (UCLASS_BLK) - partition 2 | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition (the whole device)
This is similar to Heinrich's, but without the top-level UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Yes. What I meant to say is that, if we don't need a partition table 'udevice' for hw partitions, we don't need such a device for sw partitions neither.
Meanwhile, what about UCLASS_FS? Why do we need this?
We don't need it for our current discussion, but if we want to 'open' the filesystem and keep the metadata around, rather than reading it again every time we access a file, we might find it useful. Open files could be children of the FS uclass, perhaps, if we go a step further and create devices for them.
Do you want to invent linux-like mount-point concepts or procfs? I remember that you didn't want to have child nodes under BLK devices. I'm getting confused about our goal. What should DM represent in U-Boot world?
Regards, Simon
It is compatible with what we have now and we could enable/disable the extra devices with a Kconfig.
Regards, Simon
> UCLASS_PARTITION_TABLE would be for the drivers in disk/. > UCLASS_FS would be for the drivers in fs/. > UCLASS_BLK will be for any objects exposing raw block IO. A software > partition does the same. It is created by the partition table driver as > child of the partition table udevice. > > In this model an eMMC device will not be a UCLASS_BLK device because it > does not expose block IO. It is the hardware partition that exposes this > interface. > > The suggested model will allow a clean description of nested partition > tables. > > In the UEFI world the software partition and its file system must be > mapped to a single handle with device path node type HD(). For the > parent block device we may create a child handle with partition number 0 > (HD(0)). For the partition table we will not create a handle. > > Best regards > > Heinrich

Hi Takahiro,
On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote:
Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >> >> >> > I agree with Heinrich that we are better to leave BLK as it is, both >> > in name and meaning. I think maybe I am missing the gist of your >> > argument. >> > >> > If we use UCLASS_PART, for example, can we have that refer to both s/w >> > and h/w partitions, as Herinch seems to allude to below? What would >> > the picture look like the, and would it get us closer to agreement? >> >> In the driver model: >> >> A UCLASS is a class of drivers that share the same interface. >> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >> accessed through this UCLASS's interface. > >Please be careful about "accessed through" which is a quite confusing >expression. I don't always agree with this view. > >> A hardware partition is an object that exposes only a single interface >> for block IO. >> >> A software partition is an object that may expose two interfaces: one >> for block IO, the other for file IO. > >Are you talking about UEFI world or U-Boot? >Definitely, a hw partitions can provide a file system >if you want. >It's a matter of usage. > >I remember that we had some discussion about whether block devices >on UEFI system should always have a (sw) partition table or not. >But it is a different topic. > >> The UEFI model does not have a problem with this because on a handle you >> can install as many different protocols as you wish. But U-Boot's driver >> model only allows a single interface per device. Up to now U-Boot has >> overcome this limitation by creating child devices for the extra interfaces. > >> We have the following logical levels: >> >> Controller | Block device | Software Partition| File system >> ----------------+--------------+-------------------+------------ >> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >> ATA Controller | ATA-Drive | | >> SCSI Controller | LUN | | >> MMC Controller | HW-Partition | | >> MMC Controller | SD-Card | | >> USB-Node | USB-Drive | | >> >> In the device tree this could be modeled as: >> >> |-- Controller (UCLASS_CTRL) >> | |-- Block device / HW Partition (UCLASS_BLK) (A) >> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >> | | |-- Software Partition (UCLASS_BLK) >> | | |-- File system (UCLASS_FS) >> | | >> | |-- Block device (UCLASS_BLK) >> | |-- File system (UCLASS_FS) > >I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >What is the benefit? >(A) and (B) always have 1:1 relationship.
No. You can have a bare device without a partition table.
I can have a DOS partition that covers the whole device, without a partition table. This is supported in U-Boot and Linux.
We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices.
>I also remember that you claimed that not all efi objects(handles and >protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >U-Boot counterparts in our 2019 discussion. > >If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >which should support other type of hw partitions as well?
How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device.
> >|-- eMMC controller (UCLASS_MMC) >| |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >| |-- Block device / HW Partition:user data (UCLASS_BLK) >| | |-- Partition table (UCLASS_PARTITION_TABLE) >| | |-- Software Partition (UCLASS_BLK) >| | |-- File system (UCLASS_FS) >| | >| |-- Block device / HW Partition:boot0 (UCLASS_BLK) >| |-- Block device / HW Partition:boot1 (UCLASS_BLK) > ... >| |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) > >|-- scsi controller (UCLASS_SCSI) >| |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >| |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >| | |-- Partition table (UCLASS_PARTITION_TABLE) >| | |-- Software Partition (UCLASS_BLK) >| |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) > ... > >(Here I ignored scsi buses/channels which make things more complicated.) > >This kind of complex hierarchy doesn't benefit anybody.
All these levels exist already. We simply do not model them yet in the DM way.
The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass.
The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Yes, the complexity has to go somewhere. With driver model I chose to have a single interface per uclass, since it is simpler to understand, no need to request a protocol for a device, etc.
Our current setup is similar to this
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition*
- although I don't think the MMC code actually supports it - SCSI does though
We want to add devices for the partition table and the filesystem, so could do:
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) | | | |-- Block device (UCLASS_BLK) - partition 1 | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem | | | |-- Block device (UCLASS_BLK) - partition 2 | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition (the whole device)
This is similar to Heinrich's, but without the top-level UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Yes. What I meant to say is that, if we don't need a partition table 'udevice' for hw partitions, we don't need such a device for sw partitions neither.
Meanwhile, what about UCLASS_FS? Why do we need this?
We don't need it for our current discussion, but if we want to 'open' the filesystem and keep the metadata around, rather than reading it again every time we access a file, we might find it useful. Open files could be children of the FS uclass, perhaps, if we go a step further and create devices for them.
Do you want to invent linux-like mount-point concepts or procfs? I remember that you didn't want to have child nodes under BLK devices. I'm getting confused about our goal.
I think we are all a bit unsure.
I think BLK devices can have children, sorry if I said the wrong thing somewhere along the way. For example, a partition would be under a BLK device, or a FS.
What should DM represent in U-Boot world?
That is what we are trying to figure out.
I think the minimum is to have a a way to represent partitions (s/w and hw/). As I understand it, that's what we've been discussing.
Regards, Simon
Regards, Simon
It is compatible with what we have now and we could enable/disable the extra devices with a Kconfig.
Regards, Simon
> >> UCLASS_PARTITION_TABLE would be for the drivers in disk/. >> UCLASS_FS would be for the drivers in fs/. >> UCLASS_BLK will be for any objects exposing raw block IO. A software >> partition does the same. It is created by the partition table driver as >> child of the partition table udevice. >> >> In this model an eMMC device will not be a UCLASS_BLK device because it >> does not expose block IO. It is the hardware partition that exposes this >> interface. >> >> The suggested model will allow a clean description of nested partition >> tables. >> >> In the UEFI world the software partition and its file system must be >> mapped to a single handle with device path node type HD(). For the >> parent block device we may create a child handle with partition number 0 >> (HD(0)). For the partition table we will not create a handle. >> >> Best regards >> >> Heinrich

On Sun, Oct 31, 2021 at 08:14:13PM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote:
Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: > >On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: > >> > >> > >> > I agree with Heinrich that we are better to leave BLK as it is, both > >> > in name and meaning. I think maybe I am missing the gist of your > >> > argument. > >> > > >> > If we use UCLASS_PART, for example, can we have that refer to both s/w > >> > and h/w partitions, as Herinch seems to allude to below? What would > >> > the picture look like the, and would it get us closer to agreement? > >> > >> In the driver model: > >> > >> A UCLASS is a class of drivers that share the same interface. > >> A UDEVICE is a logical device that belongs to exactly one UCLASS and is > >> accessed through this UCLASS's interface. > > > >Please be careful about "accessed through" which is a quite confusing > >expression. I don't always agree with this view. > > > >> A hardware partition is an object that exposes only a single interface > >> for block IO. > >> > >> A software partition is an object that may expose two interfaces: one > >> for block IO, the other for file IO. > > > >Are you talking about UEFI world or U-Boot? > >Definitely, a hw partitions can provide a file system > >if you want. > >It's a matter of usage. > > > >I remember that we had some discussion about whether block devices > >on UEFI system should always have a (sw) partition table or not. > >But it is a different topic. > > > >> The UEFI model does not have a problem with this because on a handle you > >> can install as many different protocols as you wish. But U-Boot's driver > >> model only allows a single interface per device. Up to now U-Boot has > >> overcome this limitation by creating child devices for the extra interfaces. > > > >> We have the following logical levels: > >> > >> Controller | Block device | Software Partition| File system > >> ----------------+--------------+-------------------+------------ > >> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 > >> ATA Controller | ATA-Drive | | > >> SCSI Controller | LUN | | > >> MMC Controller | HW-Partition | | > >> MMC Controller | SD-Card | | > >> USB-Node | USB-Drive | | > >> > >> In the device tree this could be modeled as: > >> > >> |-- Controller (UCLASS_CTRL) > >> | |-- Block device / HW Partition (UCLASS_BLK) (A) > >> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) > >> | | |-- Software Partition (UCLASS_BLK) > >> | | |-- File system (UCLASS_FS) > >> | | > >> | |-- Block device (UCLASS_BLK) > >> | |-- File system (UCLASS_FS) > > > >I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. > >What is the benefit? > >(A) and (B) always have 1:1 relationship. > > No. You can have a bare device without a partition table.
I can have a DOS partition that covers the whole device, without a partition table. This is supported in U-Boot and Linux.
> > We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. > > >I also remember that you claimed that not all efi objects(handles and > >protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding > >U-Boot counterparts in our 2019 discussion. > > > >If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, > >which should support other type of hw partitions as well? > > How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. > > > > >|-- eMMC controller (UCLASS_MMC) > >| |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) > >| |-- Block device / HW Partition:user data (UCLASS_BLK) > >| | |-- Partition table (UCLASS_PARTITION_TABLE) > >| | |-- Software Partition (UCLASS_BLK) > >| | |-- File system (UCLASS_FS) > >| | > >| |-- Block device / HW Partition:boot0 (UCLASS_BLK) > >| |-- Block device / HW Partition:boot1 (UCLASS_BLK) > > ... > >| |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > >|-- scsi controller (UCLASS_SCSI) > >| |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) > >| |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) > >| | |-- Partition table (UCLASS_PARTITION_TABLE) > >| | |-- Software Partition (UCLASS_BLK) > >| |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) > > ... > > > >(Here I ignored scsi buses/channels which make things more complicated.) > > > >This kind of complex hierarchy doesn't benefit anybody. > > All these levels exist already. We simply do not model them yet in the DM way. > > The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. > > The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Yes, the complexity has to go somewhere. With driver model I chose to have a single interface per uclass, since it is simpler to understand, no need to request a protocol for a device, etc.
Our current setup is similar to this
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition*
- although I don't think the MMC code actually supports it - SCSI does though
We want to add devices for the partition table and the filesystem, so could do:
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) | | | |-- Block device (UCLASS_BLK) - partition 1 | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem | | | |-- Block device (UCLASS_BLK) - partition 2 | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition (the whole device)
This is similar to Heinrich's, but without the top-level UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Yes. What I meant to say is that, if we don't need a partition table 'udevice' for hw partitions, we don't need such a device for sw partitions neither.
Meanwhile, what about UCLASS_FS? Why do we need this?
We don't need it for our current discussion, but if we want to 'open' the filesystem and keep the metadata around, rather than reading it again every time we access a file, we might find it useful. Open files could be children of the FS uclass, perhaps, if we go a step further and create devices for them.
Do you want to invent linux-like mount-point concepts or procfs? I remember that you didn't want to have child nodes under BLK devices. I'm getting confused about our goal.
I think we are all a bit unsure.
I think BLK devices can have children, sorry if I said the wrong thing somewhere along the way. For example, a partition would be under a BLK device, or a FS.
What should DM represent in U-Boot world?
That is what we are trying to figure out.
I think the minimum is to have a a way to represent partitions (s/w and hw/). As I understand it, that's what we've been discussing.
I don't still understand why we need a "partition table" device in DM tree.
As I proposed in my message on Oct 28th, the hierarchy like
- MMC (bus controller) |- BLK (device/hw partition:user data) ||- DISK (partition 0 == a whole device) ||- DISK (partition 1) ||- DISK (partition 2) ||- DISK (partition 3) |- BLK (device/hw partition:boot0) ||- DISK (partition 0 == a whole device) |- BLK (device/hw partition:boot0) ||- DISK (partition 0 == a whole device) |- BLK (device/hw partition:rpmb) -- this is NOT a 'block' device, though. ||- DISK (partition 0 == a whole device)
is good enough to represent the partition relationships, ie. BLK-DISK for s/w partition MMC-BLK for h/w partition
If you don't like the name DISK (or UCLASS_PARTITION in my RFC), it can be BLK_PARTITION ore even be transformed to BLK with (new) IF_TYPE_PARTITION. (I'd rather prefer to rename BLK->BLK_MEDIA and DISK->BLK, but don't stick to this idea.)
Please remember UCLASS_PARTITION devices hold partition information (offset and size) and we don't need to scan the disk every time to access.
Currently, UCLASS_MMC doesn't support h/w partitions as standalone BLK devices, but we can manage to modify the drivers. (In this sense, it is much preferable to have a "h/w partition table" device in DM tree, rather than "s/w table", as the former represents a real "hardware" device.
-Takahiro Akashi
Regards, Simon
Regards, Simon
It is compatible with what we have now and we could enable/disable the extra devices with a Kconfig.
Regards, Simon
> > > >> UCLASS_PARTITION_TABLE would be for the drivers in disk/. > >> UCLASS_FS would be for the drivers in fs/. > >> UCLASS_BLK will be for any objects exposing raw block IO. A software > >> partition does the same. It is created by the partition table driver as > >> child of the partition table udevice. > >> > >> In this model an eMMC device will not be a UCLASS_BLK device because it > >> does not expose block IO. It is the hardware partition that exposes this > >> interface. > >> > >> The suggested model will allow a clean description of nested partition > >> tables. > >> > >> In the UEFI world the software partition and its file system must be > >> mapped to a single handle with device path node type HD(). For the > >> parent block device we may create a child handle with partition number 0 > >> (HD(0)). For the partition table we will not create a handle. > >> > >> Best regards > >> > >> Heinrich

On 11/1/21 03:14, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote:
Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >>> >>> >>>> I agree with Heinrich that we are better to leave BLK as it is, both >>>> in name and meaning. I think maybe I am missing the gist of your >>>> argument. >>>> >>>> If we use UCLASS_PART, for example, can we have that refer to both s/w >>>> and h/w partitions, as Herinch seems to allude to below? What would >>>> the picture look like the, and would it get us closer to agreement? >>> >>> In the driver model: >>> >>> A UCLASS is a class of drivers that share the same interface. >>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >>> accessed through this UCLASS's interface. >> >> Please be careful about "accessed through" which is a quite confusing >> expression. I don't always agree with this view. >> >>> A hardware partition is an object that exposes only a single interface >>> for block IO. >>> >>> A software partition is an object that may expose two interfaces: one >>> for block IO, the other for file IO. >> >> Are you talking about UEFI world or U-Boot? >> Definitely, a hw partitions can provide a file system >> if you want. >> It's a matter of usage. >> >> I remember that we had some discussion about whether block devices >> on UEFI system should always have a (sw) partition table or not. >> But it is a different topic. >> >>> The UEFI model does not have a problem with this because on a handle you >>> can install as many different protocols as you wish. But U-Boot's driver >>> model only allows a single interface per device. Up to now U-Boot has >>> overcome this limitation by creating child devices for the extra interfaces. >> >>> We have the following logical levels: >>> >>> Controller | Block device | Software Partition| File system >>> ----------------+--------------+-------------------+------------ >>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >>> ATA Controller | ATA-Drive | | >>> SCSI Controller | LUN | | >>> MMC Controller | HW-Partition | | >>> MMC Controller | SD-Card | | >>> USB-Node | USB-Drive | | >>> >>> In the device tree this could be modeled as: >>> >>> |-- Controller (UCLASS_CTRL) >>> | |-- Block device / HW Partition (UCLASS_BLK) (A) >>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >>> | | |-- Software Partition (UCLASS_BLK) >>> | | |-- File system (UCLASS_FS) >>> | | >>> | |-- Block device (UCLASS_BLK) >>> | |-- File system (UCLASS_FS) >> >> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >> What is the benefit? >> (A) and (B) always have 1:1 relationship. > > No. You can have a bare device without a partition table.
I can have a DOS partition that covers the whole device, without a partition table. This is supported in U-Boot and Linux.
> > We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. > >> I also remember that you claimed that not all efi objects(handles and >> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >> U-Boot counterparts in our 2019 discussion. >> >> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >> which should support other type of hw partitions as well? > > How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. > >> >> |-- eMMC controller (UCLASS_MMC) >> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >> | |-- Block device / HW Partition:user data (UCLASS_BLK) >> | | |-- Partition table (UCLASS_PARTITION_TABLE) >> | | |-- Software Partition (UCLASS_BLK) >> | | |-- File system (UCLASS_FS) >> | | >> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) >> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) >> ... >> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) >> >> |-- scsi controller (UCLASS_SCSI) >> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >> | | |-- Partition table (UCLASS_PARTITION_TABLE) >> | | |-- Software Partition (UCLASS_BLK) >> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) >> ... >> >> (Here I ignored scsi buses/channels which make things more complicated.) >> >> This kind of complex hierarchy doesn't benefit anybody. > > All these levels exist already. We simply do not model them yet in the DM way. > > The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. > > The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases.
Yes, the complexity has to go somewhere. With driver model I chose to have a single interface per uclass, since it is simpler to understand, no need to request a protocol for a device, etc.
Our current setup is similar to this
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition*
- although I don't think the MMC code actually supports it - SCSI does though
We want to add devices for the partition table and the filesystem, so could do:
|-- Controller (UCLASS_MMC) | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) | | | |-- Block device (UCLASS_BLK) - partition 1 | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem | | | |-- Block device (UCLASS_BLK) - partition 2 | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition (the whole device)
This is similar to Heinrich's, but without the top-level UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Yes. What I meant to say is that, if we don't need a partition table 'udevice' for hw partitions, we don't need such a device for sw partitions neither.
Meanwhile, what about UCLASS_FS? Why do we need this?
We don't need it for our current discussion, but if we want to 'open' the filesystem and keep the metadata around, rather than reading it again every time we access a file, we might find it useful. Open files could be children of the FS uclass, perhaps, if we go a step further and create devices for them.
Do you want to invent linux-like mount-point concepts or procfs? I remember that you didn't want to have child nodes under BLK devices. I'm getting confused about our goal.
I think we are all a bit unsure.
I think BLK devices can have children, sorry if I said the wrong thing somewhere along the way. For example, a partition would be under a BLK device, or a FS.
What should DM represent in U-Boot world?
That is what we are trying to figure out.
I think the minimum is to have a a way to represent partitions (s/w and hw/). As I understand it, that's what we've been discussing.
The discovery of hardware partitions is specific to the block device controller SCSI/MMC/ATA/NVMe. We currently do not provide any manipulation commands to create hardware partitions (e.g. NVMe namespaces, SCSI LUNs). This is why extracting a uclass for hardware partitions does not seem necessary.
Software partitioning (MBR, GPT, ...) is independent of the harboring block device.
We already have a set of drivers for software partition tables in disk/. Currently the available methods of the drivers are defined in U_BOOT_PART_TYPE referring to struct part_driver.
Currently struct part_driver knows only the following methods:
- get_info() - print() - test()
These drivers should be ome a uclass.
gpt.c and mbr.c allow to create and delete partitions. I think we should add
- create_partition() - delete_partition()
to the uclass methods.
The partitions handled by cmd/mtdparts.c, cmd/nand.c are also software partitions. The difference to MBR, GPT is that the partition table is held in memory and not on disk. These partitions could be modeled in the same uclass.
Best regards
Heinrich
Regards, Simon
Regards, Simon
It is compatible with what we have now and we could enable/disable the extra devices with a Kconfig.
Regards, Simon
>> >>> UCLASS_PARTITION_TABLE would be for the drivers in disk/. >>> UCLASS_FS would be for the drivers in fs/. >>> UCLASS_BLK will be for any objects exposing raw block IO. A software >>> partition does the same. It is created by the partition table driver as >>> child of the partition table udevice. >>> >>> In this model an eMMC device will not be a UCLASS_BLK device because it >>> does not expose block IO. It is the hardware partition that exposes this >>> interface. >>> >>> The suggested model will allow a clean description of nested partition >>> tables. >>> >>> In the UEFI world the software partition and its file system must be >>> mapped to a single handle with device path node type HD(). For the >>> parent block device we may create a child handle with partition number 0 >>> (HD(0)). For the partition table we will not create a handle. >>> >>> Best regards >>> >>> Heinrich

Hi,
On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 11/1/21 03:14, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote:
Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: > Hi, > > On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >> >> >> >> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >>>> >>>> >>>>> I agree with Heinrich that we are better to leave BLK as it is, both >>>>> in name and meaning. I think maybe I am missing the gist of your >>>>> argument. >>>>> >>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w >>>>> and h/w partitions, as Herinch seems to allude to below? What would >>>>> the picture look like the, and would it get us closer to agreement? >>>> >>>> In the driver model: >>>> >>>> A UCLASS is a class of drivers that share the same interface. >>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >>>> accessed through this UCLASS's interface. >>> >>> Please be careful about "accessed through" which is a quite confusing >>> expression. I don't always agree with this view. >>> >>>> A hardware partition is an object that exposes only a single interface >>>> for block IO. >>>> >>>> A software partition is an object that may expose two interfaces: one >>>> for block IO, the other for file IO. >>> >>> Are you talking about UEFI world or U-Boot? >>> Definitely, a hw partitions can provide a file system >>> if you want. >>> It's a matter of usage. >>> >>> I remember that we had some discussion about whether block devices >>> on UEFI system should always have a (sw) partition table or not. >>> But it is a different topic. >>> >>>> The UEFI model does not have a problem with this because on a handle you >>>> can install as many different protocols as you wish. But U-Boot's driver >>>> model only allows a single interface per device. Up to now U-Boot has >>>> overcome this limitation by creating child devices for the extra interfaces. >>> >>>> We have the following logical levels: >>>> >>>> Controller | Block device | Software Partition| File system >>>> ----------------+--------------+-------------------+------------ >>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >>>> ATA Controller | ATA-Drive | | >>>> SCSI Controller | LUN | | >>>> MMC Controller | HW-Partition | | >>>> MMC Controller | SD-Card | | >>>> USB-Node | USB-Drive | | >>>> >>>> In the device tree this could be modeled as: >>>> >>>> |-- Controller (UCLASS_CTRL) >>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) >>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >>>> | | |-- Software Partition (UCLASS_BLK) >>>> | | |-- File system (UCLASS_FS) >>>> | | >>>> | |-- Block device (UCLASS_BLK) >>>> | |-- File system (UCLASS_FS) >>> >>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >>> What is the benefit? >>> (A) and (B) always have 1:1 relationship. >> >> No. You can have a bare device without a partition table. > > I can have a DOS partition that covers the whole device, without a > partition table. This is supported in U-Boot and Linux. > >> >> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. >> >>> I also remember that you claimed that not all efi objects(handles and >>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >>> U-Boot counterparts in our 2019 discussion. >>> >>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >>> which should support other type of hw partitions as well? >> >> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. >> >>> >>> |-- eMMC controller (UCLASS_MMC) >>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>> | |-- Block device / HW Partition:user data (UCLASS_BLK) >>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>> | | |-- Software Partition (UCLASS_BLK) >>> | | |-- File system (UCLASS_FS) >>> | | >>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) >>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) >>> ... >>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>> >>> |-- scsi controller (UCLASS_SCSI) >>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>> | | |-- Software Partition (UCLASS_BLK) >>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) >>> ... >>> >>> (Here I ignored scsi buses/channels which make things more complicated.) >>> >>> This kind of complex hierarchy doesn't benefit anybody. >> >> All these levels exist already. We simply do not model them yet in the DM way. >> >> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. >> >> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. > > Yes, the complexity has to go somewhere. With driver model I chose to > have a single interface per uclass, since it is simpler to understand, > no need to request a protocol for a device, etc. > > Our current setup is similar to this > > |-- Controller (UCLASS_MMC) > | |-- Block device (UCLASS_BLK) - 'usual' HW partition > | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* > > * although I don't think the MMC code actually supports it - SCSI does though > > We want to add devices for the partition table and the filesystem, so could do: > > |-- Controller (UCLASS_MMC) > | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) > | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) > | | | |-- Block device (UCLASS_BLK) - partition 1 > | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem > | | | |-- Block device (UCLASS_BLK) - partition 2 > | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem > | |-- Block device (UCLASS_BLK) - e.g. for a different HW > partition (the whole device) > > This is similar to Heinrich's, but without the top-level > UCLASS_HW_PARTITION_TABLE which I am not sure is necessary.
Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Yes. What I meant to say is that, if we don't need a partition table 'udevice' for hw partitions, we don't need such a device for sw partitions neither.
Meanwhile, what about UCLASS_FS? Why do we need this?
We don't need it for our current discussion, but if we want to 'open' the filesystem and keep the metadata around, rather than reading it again every time we access a file, we might find it useful. Open files could be children of the FS uclass, perhaps, if we go a step further and create devices for them.
Do you want to invent linux-like mount-point concepts or procfs? I remember that you didn't want to have child nodes under BLK devices. I'm getting confused about our goal.
I think we are all a bit unsure.
I think BLK devices can have children, sorry if I said the wrong thing somewhere along the way. For example, a partition would be under a BLK device, or a FS.
What should DM represent in U-Boot world?
That is what we are trying to figure out.
I think the minimum is to have a a way to represent partitions (s/w and hw/). As I understand it, that's what we've been discussing.
The discovery of hardware partitions is specific to the block device controller SCSI/MMC/ATA/NVMe. We currently do not provide any manipulation commands to create hardware partitions (e.g. NVMe namespaces, SCSI LUNs). This is why extracting a uclass for hardware partitions does not seem necessary.
I can see the reasoning here. It might not stand the test of time but how about we go with it for now? For MMC hardware partition we would just end up with multiple BLK devices, like we do with SCSI LUNs at present, which seems like it should work (with some code tweaks).
Software partitioning (MBR, GPT, ...) is independent of the harboring block device.
We already have a set of drivers for software partition tables in disk/. Currently the available methods of the drivers are defined in U_BOOT_PART_TYPE referring to struct part_driver.
Currently struct part_driver knows only the following methods:
- get_info()
- print()
- test()
These drivers should be ome a uclass.
gpt.c and mbr.c allow to create and delete partitions. I think we should add
- create_partition()
- delete_partition()
to the uclass methods.
That sounds good to me, although since it is a partition uclass, we can just use create() and delete().
The partitions handled by cmd/mtdparts.c, cmd/nand.c are also software partitions. The difference to MBR, GPT is that the partition table is held in memory and not on disk. These partitions could be modeled in the same uclass.
For future work!
Regards, SImon
> > It is compatible with what we have now and we could enable/disable the > extra devices with a Kconfig. > > Regards, > Simon > > > >>> >>>> UCLASS_PARTITION_TABLE would be for the drivers in disk/. >>>> UCLASS_FS would be for the drivers in fs/. >>>> UCLASS_BLK will be for any objects exposing raw block IO. A software >>>> partition does the same. It is created by the partition table driver as >>>> child of the partition table udevice. >>>> >>>> In this model an eMMC device will not be a UCLASS_BLK device because it >>>> does not expose block IO. It is the hardware partition that exposes this >>>> interface. >>>> >>>> The suggested model will allow a clean description of nested partition >>>> tables. >>>> >>>> In the UEFI world the software partition and its file system must be >>>> mapped to a single handle with device path node type HD(). For the >>>> parent block device we may create a child handle with partition number 0 >>>> (HD(0)). For the partition table we will not create a handle. >>>> >>>> Best regards >>>> >>>> Heinrich

On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote:
Hi,
On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 11/1/21 03:14, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: > > > Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: >> Hi, >> >> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >>> >>> >>> >>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >>>>> >>>>> >>>>>> I agree with Heinrich that we are better to leave BLK as it is, both >>>>>> in name and meaning. I think maybe I am missing the gist of your >>>>>> argument. >>>>>> >>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w >>>>>> and h/w partitions, as Herinch seems to allude to below? What would >>>>>> the picture look like the, and would it get us closer to agreement? >>>>> >>>>> In the driver model: >>>>> >>>>> A UCLASS is a class of drivers that share the same interface. >>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >>>>> accessed through this UCLASS's interface. >>>> >>>> Please be careful about "accessed through" which is a quite confusing >>>> expression. I don't always agree with this view. >>>> >>>>> A hardware partition is an object that exposes only a single interface >>>>> for block IO. >>>>> >>>>> A software partition is an object that may expose two interfaces: one >>>>> for block IO, the other for file IO. >>>> >>>> Are you talking about UEFI world or U-Boot? >>>> Definitely, a hw partitions can provide a file system >>>> if you want. >>>> It's a matter of usage. >>>> >>>> I remember that we had some discussion about whether block devices >>>> on UEFI system should always have a (sw) partition table or not. >>>> But it is a different topic. >>>> >>>>> The UEFI model does not have a problem with this because on a handle you >>>>> can install as many different protocols as you wish. But U-Boot's driver >>>>> model only allows a single interface per device. Up to now U-Boot has >>>>> overcome this limitation by creating child devices for the extra interfaces. >>>> >>>>> We have the following logical levels: >>>>> >>>>> Controller | Block device | Software Partition| File system >>>>> ----------------+--------------+-------------------+------------ >>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >>>>> ATA Controller | ATA-Drive | | >>>>> SCSI Controller | LUN | | >>>>> MMC Controller | HW-Partition | | >>>>> MMC Controller | SD-Card | | >>>>> USB-Node | USB-Drive | | >>>>> >>>>> In the device tree this could be modeled as: >>>>> >>>>> |-- Controller (UCLASS_CTRL) >>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) >>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >>>>> | | |-- Software Partition (UCLASS_BLK) >>>>> | | |-- File system (UCLASS_FS) >>>>> | | >>>>> | |-- Block device (UCLASS_BLK) >>>>> | |-- File system (UCLASS_FS) >>>> >>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >>>> What is the benefit? >>>> (A) and (B) always have 1:1 relationship. >>> >>> No. You can have a bare device without a partition table. >> >> I can have a DOS partition that covers the whole device, without a >> partition table. This is supported in U-Boot and Linux. >> >>> >>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. >>> >>>> I also remember that you claimed that not all efi objects(handles and >>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >>>> U-Boot counterparts in our 2019 discussion. >>>> >>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >>>> which should support other type of hw partitions as well? >>> >>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. >>> >>>> >>>> |-- eMMC controller (UCLASS_MMC) >>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) >>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>> | | |-- Software Partition (UCLASS_BLK) >>>> | | |-- File system (UCLASS_FS) >>>> | | >>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) >>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) >>>> ... >>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>> >>>> |-- scsi controller (UCLASS_SCSI) >>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>> | | |-- Software Partition (UCLASS_BLK) >>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) >>>> ... >>>> >>>> (Here I ignored scsi buses/channels which make things more complicated.) >>>> >>>> This kind of complex hierarchy doesn't benefit anybody. >>> >>> All these levels exist already. We simply do not model them yet in the DM way. >>> >>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. >>> >>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. >> >> Yes, the complexity has to go somewhere. With driver model I chose to >> have a single interface per uclass, since it is simpler to understand, >> no need to request a protocol for a device, etc. >> >> Our current setup is similar to this >> >> |-- Controller (UCLASS_MMC) >> | |-- Block device (UCLASS_BLK) - 'usual' HW partition >> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* >> >> * although I don't think the MMC code actually supports it - SCSI does though >> >> We want to add devices for the partition table and the filesystem, so could do: >> >> |-- Controller (UCLASS_MMC) >> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) >> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) >> | | | |-- Block device (UCLASS_BLK) - partition 1 >> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem >> | | | |-- Block device (UCLASS_BLK) - partition 2 >> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem >> | |-- Block device (UCLASS_BLK) - e.g. for a different HW >> partition (the whole device) >> >> This is similar to Heinrich's, but without the top-level >> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. > > Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices?
Yes. What I meant to say is that, if we don't need a partition table 'udevice' for hw partitions, we don't need such a device for sw partitions neither.
Meanwhile, what about UCLASS_FS? Why do we need this?
We don't need it for our current discussion, but if we want to 'open' the filesystem and keep the metadata around, rather than reading it again every time we access a file, we might find it useful. Open files could be children of the FS uclass, perhaps, if we go a step further and create devices for them.
Do you want to invent linux-like mount-point concepts or procfs? I remember that you didn't want to have child nodes under BLK devices. I'm getting confused about our goal.
I think we are all a bit unsure.
I think BLK devices can have children, sorry if I said the wrong thing somewhere along the way. For example, a partition would be under a BLK device, or a FS.
What should DM represent in U-Boot world?
That is what we are trying to figure out.
I think the minimum is to have a a way to represent partitions (s/w and hw/). As I understand it, that's what we've been discussing.
The discovery of hardware partitions is specific to the block device controller SCSI/MMC/ATA/NVMe. We currently do not provide any manipulation commands to create hardware partitions (e.g. NVMe namespaces, SCSI LUNs). This is why extracting a uclass for hardware partitions does not seem necessary.
I can see the reasoning here. It might not stand the test of time but how about we go with it for now? For MMC hardware partition we would just end up with multiple BLK devices, like we do with SCSI LUNs at present, which seems like it should work (with some code tweaks).
Software partitioning (MBR, GPT, ...) is independent of the harboring block device.
We already have a set of drivers for software partition tables in disk/. Currently the available methods of the drivers are defined in U_BOOT_PART_TYPE referring to struct part_driver.
Currently struct part_driver knows only the following methods:
- get_info()
- print()
- test()
These drivers should be ome a uclass.
gpt.c and mbr.c allow to create and delete partitions. I think we should add
- create_partition()
- delete_partition()
to the uclass methods.
That sounds good to me, although since it is a partition uclass, we can just use create() and delete().
I don't know why we need a "partition table" device in the middle of DM hierarchy. I believe that it simply makes the view of DM tree complicated without any explicit benefit.
-Takahiro Akashi
The partitions handled by cmd/mtdparts.c, cmd/nand.c are also software partitions. The difference to MBR, GPT is that the partition table is held in memory and not on disk. These partitions could be modeled in the same uclass.
For future work!
Regards, SImon
>> >> It is compatible with what we have now and we could enable/disable the >> extra devices with a Kconfig. >> >> Regards, >> Simon >> >> >> >>>> >>>>> UCLASS_PARTITION_TABLE would be for the drivers in disk/. >>>>> UCLASS_FS would be for the drivers in fs/. >>>>> UCLASS_BLK will be for any objects exposing raw block IO. A software >>>>> partition does the same. It is created by the partition table driver as >>>>> child of the partition table udevice. >>>>> >>>>> In this model an eMMC device will not be a UCLASS_BLK device because it >>>>> does not expose block IO. It is the hardware partition that exposes this >>>>> interface. >>>>> >>>>> The suggested model will allow a clean description of nested partition >>>>> tables. >>>>> >>>>> In the UEFI world the software partition and its file system must be >>>>> mapped to a single handle with device path node type HD(). For the >>>>> parent block device we may create a child handle with partition number 0 >>>>> (HD(0)). For the partition table we will not create a handle. >>>>> >>>>> Best regards >>>>> >>>>> Heinrich

Hi Takahiro,
On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote:
Hi,
On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 11/1/21 03:14, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: >> >> >> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: >>> Hi, >>> >>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >>>> >>>> >>>> >>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >>>>>> >>>>>> >>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both >>>>>>> in name and meaning. I think maybe I am missing the gist of your >>>>>>> argument. >>>>>>> >>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w >>>>>>> and h/w partitions, as Herinch seems to allude to below? What would >>>>>>> the picture look like the, and would it get us closer to agreement? >>>>>> >>>>>> In the driver model: >>>>>> >>>>>> A UCLASS is a class of drivers that share the same interface. >>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >>>>>> accessed through this UCLASS's interface. >>>>> >>>>> Please be careful about "accessed through" which is a quite confusing >>>>> expression. I don't always agree with this view. >>>>> >>>>>> A hardware partition is an object that exposes only a single interface >>>>>> for block IO. >>>>>> >>>>>> A software partition is an object that may expose two interfaces: one >>>>>> for block IO, the other for file IO. >>>>> >>>>> Are you talking about UEFI world or U-Boot? >>>>> Definitely, a hw partitions can provide a file system >>>>> if you want. >>>>> It's a matter of usage. >>>>> >>>>> I remember that we had some discussion about whether block devices >>>>> on UEFI system should always have a (sw) partition table or not. >>>>> But it is a different topic. >>>>> >>>>>> The UEFI model does not have a problem with this because on a handle you >>>>>> can install as many different protocols as you wish. But U-Boot's driver >>>>>> model only allows a single interface per device. Up to now U-Boot has >>>>>> overcome this limitation by creating child devices for the extra interfaces. >>>>> >>>>>> We have the following logical levels: >>>>>> >>>>>> Controller | Block device | Software Partition| File system >>>>>> ----------------+--------------+-------------------+------------ >>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >>>>>> ATA Controller | ATA-Drive | | >>>>>> SCSI Controller | LUN | | >>>>>> MMC Controller | HW-Partition | | >>>>>> MMC Controller | SD-Card | | >>>>>> USB-Node | USB-Drive | | >>>>>> >>>>>> In the device tree this could be modeled as: >>>>>> >>>>>> |-- Controller (UCLASS_CTRL) >>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) >>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>> | | |-- File system (UCLASS_FS) >>>>>> | | >>>>>> | |-- Block device (UCLASS_BLK) >>>>>> | |-- File system (UCLASS_FS) >>>>> >>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >>>>> What is the benefit? >>>>> (A) and (B) always have 1:1 relationship. >>>> >>>> No. You can have a bare device without a partition table. >>> >>> I can have a DOS partition that covers the whole device, without a >>> partition table. This is supported in U-Boot and Linux. >>> >>>> >>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. >>>> >>>>> I also remember that you claimed that not all efi objects(handles and >>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >>>>> U-Boot counterparts in our 2019 discussion. >>>>> >>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >>>>> which should support other type of hw partitions as well? >>>> >>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. >>>> >>>>> >>>>> |-- eMMC controller (UCLASS_MMC) >>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) >>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>> | | |-- Software Partition (UCLASS_BLK) >>>>> | | |-- File system (UCLASS_FS) >>>>> | | >>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) >>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) >>>>> ... >>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>> >>>>> |-- scsi controller (UCLASS_SCSI) >>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>> | | |-- Software Partition (UCLASS_BLK) >>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) >>>>> ... >>>>> >>>>> (Here I ignored scsi buses/channels which make things more complicated.) >>>>> >>>>> This kind of complex hierarchy doesn't benefit anybody. >>>> >>>> All these levels exist already. We simply do not model them yet in the DM way. >>>> >>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. >>>> >>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. >>> >>> Yes, the complexity has to go somewhere. With driver model I chose to >>> have a single interface per uclass, since it is simpler to understand, >>> no need to request a protocol for a device, etc. >>> >>> Our current setup is similar to this >>> >>> |-- Controller (UCLASS_MMC) >>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition >>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* >>> >>> * although I don't think the MMC code actually supports it - SCSI does though >>> >>> We want to add devices for the partition table and the filesystem, so could do: >>> >>> |-- Controller (UCLASS_MMC) >>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) >>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) >>> | | | |-- Block device (UCLASS_BLK) - partition 1 >>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem >>> | | | |-- Block device (UCLASS_BLK) - partition 2 >>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem >>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW >>> partition (the whole device) >>> >>> This is similar to Heinrich's, but without the top-level >>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. >> >> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? > > Yes. > What I meant to say is that, if we don't need a partition table 'udevice' > for hw partitions, we don't need such a device for sw partitions neither. > > Meanwhile, what about UCLASS_FS? Why do we need this?
We don't need it for our current discussion, but if we want to 'open' the filesystem and keep the metadata around, rather than reading it again every time we access a file, we might find it useful. Open files could be children of the FS uclass, perhaps, if we go a step further and create devices for them.
Do you want to invent linux-like mount-point concepts or procfs? I remember that you didn't want to have child nodes under BLK devices. I'm getting confused about our goal.
I think we are all a bit unsure.
I think BLK devices can have children, sorry if I said the wrong thing somewhere along the way. For example, a partition would be under a BLK device, or a FS.
What should DM represent in U-Boot world?
That is what we are trying to figure out.
I think the minimum is to have a a way to represent partitions (s/w and hw/). As I understand it, that's what we've been discussing.
The discovery of hardware partitions is specific to the block device controller SCSI/MMC/ATA/NVMe. We currently do not provide any manipulation commands to create hardware partitions (e.g. NVMe namespaces, SCSI LUNs). This is why extracting a uclass for hardware partitions does not seem necessary.
I can see the reasoning here. It might not stand the test of time but how about we go with it for now? For MMC hardware partition we would just end up with multiple BLK devices, like we do with SCSI LUNs at present, which seems like it should work (with some code tweaks).
Software partitioning (MBR, GPT, ...) is independent of the harboring block device.
We already have a set of drivers for software partition tables in disk/. Currently the available methods of the drivers are defined in U_BOOT_PART_TYPE referring to struct part_driver.
Currently struct part_driver knows only the following methods:
- get_info()
- print()
- test()
These drivers should be ome a uclass.
gpt.c and mbr.c allow to create and delete partitions. I think we should add
- create_partition()
- delete_partition()
to the uclass methods.
That sounds good to me, although since it is a partition uclass, we can just use create() and delete().
I don't know why we need a "partition table" device in the middle of DM hierarchy. I believe that it simply makes the view of DM tree complicated without any explicit benefit.
Well we clearly have an API here. The partition uclass can:
- hold the partition table in dev_get_uclass_priv() - support a read() operation to read the partition - support create() to rewrite the partition table - support delete() to overwrite/erase the partition table
Then it means that filesystems have the partition table as a parent (unless they are whole-device filesystems), which makes sense
So that's why I like the idea.
Other than the extra complexity, is there anything else wrong with it?
Regards, Simon
-Takahiro Akashi
The partitions handled by cmd/mtdparts.c, cmd/nand.c are also software partitions. The difference to MBR, GPT is that the partition table is held in memory and not on disk. These partitions could be modeled in the same uclass.
For future work!
Regards, SImon
>>> >>> It is compatible with what we have now and we could enable/disable the >>> extra devices with a Kconfig. >>> >>> Regards, >>> Simon >>> >>> >>> >>>>> >>>>>> UCLASS_PARTITION_TABLE would be for the drivers in disk/. >>>>>> UCLASS_FS would be for the drivers in fs/. >>>>>> UCLASS_BLK will be for any objects exposing raw block IO. A software >>>>>> partition does the same. It is created by the partition table driver as >>>>>> child of the partition table udevice. >>>>>> >>>>>> In this model an eMMC device will not be a UCLASS_BLK device because it >>>>>> does not expose block IO. It is the hardware partition that exposes this >>>>>> interface. >>>>>> >>>>>> The suggested model will allow a clean description of nested partition >>>>>> tables. >>>>>> >>>>>> In the UEFI world the software partition and its file system must be >>>>>> mapped to a single handle with device path node type HD(). For the >>>>>> parent block device we may create a child handle with partition number 0 >>>>>> (HD(0)). For the partition table we will not create a handle. >>>>>> >>>>>> Best regards >>>>>> >>>>>> Heinrich

On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote:
Hi,
On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 11/1/21 03:14, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: > Hi Takahiro, > > On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro > takahiro.akashi@linaro.org wrote: >> >> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: >>> >>> >>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: >>>> Hi, >>>> >>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >>>>> >>>>> >>>>> >>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >>>>>>> >>>>>>> >>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both >>>>>>>> in name and meaning. I think maybe I am missing the gist of your >>>>>>>> argument. >>>>>>>> >>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w >>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would >>>>>>>> the picture look like the, and would it get us closer to agreement? >>>>>>> >>>>>>> In the driver model: >>>>>>> >>>>>>> A UCLASS is a class of drivers that share the same interface. >>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >>>>>>> accessed through this UCLASS's interface. >>>>>> >>>>>> Please be careful about "accessed through" which is a quite confusing >>>>>> expression. I don't always agree with this view. >>>>>> >>>>>>> A hardware partition is an object that exposes only a single interface >>>>>>> for block IO. >>>>>>> >>>>>>> A software partition is an object that may expose two interfaces: one >>>>>>> for block IO, the other for file IO. >>>>>> >>>>>> Are you talking about UEFI world or U-Boot? >>>>>> Definitely, a hw partitions can provide a file system >>>>>> if you want. >>>>>> It's a matter of usage. >>>>>> >>>>>> I remember that we had some discussion about whether block devices >>>>>> on UEFI system should always have a (sw) partition table or not. >>>>>> But it is a different topic. >>>>>> >>>>>>> The UEFI model does not have a problem with this because on a handle you >>>>>>> can install as many different protocols as you wish. But U-Boot's driver >>>>>>> model only allows a single interface per device. Up to now U-Boot has >>>>>>> overcome this limitation by creating child devices for the extra interfaces. >>>>>> >>>>>>> We have the following logical levels: >>>>>>> >>>>>>> Controller | Block device | Software Partition| File system >>>>>>> ----------------+--------------+-------------------+------------ >>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >>>>>>> ATA Controller | ATA-Drive | | >>>>>>> SCSI Controller | LUN | | >>>>>>> MMC Controller | HW-Partition | | >>>>>>> MMC Controller | SD-Card | | >>>>>>> USB-Node | USB-Drive | | >>>>>>> >>>>>>> In the device tree this could be modeled as: >>>>>>> >>>>>>> |-- Controller (UCLASS_CTRL) >>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) >>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>> | | |-- File system (UCLASS_FS) >>>>>>> | | >>>>>>> | |-- Block device (UCLASS_BLK) >>>>>>> | |-- File system (UCLASS_FS) >>>>>> >>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >>>>>> What is the benefit? >>>>>> (A) and (B) always have 1:1 relationship. >>>>> >>>>> No. You can have a bare device without a partition table. >>>> >>>> I can have a DOS partition that covers the whole device, without a >>>> partition table. This is supported in U-Boot and Linux. >>>> >>>>> >>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. >>>>> >>>>>> I also remember that you claimed that not all efi objects(handles and >>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >>>>>> U-Boot counterparts in our 2019 discussion. >>>>>> >>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >>>>>> which should support other type of hw partitions as well? >>>>> >>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. >>>>> >>>>>> >>>>>> |-- eMMC controller (UCLASS_MMC) >>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) >>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>> | | |-- File system (UCLASS_FS) >>>>>> | | >>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) >>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) >>>>>> ... >>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>> >>>>>> |-- scsi controller (UCLASS_SCSI) >>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) >>>>>> ... >>>>>> >>>>>> (Here I ignored scsi buses/channels which make things more complicated.) >>>>>> >>>>>> This kind of complex hierarchy doesn't benefit anybody. >>>>> >>>>> All these levels exist already. We simply do not model them yet in the DM way. >>>>> >>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. >>>>> >>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. >>>> >>>> Yes, the complexity has to go somewhere. With driver model I chose to >>>> have a single interface per uclass, since it is simpler to understand, >>>> no need to request a protocol for a device, etc. >>>> >>>> Our current setup is similar to this >>>> >>>> |-- Controller (UCLASS_MMC) >>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition >>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* >>>> >>>> * although I don't think the MMC code actually supports it - SCSI does though >>>> >>>> We want to add devices for the partition table and the filesystem, so could do: >>>> >>>> |-- Controller (UCLASS_MMC) >>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) >>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) >>>> | | | |-- Block device (UCLASS_BLK) - partition 1 >>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem >>>> | | | |-- Block device (UCLASS_BLK) - partition 2 >>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem >>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW >>>> partition (the whole device) >>>> >>>> This is similar to Heinrich's, but without the top-level >>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. >>> >>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? >> >> Yes. >> What I meant to say is that, if we don't need a partition table 'udevice' >> for hw partitions, we don't need such a device for sw partitions neither. >> >> Meanwhile, what about UCLASS_FS? Why do we need this? > > We don't need it for our current discussion, but if we want to 'open' > the filesystem and keep the metadata around, rather than reading it > again every time we access a file, we might find it useful. Open files > could be children of the FS uclass, perhaps, if we go a step further > and create devices for them.
Do you want to invent linux-like mount-point concepts or procfs? I remember that you didn't want to have child nodes under BLK devices. I'm getting confused about our goal.
I think we are all a bit unsure.
I think BLK devices can have children, sorry if I said the wrong thing somewhere along the way. For example, a partition would be under a BLK device, or a FS.
What should DM represent in U-Boot world?
That is what we are trying to figure out.
I think the minimum is to have a a way to represent partitions (s/w and hw/). As I understand it, that's what we've been discussing.
The discovery of hardware partitions is specific to the block device controller SCSI/MMC/ATA/NVMe. We currently do not provide any manipulation commands to create hardware partitions (e.g. NVMe namespaces, SCSI LUNs). This is why extracting a uclass for hardware partitions does not seem necessary.
I can see the reasoning here. It might not stand the test of time but how about we go with it for now? For MMC hardware partition we would just end up with multiple BLK devices, like we do with SCSI LUNs at present, which seems like it should work (with some code tweaks).
Software partitioning (MBR, GPT, ...) is independent of the harboring block device.
We already have a set of drivers for software partition tables in disk/. Currently the available methods of the drivers are defined in U_BOOT_PART_TYPE referring to struct part_driver.
Currently struct part_driver knows only the following methods:
- get_info()
- print()
- test()
These drivers should be ome a uclass.
gpt.c and mbr.c allow to create and delete partitions. I think we should add
- create_partition()
- delete_partition()
to the uclass methods.
That sounds good to me, although since it is a partition uclass, we can just use create() and delete().
I don't know why we need a "partition table" device in the middle of DM hierarchy. I believe that it simply makes the view of DM tree complicated without any explicit benefit.
Well we clearly have an API here. The partition uclass can:
- hold the partition table in dev_get_uclass_priv()
- support a read() operation to read the partition
- support create() to rewrite the partition table
- support delete() to overwrite/erase the partition table
Then it means that filesystems have the partition table as a parent (unless they are whole-device filesystems), which makes sense
So that's why I like the idea.
Other than the extra complexity, is there anything else wrong with it?
- First of all, a partition table doesn't look like a 'device' at all. - Second, a partition table is just static data for block devices. IMO, even if we want to have this data, we can simply hold it as some sort of attribute of the device, or maybe as a 'tag' which I will introduce in the next version.
-Takahiro Akashi
Regards, Simon
-Takahiro Akashi
The partitions handled by cmd/mtdparts.c, cmd/nand.c are also software partitions. The difference to MBR, GPT is that the partition table is held in memory and not on disk. These partitions could be modeled in the same uclass.
For future work!
Regards, SImon
> >>>> >>>> It is compatible with what we have now and we could enable/disable the >>>> extra devices with a Kconfig. >>>> >>>> Regards, >>>> Simon >>>> >>>> >>>> >>>>>> >>>>>>> UCLASS_PARTITION_TABLE would be for the drivers in disk/. >>>>>>> UCLASS_FS would be for the drivers in fs/. >>>>>>> UCLASS_BLK will be for any objects exposing raw block IO. A software >>>>>>> partition does the same. It is created by the partition table driver as >>>>>>> child of the partition table udevice. >>>>>>> >>>>>>> In this model an eMMC device will not be a UCLASS_BLK device because it >>>>>>> does not expose block IO. It is the hardware partition that exposes this >>>>>>> interface. >>>>>>> >>>>>>> The suggested model will allow a clean description of nested partition >>>>>>> tables. >>>>>>> >>>>>>> In the UEFI world the software partition and its file system must be >>>>>>> mapped to a single handle with device path node type HD(). For the >>>>>>> parent block device we may create a child handle with partition number 0 >>>>>>> (HD(0)). For the partition table we will not create a handle. >>>>>>> >>>>>>> Best regards >>>>>>> >>>>>>> Heinrich

Hi chiming in a little late but
On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote:
Hi,
On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 11/1/21 03:14, Simon Glass wrote:
Hi Takahiro,
On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: >> Hi Takahiro, >> >> On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro >> takahiro.akashi@linaro.org wrote: >>> >>> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: >>>> >>>> >>>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: >>>>> Hi, >>>>> >>>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >>>>>> >>>>>> >>>>>> >>>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >>>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >>>>>>>> >>>>>>>> >>>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both >>>>>>>>> in name and meaning. I think maybe I am missing the gist of your >>>>>>>>> argument. >>>>>>>>> >>>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w >>>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would >>>>>>>>> the picture look like the, and would it get us closer to agreement? >>>>>>>> >>>>>>>> In the driver model: >>>>>>>> >>>>>>>> A UCLASS is a class of drivers that share the same interface. >>>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >>>>>>>> accessed through this UCLASS's interface. >>>>>>> >>>>>>> Please be careful about "accessed through" which is a quite confusing >>>>>>> expression. I don't always agree with this view. >>>>>>> >>>>>>>> A hardware partition is an object that exposes only a single interface >>>>>>>> for block IO. >>>>>>>> >>>>>>>> A software partition is an object that may expose two interfaces: one >>>>>>>> for block IO, the other for file IO. >>>>>>> >>>>>>> Are you talking about UEFI world or U-Boot? >>>>>>> Definitely, a hw partitions can provide a file system >>>>>>> if you want. >>>>>>> It's a matter of usage. >>>>>>> >>>>>>> I remember that we had some discussion about whether block devices >>>>>>> on UEFI system should always have a (sw) partition table or not. >>>>>>> But it is a different topic. >>>>>>> >>>>>>>> The UEFI model does not have a problem with this because on a handle you >>>>>>>> can install as many different protocols as you wish. But U-Boot's driver >>>>>>>> model only allows a single interface per device. Up to now U-Boot has >>>>>>>> overcome this limitation by creating child devices for the extra interfaces. >>>>>>> >>>>>>>> We have the following logical levels: >>>>>>>> >>>>>>>> Controller | Block device | Software Partition| File system >>>>>>>> ----------------+--------------+-------------------+------------ >>>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >>>>>>>> ATA Controller | ATA-Drive | | >>>>>>>> SCSI Controller | LUN | | >>>>>>>> MMC Controller | HW-Partition | | >>>>>>>> MMC Controller | SD-Card | | >>>>>>>> USB-Node | USB-Drive | | >>>>>>>> >>>>>>>> In the device tree this could be modeled as: >>>>>>>> >>>>>>>> |-- Controller (UCLASS_CTRL) >>>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >>>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>>> | | |-- File system (UCLASS_FS) >>>>>>>> | | >>>>>>>> | |-- Block device (UCLASS_BLK) >>>>>>>> | |-- File system (UCLASS_FS) >>>>>>> >>>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >>>>>>> What is the benefit? >>>>>>> (A) and (B) always have 1:1 relationship. >>>>>> >>>>>> No. You can have a bare device without a partition table. >>>>> >>>>> I can have a DOS partition that covers the whole device, without a >>>>> partition table. This is supported in U-Boot and Linux. >>>>> >>>>>> >>>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. >>>>>> >>>>>>> I also remember that you claimed that not all efi objects(handles and >>>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >>>>>>> U-Boot counterparts in our 2019 discussion. >>>>>>> >>>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >>>>>>> which should support other type of hw partitions as well? >>>>>> >>>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. >>>>>> >>>>>>> >>>>>>> |-- eMMC controller (UCLASS_MMC) >>>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) >>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>> | | |-- File system (UCLASS_FS) >>>>>>> | | >>>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) >>>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) >>>>>>> ... >>>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>> >>>>>>> |-- scsi controller (UCLASS_SCSI) >>>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) >>>>>>> ... >>>>>>> >>>>>>> (Here I ignored scsi buses/channels which make things more complicated.) >>>>>>> >>>>>>> This kind of complex hierarchy doesn't benefit anybody. >>>>>> >>>>>> All these levels exist already. We simply do not model them yet in the DM way. >>>>>> >>>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. >>>>>> >>>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. >>>>> >>>>> Yes, the complexity has to go somewhere. With driver model I chose to >>>>> have a single interface per uclass, since it is simpler to understand, >>>>> no need to request a protocol for a device, etc. >>>>> >>>>> Our current setup is similar to this >>>>> >>>>> |-- Controller (UCLASS_MMC) >>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition >>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* >>>>> >>>>> * although I don't think the MMC code actually supports it - SCSI does though >>>>> >>>>> We want to add devices for the partition table and the filesystem, so could do: >>>>> >>>>> |-- Controller (UCLASS_MMC) >>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) >>>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) >>>>> | | | |-- Block device (UCLASS_BLK) - partition 1 >>>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem >>>>> | | | |-- Block device (UCLASS_BLK) - partition 2 >>>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem >>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW >>>>> partition (the whole device) >>>>> >>>>> This is similar to Heinrich's, but without the top-level >>>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. >>>> >>>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? >>> >>> Yes. >>> What I meant to say is that, if we don't need a partition table 'udevice' >>> for hw partitions, we don't need such a device for sw partitions neither. >>> >>> Meanwhile, what about UCLASS_FS? Why do we need this? >> >> We don't need it for our current discussion, but if we want to 'open' >> the filesystem and keep the metadata around, rather than reading it >> again every time we access a file, we might find it useful. Open files >> could be children of the FS uclass, perhaps, if we go a step further >> and create devices for them. > > Do you want to invent linux-like mount-point concepts or procfs? > I remember that you didn't want to have child nodes under BLK devices. > I'm getting confused about our goal.
I think we are all a bit unsure.
I think BLK devices can have children, sorry if I said the wrong thing somewhere along the way. For example, a partition would be under a BLK device, or a FS.
> What should DM represent in U-Boot world?
That is what we are trying to figure out.
I think the minimum is to have a a way to represent partitions (s/w and hw/). As I understand it, that's what we've been discussing.
The discovery of hardware partitions is specific to the block device controller SCSI/MMC/ATA/NVMe. We currently do not provide any manipulation commands to create hardware partitions (e.g. NVMe namespaces, SCSI LUNs). This is why extracting a uclass for hardware partitions does not seem necessary.
I can see the reasoning here. It might not stand the test of time but how about we go with it for now? For MMC hardware partition we would just end up with multiple BLK devices, like we do with SCSI LUNs at present, which seems like it should work (with some code tweaks).
Software partitioning (MBR, GPT, ...) is independent of the harboring block device.
We already have a set of drivers for software partition tables in disk/. Currently the available methods of the drivers are defined in U_BOOT_PART_TYPE referring to struct part_driver.
Currently struct part_driver knows only the following methods:
- get_info()
- print()
- test()
These drivers should be ome a uclass.
gpt.c and mbr.c allow to create and delete partitions. I think we should add
- create_partition()
- delete_partition()
to the uclass methods.
That sounds good to me, although since it is a partition uclass, we can just use create() and delete().
I don't know why we need a "partition table" device in the middle of DM hierarchy. I believe that it simply makes the view of DM tree complicated without any explicit benefit.
Well we clearly have an API here. The partition uclass can:
- hold the partition table in dev_get_uclass_priv()
- support a read() operation to read the partition
- support create() to rewrite the partition table
- support delete() to overwrite/erase the partition table
Then it means that filesystems have the partition table as a parent (unless they are whole-device filesystems), which makes sense
So that's why I like the idea.
Other than the extra complexity, is there anything else wrong with it?
- First of all, a partition table doesn't look like a 'device' at all.
- Second, a partition table is just static data for block devices. IMO, even if we want to have this data, we can simply hold it as some sort of attribute of the device, or maybe as a 'tag' which I will introduce in the next version.
-Takahiro Akashi
I don't know how this affect the code, but I agree with Akashi-san here. It's indeed useful to keep the partition table stored somewhere, but I think not showing them as part of the device tree is more intuitive.
Thanks /Ilias [...]

Hi,
On Mon, 8 Nov 2021 at 11:45, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi chiming in a little late but
On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote:
Hi,
On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 11/1/21 03:14, Simon Glass wrote: > Hi Takahiro, > > On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro > takahiro.akashi@linaro.org wrote: >> >> On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: >>> Hi Takahiro, >>> >>> On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro >>> takahiro.akashi@linaro.org wrote: >>>> >>>> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: >>>>> >>>>> >>>>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: >>>>>> Hi, >>>>>> >>>>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >>>>>>> >>>>>>> >>>>>>> >>>>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >>>>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both >>>>>>>>>> in name and meaning. I think maybe I am missing the gist of your >>>>>>>>>> argument. >>>>>>>>>> >>>>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w >>>>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would >>>>>>>>>> the picture look like the, and would it get us closer to agreement? >>>>>>>>> >>>>>>>>> In the driver model: >>>>>>>>> >>>>>>>>> A UCLASS is a class of drivers that share the same interface. >>>>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >>>>>>>>> accessed through this UCLASS's interface. >>>>>>>> >>>>>>>> Please be careful about "accessed through" which is a quite confusing >>>>>>>> expression. I don't always agree with this view. >>>>>>>> >>>>>>>>> A hardware partition is an object that exposes only a single interface >>>>>>>>> for block IO. >>>>>>>>> >>>>>>>>> A software partition is an object that may expose two interfaces: one >>>>>>>>> for block IO, the other for file IO. >>>>>>>> >>>>>>>> Are you talking about UEFI world or U-Boot? >>>>>>>> Definitely, a hw partitions can provide a file system >>>>>>>> if you want. >>>>>>>> It's a matter of usage. >>>>>>>> >>>>>>>> I remember that we had some discussion about whether block devices >>>>>>>> on UEFI system should always have a (sw) partition table or not. >>>>>>>> But it is a different topic. >>>>>>>> >>>>>>>>> The UEFI model does not have a problem with this because on a handle you >>>>>>>>> can install as many different protocols as you wish. But U-Boot's driver >>>>>>>>> model only allows a single interface per device. Up to now U-Boot has >>>>>>>>> overcome this limitation by creating child devices for the extra interfaces. >>>>>>>> >>>>>>>>> We have the following logical levels: >>>>>>>>> >>>>>>>>> Controller | Block device | Software Partition| File system >>>>>>>>> ----------------+--------------+-------------------+------------ >>>>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >>>>>>>>> ATA Controller | ATA-Drive | | >>>>>>>>> SCSI Controller | LUN | | >>>>>>>>> MMC Controller | HW-Partition | | >>>>>>>>> MMC Controller | SD-Card | | >>>>>>>>> USB-Node | USB-Drive | | >>>>>>>>> >>>>>>>>> In the device tree this could be modeled as: >>>>>>>>> >>>>>>>>> |-- Controller (UCLASS_CTRL) >>>>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) >>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >>>>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>>>> | | |-- File system (UCLASS_FS) >>>>>>>>> | | >>>>>>>>> | |-- Block device (UCLASS_BLK) >>>>>>>>> | |-- File system (UCLASS_FS) >>>>>>>> >>>>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >>>>>>>> What is the benefit? >>>>>>>> (A) and (B) always have 1:1 relationship. >>>>>>> >>>>>>> No. You can have a bare device without a partition table. >>>>>> >>>>>> I can have a DOS partition that covers the whole device, without a >>>>>> partition table. This is supported in U-Boot and Linux. >>>>>> >>>>>>> >>>>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. >>>>>>> >>>>>>>> I also remember that you claimed that not all efi objects(handles and >>>>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >>>>>>>> U-Boot counterparts in our 2019 discussion. >>>>>>>> >>>>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >>>>>>>> which should support other type of hw partitions as well? >>>>>>> >>>>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. >>>>>>> >>>>>>>> >>>>>>>> |-- eMMC controller (UCLASS_MMC) >>>>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>>> | | |-- File system (UCLASS_FS) >>>>>>>> | | >>>>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) >>>>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) >>>>>>>> ... >>>>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>>> >>>>>>>> |-- scsi controller (UCLASS_SCSI) >>>>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) >>>>>>>> ... >>>>>>>> >>>>>>>> (Here I ignored scsi buses/channels which make things more complicated.) >>>>>>>> >>>>>>>> This kind of complex hierarchy doesn't benefit anybody. >>>>>>> >>>>>>> All these levels exist already. We simply do not model them yet in the DM way. >>>>>>> >>>>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. >>>>>>> >>>>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. >>>>>> >>>>>> Yes, the complexity has to go somewhere. With driver model I chose to >>>>>> have a single interface per uclass, since it is simpler to understand, >>>>>> no need to request a protocol for a device, etc. >>>>>> >>>>>> Our current setup is similar to this >>>>>> >>>>>> |-- Controller (UCLASS_MMC) >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* >>>>>> >>>>>> * although I don't think the MMC code actually supports it - SCSI does though >>>>>> >>>>>> We want to add devices for the partition table and the filesystem, so could do: >>>>>> >>>>>> |-- Controller (UCLASS_MMC) >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) >>>>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 1 >>>>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 2 >>>>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW >>>>>> partition (the whole device) >>>>>> >>>>>> This is similar to Heinrich's, but without the top-level >>>>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. >>>>> >>>>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? >>>> >>>> Yes. >>>> What I meant to say is that, if we don't need a partition table 'udevice' >>>> for hw partitions, we don't need such a device for sw partitions neither. >>>> >>>> Meanwhile, what about UCLASS_FS? Why do we need this? >>> >>> We don't need it for our current discussion, but if we want to 'open' >>> the filesystem and keep the metadata around, rather than reading it >>> again every time we access a file, we might find it useful. Open files >>> could be children of the FS uclass, perhaps, if we go a step further >>> and create devices for them. >> >> Do you want to invent linux-like mount-point concepts or procfs? >> I remember that you didn't want to have child nodes under BLK devices. >> I'm getting confused about our goal. > > I think we are all a bit unsure. > > I think BLK devices can have children, sorry if I said the wrong thing > somewhere along the way. For example, a partition would be under a BLK > device, or a FS. > >> What should DM represent in U-Boot world? > > That is what we are trying to figure out. > > I think the minimum is to have a a way to represent partitions (s/w > and hw/). As I understand it, that's what we've been discussing.
The discovery of hardware partitions is specific to the block device controller SCSI/MMC/ATA/NVMe. We currently do not provide any manipulation commands to create hardware partitions (e.g. NVMe namespaces, SCSI LUNs). This is why extracting a uclass for hardware partitions does not seem necessary.
I can see the reasoning here. It might not stand the test of time but how about we go with it for now? For MMC hardware partition we would just end up with multiple BLK devices, like we do with SCSI LUNs at present, which seems like it should work (with some code tweaks).
Software partitioning (MBR, GPT, ...) is independent of the harboring block device.
We already have a set of drivers for software partition tables in disk/. Currently the available methods of the drivers are defined in U_BOOT_PART_TYPE referring to struct part_driver.
Currently struct part_driver knows only the following methods:
- get_info()
- print()
- test()
These drivers should be ome a uclass.
gpt.c and mbr.c allow to create and delete partitions. I think we should add
- create_partition()
- delete_partition()
to the uclass methods.
That sounds good to me, although since it is a partition uclass, we can just use create() and delete().
I don't know why we need a "partition table" device in the middle of DM hierarchy. I believe that it simply makes the view of DM tree complicated without any explicit benefit.
Well we clearly have an API here. The partition uclass can:
- hold the partition table in dev_get_uclass_priv()
- support a read() operation to read the partition
- support create() to rewrite the partition table
- support delete() to overwrite/erase the partition table
Then it means that filesystems have the partition table as a parent (unless they are whole-device filesystems), which makes sense
So that's why I like the idea.
Other than the extra complexity, is there anything else wrong with it?
- First of all, a partition table doesn't look like a 'device' at all.
- Second, a partition table is just static data for block devices. IMO, even if we want to have this data, we can simply hold it as some sort of attribute of the device, or maybe as a 'tag' which I will introduce in the next version.
-Takahiro Akashi
I don't know how this affect the code, but I agree with Akashi-san here. It's indeed useful to keep the partition table stored somewhere, but I think not showing them as part of the device tree is more intuitive.
Well I think I'm easy either way. I just thought that Heinrich made a good case for having a partition uclass.
But as Takahiro says, we can use a tag to attach the partition table to the device. But it should be attached to the device's children (the BLK device) not the media device itself, right?
Regards, Simon

Hi,
On Mon, 8 Nov 2021 at 17:09, Simon Glass sjg@chromium.org wrote:
Hi,
On Mon, 8 Nov 2021 at 11:45, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi chiming in a little late but
On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote:
Hi,
On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > On 11/1/21 03:14, Simon Glass wrote: > > Hi Takahiro, > > > > On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro > > takahiro.akashi@linaro.org wrote: > >> > >> On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: > >>> Hi Takahiro, > >>> > >>> On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro > >>> takahiro.akashi@linaro.org wrote: > >>>> > >>>> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: > >>>>> > >>>>> > >>>>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: > >>>>>> Hi, > >>>>>> > >>>>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: > >>>>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both > >>>>>>>>>> in name and meaning. I think maybe I am missing the gist of your > >>>>>>>>>> argument. > >>>>>>>>>> > >>>>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w > >>>>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would > >>>>>>>>>> the picture look like the, and would it get us closer to agreement? > >>>>>>>>> > >>>>>>>>> In the driver model: > >>>>>>>>> > >>>>>>>>> A UCLASS is a class of drivers that share the same interface. > >>>>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is > >>>>>>>>> accessed through this UCLASS's interface. > >>>>>>>> > >>>>>>>> Please be careful about "accessed through" which is a quite confusing > >>>>>>>> expression. I don't always agree with this view. > >>>>>>>> > >>>>>>>>> A hardware partition is an object that exposes only a single interface > >>>>>>>>> for block IO. > >>>>>>>>> > >>>>>>>>> A software partition is an object that may expose two interfaces: one > >>>>>>>>> for block IO, the other for file IO. > >>>>>>>> > >>>>>>>> Are you talking about UEFI world or U-Boot? > >>>>>>>> Definitely, a hw partitions can provide a file system > >>>>>>>> if you want. > >>>>>>>> It's a matter of usage. > >>>>>>>> > >>>>>>>> I remember that we had some discussion about whether block devices > >>>>>>>> on UEFI system should always have a (sw) partition table or not. > >>>>>>>> But it is a different topic. > >>>>>>>> > >>>>>>>>> The UEFI model does not have a problem with this because on a handle you > >>>>>>>>> can install as many different protocols as you wish. But U-Boot's driver > >>>>>>>>> model only allows a single interface per device. Up to now U-Boot has > >>>>>>>>> overcome this limitation by creating child devices for the extra interfaces. > >>>>>>>> > >>>>>>>>> We have the following logical levels: > >>>>>>>>> > >>>>>>>>> Controller | Block device | Software Partition| File system > >>>>>>>>> ----------------+--------------+-------------------+------------ > >>>>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 > >>>>>>>>> ATA Controller | ATA-Drive | | > >>>>>>>>> SCSI Controller | LUN | | > >>>>>>>>> MMC Controller | HW-Partition | | > >>>>>>>>> MMC Controller | SD-Card | | > >>>>>>>>> USB-Node | USB-Drive | | > >>>>>>>>> > >>>>>>>>> In the device tree this could be modeled as: > >>>>>>>>> > >>>>>>>>> |-- Controller (UCLASS_CTRL) > >>>>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) > >>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) > >>>>>>>>> | | |-- Software Partition (UCLASS_BLK) > >>>>>>>>> | | |-- File system (UCLASS_FS) > >>>>>>>>> | | > >>>>>>>>> | |-- Block device (UCLASS_BLK) > >>>>>>>>> | |-- File system (UCLASS_FS) > >>>>>>>> > >>>>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. > >>>>>>>> What is the benefit? > >>>>>>>> (A) and (B) always have 1:1 relationship. > >>>>>>> > >>>>>>> No. You can have a bare device without a partition table. > >>>>>> > >>>>>> I can have a DOS partition that covers the whole device, without a > >>>>>> partition table. This is supported in U-Boot and Linux. > >>>>>> > >>>>>>> > >>>>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. > >>>>>>> > >>>>>>>> I also remember that you claimed that not all efi objects(handles and > >>>>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding > >>>>>>>> U-Boot counterparts in our 2019 discussion. > >>>>>>>> > >>>>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, > >>>>>>>> which should support other type of hw partitions as well? > >>>>>>> > >>>>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. > >>>>>>> > >>>>>>>> > >>>>>>>> |-- eMMC controller (UCLASS_MMC) > >>>>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) > >>>>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > >>>>>>>> | | |-- File system (UCLASS_FS) > >>>>>>>> | | > >>>>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) > >>>>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) > >>>>>>>> ... > >>>>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) > >>>>>>>> > >>>>>>>> |-- scsi controller (UCLASS_SCSI) > >>>>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) > >>>>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > >>>>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) > >>>>>>>> ... > >>>>>>>> > >>>>>>>> (Here I ignored scsi buses/channels which make things more complicated.) > >>>>>>>> > >>>>>>>> This kind of complex hierarchy doesn't benefit anybody. > >>>>>>> > >>>>>>> All these levels exist already. We simply do not model them yet in the DM way. > >>>>>>> > >>>>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. > >>>>>>> > >>>>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. > >>>>>> > >>>>>> Yes, the complexity has to go somewhere. With driver model I chose to > >>>>>> have a single interface per uclass, since it is simpler to understand, > >>>>>> no need to request a protocol for a device, etc. > >>>>>> > >>>>>> Our current setup is similar to this > >>>>>> > >>>>>> |-- Controller (UCLASS_MMC) > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* > >>>>>> > >>>>>> * although I don't think the MMC code actually supports it - SCSI does though > >>>>>> > >>>>>> We want to add devices for the partition table and the filesystem, so could do: > >>>>>> > >>>>>> |-- Controller (UCLASS_MMC) > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) > >>>>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 1 > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 2 > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW > >>>>>> partition (the whole device) > >>>>>> > >>>>>> This is similar to Heinrich's, but without the top-level > >>>>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. > >>>>> > >>>>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? > >>>> > >>>> Yes. > >>>> What I meant to say is that, if we don't need a partition table 'udevice' > >>>> for hw partitions, we don't need such a device for sw partitions neither. > >>>> > >>>> Meanwhile, what about UCLASS_FS? Why do we need this? > >>> > >>> We don't need it for our current discussion, but if we want to 'open' > >>> the filesystem and keep the metadata around, rather than reading it > >>> again every time we access a file, we might find it useful. Open files > >>> could be children of the FS uclass, perhaps, if we go a step further > >>> and create devices for them. > >> > >> Do you want to invent linux-like mount-point concepts or procfs? > >> I remember that you didn't want to have child nodes under BLK devices. > >> I'm getting confused about our goal. > > > > I think we are all a bit unsure. > > > > I think BLK devices can have children, sorry if I said the wrong thing > > somewhere along the way. For example, a partition would be under a BLK > > device, or a FS. > > > >> What should DM represent in U-Boot world? > > > > That is what we are trying to figure out. > > > > I think the minimum is to have a a way to represent partitions (s/w > > and hw/). As I understand it, that's what we've been discussing. > > The discovery of hardware partitions is specific to the block device > controller SCSI/MMC/ATA/NVMe. We currently do not provide any > manipulation commands to create hardware partitions (e.g. NVMe > namespaces, SCSI LUNs). This is why extracting a uclass for hardware > partitions does not seem necessary.
I can see the reasoning here. It might not stand the test of time but how about we go with it for now? For MMC hardware partition we would just end up with multiple BLK devices, like we do with SCSI LUNs at present, which seems like it should work (with some code tweaks).
> > Software partitioning (MBR, GPT, ...) is independent of the harboring > block device. > > We already have a set of drivers for software partition tables in disk/. > Currently the available methods of the drivers are defined in > U_BOOT_PART_TYPE referring to struct part_driver. > > Currently struct part_driver knows only the following methods: > > - get_info() > - print() > - test() > > These drivers should be ome a uclass. > > gpt.c and mbr.c allow to create and delete partitions. I think we should add > > - create_partition() > - delete_partition() > > to the uclass methods.
That sounds good to me, although since it is a partition uclass, we can just use create() and delete().
I don't know why we need a "partition table" device in the middle of DM hierarchy. I believe that it simply makes the view of DM tree complicated without any explicit benefit.
Well we clearly have an API here. The partition uclass can:
- hold the partition table in dev_get_uclass_priv()
- support a read() operation to read the partition
- support create() to rewrite the partition table
- support delete() to overwrite/erase the partition table
Then it means that filesystems have the partition table as a parent (unless they are whole-device filesystems), which makes sense
So that's why I like the idea.
Other than the extra complexity, is there anything else wrong with it?
- First of all, a partition table doesn't look like a 'device' at all.
- Second, a partition table is just static data for block devices. IMO, even if we want to have this data, we can simply hold it as some sort of attribute of the device, or maybe as a 'tag' which I will introduce in the next version.
-Takahiro Akashi
I don't know how this affect the code, but I agree with Akashi-san here. It's indeed useful to keep the partition table stored somewhere, but I think not showing them as part of the device tree is more intuitive.
Well I think I'm easy either way. I just thought that Heinrich made a good case for having a partition uclass.
But as Takahiro says, we can use a tag to attach the partition table to the device. But it should be attached to the device's children (the BLK device) not the media device itself, right?
As there has been no discussion in 5 days and Takahiro is writing this, let's go with no uclass for the partition table.
Regards, Simon

Am 13. November 2021 19:14:32 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Mon, 8 Nov 2021 at 17:09, Simon Glass sjg@chromium.org wrote:
Hi,
On Mon, 8 Nov 2021 at 11:45, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi chiming in a little late but
On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote: > Hi, > > On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > > > > > On 11/1/21 03:14, Simon Glass wrote: > > > Hi Takahiro, > > > > > > On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro > > > takahiro.akashi@linaro.org wrote: > > >> > > >> On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: > > >>> Hi Takahiro, > > >>> > > >>> On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro > > >>> takahiro.akashi@linaro.org wrote: > > >>>> > > >>>> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: > > >>>>> > > >>>>> > > >>>>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: > > >>>>>> Hi, > > >>>>>> > > >>>>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > >>>>>>> > > >>>>>>> > > >>>>>>> > > >>>>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: > > >>>>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: > > >>>>>>>>> > > >>>>>>>>> > > >>>>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both > > >>>>>>>>>> in name and meaning. I think maybe I am missing the gist of your > > >>>>>>>>>> argument. > > >>>>>>>>>> > > >>>>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w > > >>>>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would > > >>>>>>>>>> the picture look like the, and would it get us closer to agreement? > > >>>>>>>>> > > >>>>>>>>> In the driver model: > > >>>>>>>>> > > >>>>>>>>> A UCLASS is a class of drivers that share the same interface. > > >>>>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is > > >>>>>>>>> accessed through this UCLASS's interface. > > >>>>>>>> > > >>>>>>>> Please be careful about "accessed through" which is a quite confusing > > >>>>>>>> expression. I don't always agree with this view. > > >>>>>>>> > > >>>>>>>>> A hardware partition is an object that exposes only a single interface > > >>>>>>>>> for block IO. > > >>>>>>>>> > > >>>>>>>>> A software partition is an object that may expose two interfaces: one > > >>>>>>>>> for block IO, the other for file IO. > > >>>>>>>> > > >>>>>>>> Are you talking about UEFI world or U-Boot? > > >>>>>>>> Definitely, a hw partitions can provide a file system > > >>>>>>>> if you want. > > >>>>>>>> It's a matter of usage. > > >>>>>>>> > > >>>>>>>> I remember that we had some discussion about whether block devices > > >>>>>>>> on UEFI system should always have a (sw) partition table or not. > > >>>>>>>> But it is a different topic. > > >>>>>>>> > > >>>>>>>>> The UEFI model does not have a problem with this because on a handle you > > >>>>>>>>> can install as many different protocols as you wish. But U-Boot's driver > > >>>>>>>>> model only allows a single interface per device. Up to now U-Boot has > > >>>>>>>>> overcome this limitation by creating child devices for the extra interfaces. > > >>>>>>>> > > >>>>>>>>> We have the following logical levels: > > >>>>>>>>> > > >>>>>>>>> Controller | Block device | Software Partition| File system > > >>>>>>>>> ----------------+--------------+-------------------+------------ > > >>>>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 > > >>>>>>>>> ATA Controller | ATA-Drive | | > > >>>>>>>>> SCSI Controller | LUN | | > > >>>>>>>>> MMC Controller | HW-Partition | | > > >>>>>>>>> MMC Controller | SD-Card | | > > >>>>>>>>> USB-Node | USB-Drive | | > > >>>>>>>>> > > >>>>>>>>> In the device tree this could be modeled as: > > >>>>>>>>> > > >>>>>>>>> |-- Controller (UCLASS_CTRL) > > >>>>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) > > >>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) > > >>>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > >>>>>>>>> | | |-- File system (UCLASS_FS) > > >>>>>>>>> | | > > >>>>>>>>> | |-- Block device (UCLASS_BLK) > > >>>>>>>>> | |-- File system (UCLASS_FS) > > >>>>>>>> > > >>>>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. > > >>>>>>>> What is the benefit? > > >>>>>>>> (A) and (B) always have 1:1 relationship. > > >>>>>>> > > >>>>>>> No. You can have a bare device without a partition table. > > >>>>>> > > >>>>>> I can have a DOS partition that covers the whole device, without a > > >>>>>> partition table. This is supported in U-Boot and Linux. > > >>>>>> > > >>>>>>> > > >>>>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. > > >>>>>>> > > >>>>>>>> I also remember that you claimed that not all efi objects(handles and > > >>>>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding > > >>>>>>>> U-Boot counterparts in our 2019 discussion. > > >>>>>>>> > > >>>>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, > > >>>>>>>> which should support other type of hw partitions as well? > > >>>>>>> > > >>>>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. > > >>>>>>> > > >>>>>>>> > > >>>>>>>> |-- eMMC controller (UCLASS_MMC) > > >>>>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > >>>>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) > > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > >>>>>>>> | | |-- File system (UCLASS_FS) > > >>>>>>>> | | > > >>>>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) > > >>>>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) > > >>>>>>>> ... > > >>>>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > >>>>>>>> > > >>>>>>>> |-- scsi controller (UCLASS_SCSI) > > >>>>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) > > >>>>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) > > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > >>>>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) > > >>>>>>>> ... > > >>>>>>>> > > >>>>>>>> (Here I ignored scsi buses/channels which make things more complicated.) > > >>>>>>>> > > >>>>>>>> This kind of complex hierarchy doesn't benefit anybody. > > >>>>>>> > > >>>>>>> All these levels exist already. We simply do not model them yet in the DM way. > > >>>>>>> > > >>>>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. > > >>>>>>> > > >>>>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. > > >>>>>> > > >>>>>> Yes, the complexity has to go somewhere. With driver model I chose to > > >>>>>> have a single interface per uclass, since it is simpler to understand, > > >>>>>> no need to request a protocol for a device, etc. > > >>>>>> > > >>>>>> Our current setup is similar to this > > >>>>>> > > >>>>>> |-- Controller (UCLASS_MMC) > > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition > > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* > > >>>>>> > > >>>>>> * although I don't think the MMC code actually supports it - SCSI does though > > >>>>>> > > >>>>>> We want to add devices for the partition table and the filesystem, so could do: > > >>>>>> > > >>>>>> |-- Controller (UCLASS_MMC) > > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) > > >>>>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) > > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 1 > > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem > > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 2 > > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem > > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW > > >>>>>> partition (the whole device) > > >>>>>> > > >>>>>> This is similar to Heinrich's, but without the top-level > > >>>>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. > > >>>>> > > >>>>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? > > >>>> > > >>>> Yes. > > >>>> What I meant to say is that, if we don't need a partition table 'udevice' > > >>>> for hw partitions, we don't need such a device for sw partitions neither. > > >>>> > > >>>> Meanwhile, what about UCLASS_FS? Why do we need this? > > >>> > > >>> We don't need it for our current discussion, but if we want to 'open' > > >>> the filesystem and keep the metadata around, rather than reading it > > >>> again every time we access a file, we might find it useful. Open files > > >>> could be children of the FS uclass, perhaps, if we go a step further > > >>> and create devices for them. > > >> > > >> Do you want to invent linux-like mount-point concepts or procfs? > > >> I remember that you didn't want to have child nodes under BLK devices. > > >> I'm getting confused about our goal. > > > > > > I think we are all a bit unsure. > > > > > > I think BLK devices can have children, sorry if I said the wrong thing > > > somewhere along the way. For example, a partition would be under a BLK > > > device, or a FS. > > > > > >> What should DM represent in U-Boot world? > > > > > > That is what we are trying to figure out. > > > > > > I think the minimum is to have a a way to represent partitions (s/w > > > and hw/). As I understand it, that's what we've been discussing. > > > > The discovery of hardware partitions is specific to the block device > > controller SCSI/MMC/ATA/NVMe. We currently do not provide any > > manipulation commands to create hardware partitions (e.g. NVMe > > namespaces, SCSI LUNs). This is why extracting a uclass for hardware > > partitions does not seem necessary. > > I can see the reasoning here. It might not stand the test of time but > how about we go with it for now? For MMC hardware partition we would > just end up with multiple BLK devices, like we do with SCSI LUNs at > present, which seems like it should work (with some code tweaks). > > > > > Software partitioning (MBR, GPT, ...) is independent of the harboring > > block device. > > > > We already have a set of drivers for software partition tables in disk/. > > Currently the available methods of the drivers are defined in > > U_BOOT_PART_TYPE referring to struct part_driver. > > > > Currently struct part_driver knows only the following methods: > > > > - get_info() > > - print() > > - test() > > > > These drivers should be ome a uclass. > > > > gpt.c and mbr.c allow to create and delete partitions. I think we should add > > > > - create_partition() > > - delete_partition() > > > > to the uclass methods. > > That sounds good to me, although since it is a partition uclass, we > can just use create() and delete().
I don't know why we need a "partition table" device in the middle of DM hierarchy. I believe that it simply makes the view of DM tree complicated without any explicit benefit.
Well we clearly have an API here. The partition uclass can:
- hold the partition table in dev_get_uclass_priv()
- support a read() operation to read the partition
- support create() to rewrite the partition table
- support delete() to overwrite/erase the partition table
Then it means that filesystems have the partition table as a parent (unless they are whole-device filesystems), which makes sense
So that's why I like the idea.
Other than the extra complexity, is there anything else wrong with it?
- First of all, a partition table doesn't look like a 'device' at all.
- Second, a partition table is just static data for block devices. IMO, even if we want to have this data, we can simply hold it as some sort of attribute of the device, or maybe as a 'tag' which I will introduce in the next version.
-Takahiro Akashi
I don't know how this affect the code, but I agree with Akashi-san here. It's indeed useful to keep the partition table stored somewhere, but I think not showing them as part of the device tree is more intuitive.
Well I think I'm easy either way. I just thought that Heinrich made a good case for having a partition uclass.
But as Takahiro says, we can use a tag to attach the partition table to the device. But it should be attached to the device's children (the BLK device) not the media device itself, right?
As there has been no discussion in 5 days and Takahiro is writing this, let's go with no uclass for the partition table.
Without uclass you cannot bring the partition table drivers into th driver model.
No clue what a tag should be in the driver model.
Best regards
Heinrich
Regards, Simon

Hi Heinrich,
On Sat, 13 Nov 2021 at 11:42, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 13. November 2021 19:14:32 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Mon, 8 Nov 2021 at 17:09, Simon Glass sjg@chromium.org wrote:
Hi,
On Mon, 8 Nov 2021 at 11:45, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi chiming in a little late but
On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote: > > Hi, > > > > On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > > > > > > > > > On 11/1/21 03:14, Simon Glass wrote: > > > > Hi Takahiro, > > > > > > > > On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro > > > > takahiro.akashi@linaro.org wrote: > > > >> > > > >> On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: > > > >>> Hi Takahiro, > > > >>> > > > >>> On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro > > > >>> takahiro.akashi@linaro.org wrote: > > > >>>> > > > >>>> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: > > > >>>>> > > > >>>>> > > > >>>>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: > > > >>>>>> Hi, > > > >>>>>> > > > >>>>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > >>>>>>> > > > >>>>>>> > > > >>>>>>> > > > >>>>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: > > > >>>>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: > > > >>>>>>>>> > > > >>>>>>>>> > > > >>>>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both > > > >>>>>>>>>> in name and meaning. I think maybe I am missing the gist of your > > > >>>>>>>>>> argument. > > > >>>>>>>>>> > > > >>>>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w > > > >>>>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would > > > >>>>>>>>>> the picture look like the, and would it get us closer to agreement? > > > >>>>>>>>> > > > >>>>>>>>> In the driver model: > > > >>>>>>>>> > > > >>>>>>>>> A UCLASS is a class of drivers that share the same interface. > > > >>>>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is > > > >>>>>>>>> accessed through this UCLASS's interface. > > > >>>>>>>> > > > >>>>>>>> Please be careful about "accessed through" which is a quite confusing > > > >>>>>>>> expression. I don't always agree with this view. > > > >>>>>>>> > > > >>>>>>>>> A hardware partition is an object that exposes only a single interface > > > >>>>>>>>> for block IO. > > > >>>>>>>>> > > > >>>>>>>>> A software partition is an object that may expose two interfaces: one > > > >>>>>>>>> for block IO, the other for file IO. > > > >>>>>>>> > > > >>>>>>>> Are you talking about UEFI world or U-Boot? > > > >>>>>>>> Definitely, a hw partitions can provide a file system > > > >>>>>>>> if you want. > > > >>>>>>>> It's a matter of usage. > > > >>>>>>>> > > > >>>>>>>> I remember that we had some discussion about whether block devices > > > >>>>>>>> on UEFI system should always have a (sw) partition table or not. > > > >>>>>>>> But it is a different topic. > > > >>>>>>>> > > > >>>>>>>>> The UEFI model does not have a problem with this because on a handle you > > > >>>>>>>>> can install as many different protocols as you wish. But U-Boot's driver > > > >>>>>>>>> model only allows a single interface per device. Up to now U-Boot has > > > >>>>>>>>> overcome this limitation by creating child devices for the extra interfaces. > > > >>>>>>>> > > > >>>>>>>>> We have the following logical levels: > > > >>>>>>>>> > > > >>>>>>>>> Controller | Block device | Software Partition| File system > > > >>>>>>>>> ----------------+--------------+-------------------+------------ > > > >>>>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 > > > >>>>>>>>> ATA Controller | ATA-Drive | | > > > >>>>>>>>> SCSI Controller | LUN | | > > > >>>>>>>>> MMC Controller | HW-Partition | | > > > >>>>>>>>> MMC Controller | SD-Card | | > > > >>>>>>>>> USB-Node | USB-Drive | | > > > >>>>>>>>> > > > >>>>>>>>> In the device tree this could be modeled as: > > > >>>>>>>>> > > > >>>>>>>>> |-- Controller (UCLASS_CTRL) > > > >>>>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) > > > >>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) > > > >>>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > >>>>>>>>> | | |-- File system (UCLASS_FS) > > > >>>>>>>>> | | > > > >>>>>>>>> | |-- Block device (UCLASS_BLK) > > > >>>>>>>>> | |-- File system (UCLASS_FS) > > > >>>>>>>> > > > >>>>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. > > > >>>>>>>> What is the benefit? > > > >>>>>>>> (A) and (B) always have 1:1 relationship. > > > >>>>>>> > > > >>>>>>> No. You can have a bare device without a partition table. > > > >>>>>> > > > >>>>>> I can have a DOS partition that covers the whole device, without a > > > >>>>>> partition table. This is supported in U-Boot and Linux. > > > >>>>>> > > > >>>>>>> > > > >>>>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. > > > >>>>>>> > > > >>>>>>>> I also remember that you claimed that not all efi objects(handles and > > > >>>>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding > > > >>>>>>>> U-Boot counterparts in our 2019 discussion. > > > >>>>>>>> > > > >>>>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, > > > >>>>>>>> which should support other type of hw partitions as well? > > > >>>>>>> > > > >>>>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. > > > >>>>>>> > > > >>>>>>>> > > > >>>>>>>> |-- eMMC controller (UCLASS_MMC) > > > >>>>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > >>>>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) > > > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > > > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > >>>>>>>> | | |-- File system (UCLASS_FS) > > > >>>>>>>> | | > > > >>>>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) > > > >>>>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) > > > >>>>>>>> ... > > > >>>>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > >>>>>>>> > > > >>>>>>>> |-- scsi controller (UCLASS_SCSI) > > > >>>>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > >>>>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) > > > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > > > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > >>>>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) > > > >>>>>>>> ... > > > >>>>>>>> > > > >>>>>>>> (Here I ignored scsi buses/channels which make things more complicated.) > > > >>>>>>>> > > > >>>>>>>> This kind of complex hierarchy doesn't benefit anybody. > > > >>>>>>> > > > >>>>>>> All these levels exist already. We simply do not model them yet in the DM way. > > > >>>>>>> > > > >>>>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. > > > >>>>>>> > > > >>>>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. > > > >>>>>> > > > >>>>>> Yes, the complexity has to go somewhere. With driver model I chose to > > > >>>>>> have a single interface per uclass, since it is simpler to understand, > > > >>>>>> no need to request a protocol for a device, etc. > > > >>>>>> > > > >>>>>> Our current setup is similar to this > > > >>>>>> > > > >>>>>> |-- Controller (UCLASS_MMC) > > > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition > > > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* > > > >>>>>> > > > >>>>>> * although I don't think the MMC code actually supports it - SCSI does though > > > >>>>>> > > > >>>>>> We want to add devices for the partition table and the filesystem, so could do: > > > >>>>>> > > > >>>>>> |-- Controller (UCLASS_MMC) > > > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) > > > >>>>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) > > > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 1 > > > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem > > > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 2 > > > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem > > > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW > > > >>>>>> partition (the whole device) > > > >>>>>> > > > >>>>>> This is similar to Heinrich's, but without the top-level > > > >>>>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. > > > >>>>> > > > >>>>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? > > > >>>> > > > >>>> Yes. > > > >>>> What I meant to say is that, if we don't need a partition table 'udevice' > > > >>>> for hw partitions, we don't need such a device for sw partitions neither. > > > >>>> > > > >>>> Meanwhile, what about UCLASS_FS? Why do we need this? > > > >>> > > > >>> We don't need it for our current discussion, but if we want to 'open' > > > >>> the filesystem and keep the metadata around, rather than reading it > > > >>> again every time we access a file, we might find it useful. Open files > > > >>> could be children of the FS uclass, perhaps, if we go a step further > > > >>> and create devices for them. > > > >> > > > >> Do you want to invent linux-like mount-point concepts or procfs? > > > >> I remember that you didn't want to have child nodes under BLK devices. > > > >> I'm getting confused about our goal. > > > > > > > > I think we are all a bit unsure. > > > > > > > > I think BLK devices can have children, sorry if I said the wrong thing > > > > somewhere along the way. For example, a partition would be under a BLK > > > > device, or a FS. > > > > > > > >> What should DM represent in U-Boot world? > > > > > > > > That is what we are trying to figure out. > > > > > > > > I think the minimum is to have a a way to represent partitions (s/w > > > > and hw/). As I understand it, that's what we've been discussing. > > > > > > The discovery of hardware partitions is specific to the block device > > > controller SCSI/MMC/ATA/NVMe. We currently do not provide any > > > manipulation commands to create hardware partitions (e.g. NVMe > > > namespaces, SCSI LUNs). This is why extracting a uclass for hardware > > > partitions does not seem necessary. > > > > I can see the reasoning here. It might not stand the test of time but > > how about we go with it for now? For MMC hardware partition we would > > just end up with multiple BLK devices, like we do with SCSI LUNs at > > present, which seems like it should work (with some code tweaks). > > > > > > > > Software partitioning (MBR, GPT, ...) is independent of the harboring > > > block device. > > > > > > We already have a set of drivers for software partition tables in disk/. > > > Currently the available methods of the drivers are defined in > > > U_BOOT_PART_TYPE referring to struct part_driver. > > > > > > Currently struct part_driver knows only the following methods: > > > > > > - get_info() > > > - print() > > > - test() > > > > > > These drivers should be ome a uclass. > > > > > > gpt.c and mbr.c allow to create and delete partitions. I think we should add > > > > > > - create_partition() > > > - delete_partition() > > > > > > to the uclass methods. > > > > That sounds good to me, although since it is a partition uclass, we > > can just use create() and delete(). > > I don't know why we need a "partition table" device in the middle > of DM hierarchy. > I believe that it simply makes the view of DM tree complicated > without any explicit benefit.
Well we clearly have an API here. The partition uclass can:
- hold the partition table in dev_get_uclass_priv()
- support a read() operation to read the partition
- support create() to rewrite the partition table
- support delete() to overwrite/erase the partition table
Then it means that filesystems have the partition table as a parent (unless they are whole-device filesystems), which makes sense
So that's why I like the idea.
Other than the extra complexity, is there anything else wrong with it?
- First of all, a partition table doesn't look like a 'device' at all.
- Second, a partition table is just static data for block devices. IMO, even if we want to have this data, we can simply hold it as some sort of attribute of the device, or maybe as a 'tag' which I will introduce in the next version.
-Takahiro Akashi
I don't know how this affect the code, but I agree with Akashi-san here. It's indeed useful to keep the partition table stored somewhere, but I think not showing them as part of the device tree is more intuitive.
Well I think I'm easy either way. I just thought that Heinrich made a good case for having a partition uclass.
But as Takahiro says, we can use a tag to attach the partition table to the device. But it should be attached to the device's children (the BLK device) not the media device itself, right?
As there has been no discussion in 5 days and Takahiro is writing this, let's go with no uclass for the partition table.
Without uclass you cannot bring the partition table drivers into th driver model.
No clue what a tag should be in the driver model.
A tag is a way to associate data with a device. At present we do this with varoius built-in mechanisms (priv data, uclass-priv, plat, etc.) but with tags you can add something else.
Regards, Simon

Hi Simon,
On Sat, Nov 13, 2021 at 02:32:20PM -0700, Simon Glass wrote:
Hi Heinrich,
On Sat, 13 Nov 2021 at 11:42, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 13. November 2021 19:14:32 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Mon, 8 Nov 2021 at 17:09, Simon Glass sjg@chromium.org wrote:
Hi,
On Mon, 8 Nov 2021 at 11:45, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi chiming in a little late but
On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote: > Hi Takahiro, > > On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > > > On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote: > > > Hi, > > > > > > On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > > > > > > > > > > > > > On 11/1/21 03:14, Simon Glass wrote: > > > > > Hi Takahiro, > > > > > > > > > > On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro > > > > > takahiro.akashi@linaro.org wrote: > > > > >> > > > > >> On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: > > > > >>> Hi Takahiro, > > > > >>> > > > > >>> On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro > > > > >>> takahiro.akashi@linaro.org wrote: > > > > >>>> > > > > >>>> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: > > > > >>>>> > > > > >>>>> > > > > >>>>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: > > > > >>>>>> Hi, > > > > >>>>>> > > > > >>>>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > >>>>>>> > > > > >>>>>>> > > > > >>>>>>> > > > > >>>>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: > > > > >>>>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: > > > > >>>>>>>>> > > > > >>>>>>>>> > > > > >>>>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both > > > > >>>>>>>>>> in name and meaning. I think maybe I am missing the gist of your > > > > >>>>>>>>>> argument. > > > > >>>>>>>>>> > > > > >>>>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w > > > > >>>>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would > > > > >>>>>>>>>> the picture look like the, and would it get us closer to agreement? > > > > >>>>>>>>> > > > > >>>>>>>>> In the driver model: > > > > >>>>>>>>> > > > > >>>>>>>>> A UCLASS is a class of drivers that share the same interface. > > > > >>>>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is > > > > >>>>>>>>> accessed through this UCLASS's interface. > > > > >>>>>>>> > > > > >>>>>>>> Please be careful about "accessed through" which is a quite confusing > > > > >>>>>>>> expression. I don't always agree with this view. > > > > >>>>>>>> > > > > >>>>>>>>> A hardware partition is an object that exposes only a single interface > > > > >>>>>>>>> for block IO. > > > > >>>>>>>>> > > > > >>>>>>>>> A software partition is an object that may expose two interfaces: one > > > > >>>>>>>>> for block IO, the other for file IO. > > > > >>>>>>>> > > > > >>>>>>>> Are you talking about UEFI world or U-Boot? > > > > >>>>>>>> Definitely, a hw partitions can provide a file system > > > > >>>>>>>> if you want. > > > > >>>>>>>> It's a matter of usage. > > > > >>>>>>>> > > > > >>>>>>>> I remember that we had some discussion about whether block devices > > > > >>>>>>>> on UEFI system should always have a (sw) partition table or not. > > > > >>>>>>>> But it is a different topic. > > > > >>>>>>>> > > > > >>>>>>>>> The UEFI model does not have a problem with this because on a handle you > > > > >>>>>>>>> can install as many different protocols as you wish. But U-Boot's driver > > > > >>>>>>>>> model only allows a single interface per device. Up to now U-Boot has > > > > >>>>>>>>> overcome this limitation by creating child devices for the extra interfaces. > > > > >>>>>>>> > > > > >>>>>>>>> We have the following logical levels: > > > > >>>>>>>>> > > > > >>>>>>>>> Controller | Block device | Software Partition| File system > > > > >>>>>>>>> ----------------+--------------+-------------------+------------ > > > > >>>>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 > > > > >>>>>>>>> ATA Controller | ATA-Drive | | > > > > >>>>>>>>> SCSI Controller | LUN | | > > > > >>>>>>>>> MMC Controller | HW-Partition | | > > > > >>>>>>>>> MMC Controller | SD-Card | | > > > > >>>>>>>>> USB-Node | USB-Drive | | > > > > >>>>>>>>> > > > > >>>>>>>>> In the device tree this could be modeled as: > > > > >>>>>>>>> > > > > >>>>>>>>> |-- Controller (UCLASS_CTRL) > > > > >>>>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) > > > > >>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) > > > > >>>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > > >>>>>>>>> | | |-- File system (UCLASS_FS) > > > > >>>>>>>>> | | > > > > >>>>>>>>> | |-- Block device (UCLASS_BLK) > > > > >>>>>>>>> | |-- File system (UCLASS_FS) > > > > >>>>>>>> > > > > >>>>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. > > > > >>>>>>>> What is the benefit? > > > > >>>>>>>> (A) and (B) always have 1:1 relationship. > > > > >>>>>>> > > > > >>>>>>> No. You can have a bare device without a partition table. > > > > >>>>>> > > > > >>>>>> I can have a DOS partition that covers the whole device, without a > > > > >>>>>> partition table. This is supported in U-Boot and Linux. > > > > >>>>>> > > > > >>>>>>> > > > > >>>>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. > > > > >>>>>>> > > > > >>>>>>>> I also remember that you claimed that not all efi objects(handles and > > > > >>>>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding > > > > >>>>>>>> U-Boot counterparts in our 2019 discussion. > > > > >>>>>>>> > > > > >>>>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, > > > > >>>>>>>> which should support other type of hw partitions as well? > > > > >>>>>>> > > > > >>>>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. > > > > >>>>>>> > > > > >>>>>>>> > > > > >>>>>>>> |-- eMMC controller (UCLASS_MMC) > > > > >>>>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > >>>>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) > > > > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > > > > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > > >>>>>>>> | | |-- File system (UCLASS_FS) > > > > >>>>>>>> | | > > > > >>>>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) > > > > >>>>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) > > > > >>>>>>>> ... > > > > >>>>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > >>>>>>>> > > > > >>>>>>>> |-- scsi controller (UCLASS_SCSI) > > > > >>>>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > >>>>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) > > > > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > > > > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > > >>>>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) > > > > >>>>>>>> ... > > > > >>>>>>>> > > > > >>>>>>>> (Here I ignored scsi buses/channels which make things more complicated.) > > > > >>>>>>>> > > > > >>>>>>>> This kind of complex hierarchy doesn't benefit anybody. > > > > >>>>>>> > > > > >>>>>>> All these levels exist already. We simply do not model them yet in the DM way. > > > > >>>>>>> > > > > >>>>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. > > > > >>>>>>> > > > > >>>>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. > > > > >>>>>> > > > > >>>>>> Yes, the complexity has to go somewhere. With driver model I chose to > > > > >>>>>> have a single interface per uclass, since it is simpler to understand, > > > > >>>>>> no need to request a protocol for a device, etc. > > > > >>>>>> > > > > >>>>>> Our current setup is similar to this > > > > >>>>>> > > > > >>>>>> |-- Controller (UCLASS_MMC) > > > > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition > > > > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* > > > > >>>>>> > > > > >>>>>> * although I don't think the MMC code actually supports it - SCSI does though > > > > >>>>>> > > > > >>>>>> We want to add devices for the partition table and the filesystem, so could do: > > > > >>>>>> > > > > >>>>>> |-- Controller (UCLASS_MMC) > > > > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) > > > > >>>>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) > > > > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 1 > > > > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem > > > > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 2 > > > > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem > > > > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW > > > > >>>>>> partition (the whole device) > > > > >>>>>> > > > > >>>>>> This is similar to Heinrich's, but without the top-level > > > > >>>>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. > > > > >>>>> > > > > >>>>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? > > > > >>>> > > > > >>>> Yes. > > > > >>>> What I meant to say is that, if we don't need a partition table 'udevice' > > > > >>>> for hw partitions, we don't need such a device for sw partitions neither. > > > > >>>> > > > > >>>> Meanwhile, what about UCLASS_FS? Why do we need this? > > > > >>> > > > > >>> We don't need it for our current discussion, but if we want to 'open' > > > > >>> the filesystem and keep the metadata around, rather than reading it > > > > >>> again every time we access a file, we might find it useful. Open files > > > > >>> could be children of the FS uclass, perhaps, if we go a step further > > > > >>> and create devices for them. > > > > >> > > > > >> Do you want to invent linux-like mount-point concepts or procfs? > > > > >> I remember that you didn't want to have child nodes under BLK devices. > > > > >> I'm getting confused about our goal. > > > > > > > > > > I think we are all a bit unsure. > > > > > > > > > > I think BLK devices can have children, sorry if I said the wrong thing > > > > > somewhere along the way. For example, a partition would be under a BLK > > > > > device, or a FS. > > > > > > > > > >> What should DM represent in U-Boot world? > > > > > > > > > > That is what we are trying to figure out. > > > > > > > > > > I think the minimum is to have a a way to represent partitions (s/w > > > > > and hw/). As I understand it, that's what we've been discussing. > > > > > > > > The discovery of hardware partitions is specific to the block device > > > > controller SCSI/MMC/ATA/NVMe. We currently do not provide any > > > > manipulation commands to create hardware partitions (e.g. NVMe > > > > namespaces, SCSI LUNs). This is why extracting a uclass for hardware > > > > partitions does not seem necessary. > > > > > > I can see the reasoning here. It might not stand the test of time but > > > how about we go with it for now? For MMC hardware partition we would > > > just end up with multiple BLK devices, like we do with SCSI LUNs at > > > present, which seems like it should work (with some code tweaks). > > > > > > > > > > > Software partitioning (MBR, GPT, ...) is independent of the harboring > > > > block device. > > > > > > > > We already have a set of drivers for software partition tables in disk/. > > > > Currently the available methods of the drivers are defined in > > > > U_BOOT_PART_TYPE referring to struct part_driver. > > > > > > > > Currently struct part_driver knows only the following methods: > > > > > > > > - get_info() > > > > - print() > > > > - test() > > > > > > > > These drivers should be ome a uclass. > > > > > > > > gpt.c and mbr.c allow to create and delete partitions. I think we should add > > > > > > > > - create_partition() > > > > - delete_partition() > > > > > > > > to the uclass methods. > > > > > > That sounds good to me, although since it is a partition uclass, we > > > can just use create() and delete(). > > > > I don't know why we need a "partition table" device in the middle > > of DM hierarchy. > > I believe that it simply makes the view of DM tree complicated > > without any explicit benefit. > > Well we clearly have an API here. The partition uclass can: > > - hold the partition table in dev_get_uclass_priv() > - support a read() operation to read the partition > - support create() to rewrite the partition table > - support delete() to overwrite/erase the partition table > > Then it means that filesystems have the partition table as a parent > (unless they are whole-device filesystems), which makes sense > > So that's why I like the idea. > > Other than the extra complexity, is there anything else wrong with it?
- First of all, a partition table doesn't look like a 'device' at all.
- Second, a partition table is just static data for block devices. IMO, even if we want to have this data, we can simply hold it as some sort of attribute of the device, or maybe as a 'tag' which I will introduce in the next version.
-Takahiro Akashi
I don't know how this affect the code, but I agree with Akashi-san here. It's indeed useful to keep the partition table stored somewhere, but I think not showing them as part of the device tree is more intuitive.
Well I think I'm easy either way. I just thought that Heinrich made a good case for having a partition uclass.
But as Takahiro says, we can use a tag to attach the partition table to the device. But it should be attached to the device's children (the BLK device) not the media device itself, right?
As there has been no discussion in 5 days and Takahiro is writing this, let's go with no uclass for the partition table.
Without uclass you cannot bring the partition table drivers into th driver model.
This transition may be able to be done later when really necessary as long as we agree that a partition table be hold within a "raw" disk object (with a tag support). # I don't think we need it for now.
No clue what a tag should be in the driver model.
A tag is a way to associate data with a device. At present we do this with varoius built-in mechanisms (priv data, uclass-priv, plat, etc.) but with tags you can add something else.
Since this discussion thread is getting too long, I would like to respin my RFC. How should I deal with your "event notification" proposal?
-Takahiro Akashi
Regards, Simon

Hi Takahiro,
On Sun, 14 Nov 2021 at 18:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Hi Simon,
On Sat, Nov 13, 2021 at 02:32:20PM -0700, Simon Glass wrote:
Hi Heinrich,
On Sat, 13 Nov 2021 at 11:42, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 13. November 2021 19:14:32 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Mon, 8 Nov 2021 at 17:09, Simon Glass sjg@chromium.org wrote:
Hi,
On Mon, 8 Nov 2021 at 11:45, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi chiming in a little late but
On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote: > > Hi Takahiro, > > > > On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > > > > > On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote: > > > > Hi, > > > > > > > > On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > > > > > > > > > > > > > > > > > On 11/1/21 03:14, Simon Glass wrote: > > > > > > Hi Takahiro, > > > > > > > > > > > > On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro > > > > > > takahiro.akashi@linaro.org wrote: > > > > > >> > > > > > >> On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: > > > > > >>> Hi Takahiro, > > > > > >>> > > > > > >>> On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro > > > > > >>> takahiro.akashi@linaro.org wrote: > > > > > >>>> > > > > > >>>> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: > > > > > >>>>> > > > > > >>>>> > > > > > >>>>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: > > > > > >>>>>> Hi, > > > > > >>>>>> > > > > > >>>>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > > >>>>>>> > > > > > >>>>>>> > > > > > >>>>>>> > > > > > >>>>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: > > > > > >>>>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: > > > > > >>>>>>>>> > > > > > >>>>>>>>> > > > > > >>>>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both > > > > > >>>>>>>>>> in name and meaning. I think maybe I am missing the gist of your > > > > > >>>>>>>>>> argument. > > > > > >>>>>>>>>> > > > > > >>>>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w > > > > > >>>>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would > > > > > >>>>>>>>>> the picture look like the, and would it get us closer to agreement? > > > > > >>>>>>>>> > > > > > >>>>>>>>> In the driver model: > > > > > >>>>>>>>> > > > > > >>>>>>>>> A UCLASS is a class of drivers that share the same interface. > > > > > >>>>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is > > > > > >>>>>>>>> accessed through this UCLASS's interface. > > > > > >>>>>>>> > > > > > >>>>>>>> Please be careful about "accessed through" which is a quite confusing > > > > > >>>>>>>> expression. I don't always agree with this view. > > > > > >>>>>>>> > > > > > >>>>>>>>> A hardware partition is an object that exposes only a single interface > > > > > >>>>>>>>> for block IO. > > > > > >>>>>>>>> > > > > > >>>>>>>>> A software partition is an object that may expose two interfaces: one > > > > > >>>>>>>>> for block IO, the other for file IO. > > > > > >>>>>>>> > > > > > >>>>>>>> Are you talking about UEFI world or U-Boot? > > > > > >>>>>>>> Definitely, a hw partitions can provide a file system > > > > > >>>>>>>> if you want. > > > > > >>>>>>>> It's a matter of usage. > > > > > >>>>>>>> > > > > > >>>>>>>> I remember that we had some discussion about whether block devices > > > > > >>>>>>>> on UEFI system should always have a (sw) partition table or not. > > > > > >>>>>>>> But it is a different topic. > > > > > >>>>>>>> > > > > > >>>>>>>>> The UEFI model does not have a problem with this because on a handle you > > > > > >>>>>>>>> can install as many different protocols as you wish. But U-Boot's driver > > > > > >>>>>>>>> model only allows a single interface per device. Up to now U-Boot has > > > > > >>>>>>>>> overcome this limitation by creating child devices for the extra interfaces. > > > > > >>>>>>>> > > > > > >>>>>>>>> We have the following logical levels: > > > > > >>>>>>>>> > > > > > >>>>>>>>> Controller | Block device | Software Partition| File system > > > > > >>>>>>>>> ----------------+--------------+-------------------+------------ > > > > > >>>>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 > > > > > >>>>>>>>> ATA Controller | ATA-Drive | | > > > > > >>>>>>>>> SCSI Controller | LUN | | > > > > > >>>>>>>>> MMC Controller | HW-Partition | | > > > > > >>>>>>>>> MMC Controller | SD-Card | | > > > > > >>>>>>>>> USB-Node | USB-Drive | | > > > > > >>>>>>>>> > > > > > >>>>>>>>> In the device tree this could be modeled as: > > > > > >>>>>>>>> > > > > > >>>>>>>>> |-- Controller (UCLASS_CTRL) > > > > > >>>>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) > > > > > >>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) > > > > > >>>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > > > >>>>>>>>> | | |-- File system (UCLASS_FS) > > > > > >>>>>>>>> | | > > > > > >>>>>>>>> | |-- Block device (UCLASS_BLK) > > > > > >>>>>>>>> | |-- File system (UCLASS_FS) > > > > > >>>>>>>> > > > > > >>>>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. > > > > > >>>>>>>> What is the benefit? > > > > > >>>>>>>> (A) and (B) always have 1:1 relationship. > > > > > >>>>>>> > > > > > >>>>>>> No. You can have a bare device without a partition table. > > > > > >>>>>> > > > > > >>>>>> I can have a DOS partition that covers the whole device, without a > > > > > >>>>>> partition table. This is supported in U-Boot and Linux. > > > > > >>>>>> > > > > > >>>>>>> > > > > > >>>>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. > > > > > >>>>>>> > > > > > >>>>>>>> I also remember that you claimed that not all efi objects(handles and > > > > > >>>>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding > > > > > >>>>>>>> U-Boot counterparts in our 2019 discussion. > > > > > >>>>>>>> > > > > > >>>>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, > > > > > >>>>>>>> which should support other type of hw partitions as well? > > > > > >>>>>>> > > > > > >>>>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. > > > > > >>>>>>> > > > > > >>>>>>>> > > > > > >>>>>>>> |-- eMMC controller (UCLASS_MMC) > > > > > >>>>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > > >>>>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) > > > > > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > > > > > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > > > >>>>>>>> | | |-- File system (UCLASS_FS) > > > > > >>>>>>>> | | > > > > > >>>>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) > > > > > >>>>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) > > > > > >>>>>>>> ... > > > > > >>>>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > > >>>>>>>> > > > > > >>>>>>>> |-- scsi controller (UCLASS_SCSI) > > > > > >>>>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > > >>>>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) > > > > > >>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) > > > > > >>>>>>>> | | |-- Software Partition (UCLASS_BLK) > > > > > >>>>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) > > > > > >>>>>>>> ... > > > > > >>>>>>>> > > > > > >>>>>>>> (Here I ignored scsi buses/channels which make things more complicated.) > > > > > >>>>>>>> > > > > > >>>>>>>> This kind of complex hierarchy doesn't benefit anybody. > > > > > >>>>>>> > > > > > >>>>>>> All these levels exist already. We simply do not model them yet in the DM way. > > > > > >>>>>>> > > > > > >>>>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. > > > > > >>>>>>> > > > > > >>>>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. > > > > > >>>>>> > > > > > >>>>>> Yes, the complexity has to go somewhere. With driver model I chose to > > > > > >>>>>> have a single interface per uclass, since it is simpler to understand, > > > > > >>>>>> no need to request a protocol for a device, etc. > > > > > >>>>>> > > > > > >>>>>> Our current setup is similar to this > > > > > >>>>>> > > > > > >>>>>> |-- Controller (UCLASS_MMC) > > > > > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition > > > > > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* > > > > > >>>>>> > > > > > >>>>>> * although I don't think the MMC code actually supports it - SCSI does though > > > > > >>>>>> > > > > > >>>>>> We want to add devices for the partition table and the filesystem, so could do: > > > > > >>>>>> > > > > > >>>>>> |-- Controller (UCLASS_MMC) > > > > > >>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) > > > > > >>>>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) > > > > > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 1 > > > > > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem > > > > > >>>>>> | | | |-- Block device (UCLASS_BLK) - partition 2 > > > > > >>>>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem > > > > > >>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW > > > > > >>>>>> partition (the whole device) > > > > > >>>>>> > > > > > >>>>>> This is similar to Heinrich's, but without the top-level > > > > > >>>>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. > > > > > >>>>> > > > > > >>>>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? > > > > > >>>> > > > > > >>>> Yes. > > > > > >>>> What I meant to say is that, if we don't need a partition table 'udevice' > > > > > >>>> for hw partitions, we don't need such a device for sw partitions neither. > > > > > >>>> > > > > > >>>> Meanwhile, what about UCLASS_FS? Why do we need this? > > > > > >>> > > > > > >>> We don't need it for our current discussion, but if we want to 'open' > > > > > >>> the filesystem and keep the metadata around, rather than reading it > > > > > >>> again every time we access a file, we might find it useful. Open files > > > > > >>> could be children of the FS uclass, perhaps, if we go a step further > > > > > >>> and create devices for them. > > > > > >> > > > > > >> Do you want to invent linux-like mount-point concepts or procfs? > > > > > >> I remember that you didn't want to have child nodes under BLK devices. > > > > > >> I'm getting confused about our goal. > > > > > > > > > > > > I think we are all a bit unsure. > > > > > > > > > > > > I think BLK devices can have children, sorry if I said the wrong thing > > > > > > somewhere along the way. For example, a partition would be under a BLK > > > > > > device, or a FS. > > > > > > > > > > > >> What should DM represent in U-Boot world? > > > > > > > > > > > > That is what we are trying to figure out. > > > > > > > > > > > > I think the minimum is to have a a way to represent partitions (s/w > > > > > > and hw/). As I understand it, that's what we've been discussing. > > > > > > > > > > The discovery of hardware partitions is specific to the block device > > > > > controller SCSI/MMC/ATA/NVMe. We currently do not provide any > > > > > manipulation commands to create hardware partitions (e.g. NVMe > > > > > namespaces, SCSI LUNs). This is why extracting a uclass for hardware > > > > > partitions does not seem necessary. > > > > > > > > I can see the reasoning here. It might not stand the test of time but > > > > how about we go with it for now? For MMC hardware partition we would > > > > just end up with multiple BLK devices, like we do with SCSI LUNs at > > > > present, which seems like it should work (with some code tweaks). > > > > > > > > > > > > > > Software partitioning (MBR, GPT, ...) is independent of the harboring > > > > > block device. > > > > > > > > > > We already have a set of drivers for software partition tables in disk/. > > > > > Currently the available methods of the drivers are defined in > > > > > U_BOOT_PART_TYPE referring to struct part_driver. > > > > > > > > > > Currently struct part_driver knows only the following methods: > > > > > > > > > > - get_info() > > > > > - print() > > > > > - test() > > > > > > > > > > These drivers should be ome a uclass. > > > > > > > > > > gpt.c and mbr.c allow to create and delete partitions. I think we should add > > > > > > > > > > - create_partition() > > > > > - delete_partition() > > > > > > > > > > to the uclass methods. > > > > > > > > That sounds good to me, although since it is a partition uclass, we > > > > can just use create() and delete(). > > > > > > I don't know why we need a "partition table" device in the middle > > > of DM hierarchy. > > > I believe that it simply makes the view of DM tree complicated > > > without any explicit benefit. > > > > Well we clearly have an API here. The partition uclass can: > > > > - hold the partition table in dev_get_uclass_priv() > > - support a read() operation to read the partition > > - support create() to rewrite the partition table > > - support delete() to overwrite/erase the partition table > > > > Then it means that filesystems have the partition table as a parent > > (unless they are whole-device filesystems), which makes sense > > > > So that's why I like the idea. > > > > Other than the extra complexity, is there anything else wrong with it? > > - First of all, a partition table doesn't look like a 'device' at all. > - Second, a partition table is just static data for block devices. > IMO, even if we want to have this data, we can simply hold it > as some sort of attribute of the device, or maybe as a 'tag' which > I will introduce in the next version. > > -Takahiro Akashi >
I don't know how this affect the code, but I agree with Akashi-san here. It's indeed useful to keep the partition table stored somewhere, but I think not showing them as part of the device tree is more intuitive.
Well I think I'm easy either way. I just thought that Heinrich made a good case for having a partition uclass.
But as Takahiro says, we can use a tag to attach the partition table to the device. But it should be attached to the device's children (the BLK device) not the media device itself, right?
As there has been no discussion in 5 days and Takahiro is writing this, let's go with no uclass for the partition table.
Without uclass you cannot bring the partition table drivers into th driver model.
This transition may be able to be done later when really necessary as long as we agree that a partition table be hold within a "raw" disk object (with a tag support). # I don't think we need it for now.
No clue what a tag should be in the driver model.
A tag is a way to associate data with a device. At present we do this with varoius built-in mechanisms (priv data, uclass-priv, plat, etc.) but with tags you can add something else.
Since this discussion thread is getting too long, I would like to respin my RFC. How should I deal with your "event notification" proposal?
Is the patch good enough to include in the series?
If not, you could reply to it with what needs doing.
Regards, Simon

On 11/15/21 20:05, Simon Glass wrote:
Hi Takahiro,
On Sun, 14 Nov 2021 at 18:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Hi Simon,
On Sat, Nov 13, 2021 at 02:32:20PM -0700, Simon Glass wrote:
Hi Heinrich,
On Sat, 13 Nov 2021 at 11:42, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 13. November 2021 19:14:32 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Mon, 8 Nov 2021 at 17:09, Simon Glass sjg@chromium.org wrote:
Hi,
On Mon, 8 Nov 2021 at 11:45, Ilias Apalodimas ilias.apalodimas@linaro.org wrote: > > Hi chiming in a little late but > > On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote: >> >> On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote: >>> Hi Takahiro, >>> >>> On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote: >>>> >>>> On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote: >>>>> Hi, >>>>> >>>>> On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >>>>>> >>>>>> >>>>>> >>>>>> On 11/1/21 03:14, Simon Glass wrote: >>>>>>> Hi Takahiro, >>>>>>> >>>>>>> On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro >>>>>>> takahiro.akashi@linaro.org wrote: >>>>>>>> >>>>>>>> On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: >>>>>>>>> Hi Takahiro, >>>>>>>>> >>>>>>>>> On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro >>>>>>>>> takahiro.akashi@linaro.org wrote: >>>>>>>>>> >>>>>>>>>> On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: >>>>>>>>>>>> Hi, >>>>>>>>>>>> >>>>>>>>>>>> On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: >>>>>>>>>>>>>> On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I agree with Heinrich that we are better to leave BLK as it is, both >>>>>>>>>>>>>>>> in name and meaning. I think maybe I am missing the gist of your >>>>>>>>>>>>>>>> argument. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> If we use UCLASS_PART, for example, can we have that refer to both s/w >>>>>>>>>>>>>>>> and h/w partitions, as Herinch seems to allude to below? What would >>>>>>>>>>>>>>>> the picture look like the, and would it get us closer to agreement? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> In the driver model: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> A UCLASS is a class of drivers that share the same interface. >>>>>>>>>>>>>>> A UDEVICE is a logical device that belongs to exactly one UCLASS and is >>>>>>>>>>>>>>> accessed through this UCLASS's interface. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Please be careful about "accessed through" which is a quite confusing >>>>>>>>>>>>>> expression. I don't always agree with this view. >>>>>>>>>>>>>> >>>>>>>>>>>>>>> A hardware partition is an object that exposes only a single interface >>>>>>>>>>>>>>> for block IO. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> A software partition is an object that may expose two interfaces: one >>>>>>>>>>>>>>> for block IO, the other for file IO. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Are you talking about UEFI world or U-Boot? >>>>>>>>>>>>>> Definitely, a hw partitions can provide a file system >>>>>>>>>>>>>> if you want. >>>>>>>>>>>>>> It's a matter of usage. >>>>>>>>>>>>>> >>>>>>>>>>>>>> I remember that we had some discussion about whether block devices >>>>>>>>>>>>>> on UEFI system should always have a (sw) partition table or not. >>>>>>>>>>>>>> But it is a different topic. >>>>>>>>>>>>>> >>>>>>>>>>>>>>> The UEFI model does not have a problem with this because on a handle you >>>>>>>>>>>>>>> can install as many different protocols as you wish. But U-Boot's driver >>>>>>>>>>>>>>> model only allows a single interface per device. Up to now U-Boot has >>>>>>>>>>>>>>> overcome this limitation by creating child devices for the extra interfaces. >>>>>>>>>>>>>> >>>>>>>>>>>>>>> We have the following logical levels: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Controller | Block device | Software Partition| File system >>>>>>>>>>>>>>> ----------------+--------------+-------------------+------------ >>>>>>>>>>>>>>> NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 >>>>>>>>>>>>>>> ATA Controller | ATA-Drive | | >>>>>>>>>>>>>>> SCSI Controller | LUN | | >>>>>>>>>>>>>>> MMC Controller | HW-Partition | | >>>>>>>>>>>>>>> MMC Controller | SD-Card | | >>>>>>>>>>>>>>> USB-Node | USB-Drive | | >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> In the device tree this could be modeled as: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> |-- Controller (UCLASS_CTRL) >>>>>>>>>>>>>>> | |-- Block device / HW Partition (UCLASS_BLK) (A) >>>>>>>>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) >>>>>>>>>>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>>>>>>>>>> | | |-- File system (UCLASS_FS) >>>>>>>>>>>>>>> | | >>>>>>>>>>>>>>> | |-- Block device (UCLASS_BLK) >>>>>>>>>>>>>>> | |-- File system (UCLASS_FS) >>>>>>>>>>>>>> >>>>>>>>>>>>>> I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. >>>>>>>>>>>>>> What is the benefit? >>>>>>>>>>>>>> (A) and (B) always have 1:1 relationship. >>>>>>>>>>>>> >>>>>>>>>>>>> No. You can have a bare device without a partition table. >>>>>>>>>>>> >>>>>>>>>>>> I can have a DOS partition that covers the whole device, without a >>>>>>>>>>>> partition table. This is supported in U-Boot and Linux. >>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. >>>>>>>>>>>>> >>>>>>>>>>>>>> I also remember that you claimed that not all efi objects(handles and >>>>>>>>>>>>>> protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding >>>>>>>>>>>>>> U-Boot counterparts in our 2019 discussion. >>>>>>>>>>>>>> >>>>>>>>>>>>>> If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, >>>>>>>>>>>>>> which should support other type of hw partitions as well? >>>>>>>>>>>>> >>>>>>>>>>>>> How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. >>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> |-- eMMC controller (UCLASS_MMC) >>>>>>>>>>>>>> | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>>>>>>>>> | |-- Block device / HW Partition:user data (UCLASS_BLK) >>>>>>>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>>>>>>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>>>>>>>>> | | |-- File system (UCLASS_FS) >>>>>>>>>>>>>> | | >>>>>>>>>>>>>> | |-- Block device / HW Partition:boot0 (UCLASS_BLK) >>>>>>>>>>>>>> | |-- Block device / HW Partition:boot1 (UCLASS_BLK) >>>>>>>>>>>>>> ... >>>>>>>>>>>>>> | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>>>>>>>>> >>>>>>>>>>>>>> |-- scsi controller (UCLASS_SCSI) >>>>>>>>>>>>>> | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) >>>>>>>>>>>>>> | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) >>>>>>>>>>>>>> | | |-- Partition table (UCLASS_PARTITION_TABLE) >>>>>>>>>>>>>> | | |-- Software Partition (UCLASS_BLK) >>>>>>>>>>>>>> | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) >>>>>>>>>>>>>> ... >>>>>>>>>>>>>> >>>>>>>>>>>>>> (Here I ignored scsi buses/channels which make things more complicated.) >>>>>>>>>>>>>> >>>>>>>>>>>>>> This kind of complex hierarchy doesn't benefit anybody. >>>>>>>>>>>>> >>>>>>>>>>>>> All these levels exist already. We simply do not model them yet in the DM way. >>>>>>>>>>>>> >>>>>>>>>>>>> The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. >>>>>>>>>>>>> >>>>>>>>>>>>> The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. >>>>>>>>>>>> >>>>>>>>>>>> Yes, the complexity has to go somewhere. With driver model I chose to >>>>>>>>>>>> have a single interface per uclass, since it is simpler to understand, >>>>>>>>>>>> no need to request a protocol for a device, etc. >>>>>>>>>>>> >>>>>>>>>>>> Our current setup is similar to this >>>>>>>>>>>> >>>>>>>>>>>> |-- Controller (UCLASS_MMC) >>>>>>>>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition >>>>>>>>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* >>>>>>>>>>>> >>>>>>>>>>>> * although I don't think the MMC code actually supports it - SCSI does though >>>>>>>>>>>> >>>>>>>>>>>> We want to add devices for the partition table and the filesystem, so could do: >>>>>>>>>>>> >>>>>>>>>>>> |-- Controller (UCLASS_MMC) >>>>>>>>>>>> | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) >>>>>>>>>>>> | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) >>>>>>>>>>>> | | | |-- Block device (UCLASS_BLK) - partition 1 >>>>>>>>>>>> | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem >>>>>>>>>>>> | | | |-- Block device (UCLASS_BLK) - partition 2 >>>>>>>>>>>> | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem >>>>>>>>>>>> | |-- Block device (UCLASS_BLK) - e.g. for a different HW >>>>>>>>>>>> partition (the whole device) >>>>>>>>>>>> >>>>>>>>>>>> This is similar to Heinrich's, but without the top-level >>>>>>>>>>>> UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. >>>>>>>>>>> >>>>>>>>>>> Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? >>>>>>>>>> >>>>>>>>>> Yes. >>>>>>>>>> What I meant to say is that, if we don't need a partition table 'udevice' >>>>>>>>>> for hw partitions, we don't need such a device for sw partitions neither. >>>>>>>>>> >>>>>>>>>> Meanwhile, what about UCLASS_FS? Why do we need this? >>>>>>>>> >>>>>>>>> We don't need it for our current discussion, but if we want to 'open' >>>>>>>>> the filesystem and keep the metadata around, rather than reading it >>>>>>>>> again every time we access a file, we might find it useful. Open files >>>>>>>>> could be children of the FS uclass, perhaps, if we go a step further >>>>>>>>> and create devices for them. >>>>>>>> >>>>>>>> Do you want to invent linux-like mount-point concepts or procfs? >>>>>>>> I remember that you didn't want to have child nodes under BLK devices. >>>>>>>> I'm getting confused about our goal. >>>>>>> >>>>>>> I think we are all a bit unsure. >>>>>>> >>>>>>> I think BLK devices can have children, sorry if I said the wrong thing >>>>>>> somewhere along the way. For example, a partition would be under a BLK >>>>>>> device, or a FS. >>>>>>> >>>>>>>> What should DM represent in U-Boot world? >>>>>>> >>>>>>> That is what we are trying to figure out. >>>>>>> >>>>>>> I think the minimum is to have a a way to represent partitions (s/w >>>>>>> and hw/). As I understand it, that's what we've been discussing. >>>>>> >>>>>> The discovery of hardware partitions is specific to the block device >>>>>> controller SCSI/MMC/ATA/NVMe. We currently do not provide any >>>>>> manipulation commands to create hardware partitions (e.g. NVMe >>>>>> namespaces, SCSI LUNs). This is why extracting a uclass for hardware >>>>>> partitions does not seem necessary. >>>>> >>>>> I can see the reasoning here. It might not stand the test of time but >>>>> how about we go with it for now? For MMC hardware partition we would >>>>> just end up with multiple BLK devices, like we do with SCSI LUNs at >>>>> present, which seems like it should work (with some code tweaks). >>>>> >>>>>> >>>>>> Software partitioning (MBR, GPT, ...) is independent of the harboring >>>>>> block device. >>>>>> >>>>>> We already have a set of drivers for software partition tables in disk/. >>>>>> Currently the available methods of the drivers are defined in >>>>>> U_BOOT_PART_TYPE referring to struct part_driver. >>>>>> >>>>>> Currently struct part_driver knows only the following methods: >>>>>> >>>>>> - get_info() >>>>>> - print() >>>>>> - test() >>>>>> >>>>>> These drivers should be ome a uclass. >>>>>> >>>>>> gpt.c and mbr.c allow to create and delete partitions. I think we should add >>>>>> >>>>>> - create_partition() >>>>>> - delete_partition() >>>>>> >>>>>> to the uclass methods. >>>>> >>>>> That sounds good to me, although since it is a partition uclass, we >>>>> can just use create() and delete(). >>>> >>>> I don't know why we need a "partition table" device in the middle >>>> of DM hierarchy. >>>> I believe that it simply makes the view of DM tree complicated >>>> without any explicit benefit. >>> >>> Well we clearly have an API here. The partition uclass can: >>> >>> - hold the partition table in dev_get_uclass_priv() >>> - support a read() operation to read the partition >>> - support create() to rewrite the partition table >>> - support delete() to overwrite/erase the partition table >>> >>> Then it means that filesystems have the partition table as a parent >>> (unless they are whole-device filesystems), which makes sense >>> >>> So that's why I like the idea. >>> >>> Other than the extra complexity, is there anything else wrong with it? >> >> - First of all, a partition table doesn't look like a 'device' at all. >> - Second, a partition table is just static data for block devices. >> IMO, even if we want to have this data, we can simply hold it >> as some sort of attribute of the device, or maybe as a 'tag' which >> I will introduce in the next version. >> >> -Takahiro Akashi >> > > I don't know how this affect the code, but I agree with Akashi-san > here. It's indeed useful to keep the partition table stored > somewhere, but I think not showing them as part of the device tree is > more intuitive.
Well I think I'm easy either way. I just thought that Heinrich made a good case for having a partition uclass.
But as Takahiro says, we can use a tag to attach the partition table to the device. But it should be attached to the device's children (the BLK device) not the media device itself, right?
As there has been no discussion in 5 days and Takahiro is writing this, let's go with no uclass for the partition table.
Without uclass you cannot bring the partition table drivers into th driver model.
This transition may be able to be done later when really necessary as long as we agree that a partition table be hold within a "raw" disk object (with a tag support). # I don't think we need it for now.
No clue what a tag should be in the driver model.
A tag is a way to associate data with a device. At present we do this with varoius built-in mechanisms (priv data, uclass-priv, plat, etc.) but with tags you can add something else.
Since this discussion thread is getting too long, I would like to respin my RFC. How should I deal with your "event notification" proposal?
Is the patch good enough to include in the series?
If not, you could reply to it with what needs doing.
Regards, Simon
The patch is not usable as is. It assumes only GPT partioning is used.
Instead all partition table drivers need to be converted to drivers for the new uclass.
Best regards
Heinrich

On Mon, Nov 15, 2021 at 08:16:25PM +0100, Heinrich Schuchardt wrote:
On 11/15/21 20:05, Simon Glass wrote:
Hi Takahiro,
On Sun, 14 Nov 2021 at 18:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Hi Simon,
On Sat, Nov 13, 2021 at 02:32:20PM -0700, Simon Glass wrote:
Hi Heinrich,
On Sat, 13 Nov 2021 at 11:42, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 13. November 2021 19:14:32 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Mon, 8 Nov 2021 at 17:09, Simon Glass sjg@chromium.org wrote: > > Hi, > > On Mon, 8 Nov 2021 at 11:45, Ilias Apalodimas > ilias.apalodimas@linaro.org wrote: > > > > Hi chiming in a little late but > > > > On Mon, 8 Nov 2021 at 06:46, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > > > > > On Fri, Nov 05, 2021 at 10:12:16AM -0600, Simon Glass wrote: > > > > Hi Takahiro, > > > > > > > > On Thu, 4 Nov 2021 at 20:49, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > > > > > > > > > On Thu, Nov 04, 2021 at 08:02:05PM -0600, Simon Glass wrote: > > > > > > Hi, > > > > > > > > > > > > On Tue, 2 Nov 2021 at 01:43, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > On 11/1/21 03:14, Simon Glass wrote: > > > > > > > > Hi Takahiro, > > > > > > > > > > > > > > > > On Sun, 31 Oct 2021 at 19:52, AKASHI Takahiro > > > > > > > > takahiro.akashi@linaro.org wrote: > > > > > > > > > > > > > > > > > > On Sun, Oct 31, 2021 at 07:15:17PM -0600, Simon Glass wrote: > > > > > > > > > > Hi Takahiro, > > > > > > > > > > > > > > > > > > > > On Sun, 31 Oct 2021 at 18:36, AKASHI Takahiro > > > > > > > > > > takahiro.akashi@linaro.org wrote: > > > > > > > > > > > > > > > > > > > > > > On Sat, Oct 30, 2021 at 07:45:14AM +0200, Heinrich Schuchardt wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Am 29. Oktober 2021 23:17:56 MESZ schrieb Simon Glass sjg@chromium.org: > > > > > > > > > > > > > Hi, > > > > > > > > > > > > > > > > > > > > > > > > > > On Fri, 29 Oct 2021 at 13:26, Heinrich Schuchardt xypron.glpk@gmx.de wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Am 29. Oktober 2021 08:15:56 MESZ schrieb AKASHI Takahiro takahiro.akashi@linaro.org: > > > > > > > > > > > > > > > On Fri, Oct 29, 2021 at 06:57:24AM +0200, Heinrich Schuchardt wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > I agree with Heinrich that we are better to leave BLK as it is, both > > > > > > > > > > > > > > > > > in name and meaning. I think maybe I am missing the gist of your > > > > > > > > > > > > > > > > > argument. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > If we use UCLASS_PART, for example, can we have that refer to both s/w > > > > > > > > > > > > > > > > > and h/w partitions, as Herinch seems to allude to below? What would > > > > > > > > > > > > > > > > > the picture look like the, and would it get us closer to agreement? > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > In the driver model: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > A UCLASS is a class of drivers that share the same interface. > > > > > > > > > > > > > > > > A UDEVICE is a logical device that belongs to exactly one UCLASS and is > > > > > > > > > > > > > > > > accessed through this UCLASS's interface. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Please be careful about "accessed through" which is a quite confusing > > > > > > > > > > > > > > > expression. I don't always agree with this view. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > A hardware partition is an object that exposes only a single interface > > > > > > > > > > > > > > > > for block IO. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > A software partition is an object that may expose two interfaces: one > > > > > > > > > > > > > > > > for block IO, the other for file IO. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Are you talking about UEFI world or U-Boot? > > > > > > > > > > > > > > > Definitely, a hw partitions can provide a file system > > > > > > > > > > > > > > > if you want. > > > > > > > > > > > > > > > It's a matter of usage. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > I remember that we had some discussion about whether block devices > > > > > > > > > > > > > > > on UEFI system should always have a (sw) partition table or not. > > > > > > > > > > > > > > > But it is a different topic. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > The UEFI model does not have a problem with this because on a handle you > > > > > > > > > > > > > > > > can install as many different protocols as you wish. But U-Boot's driver > > > > > > > > > > > > > > > > model only allows a single interface per device. Up to now U-Boot has > > > > > > > > > > > > > > > > overcome this limitation by creating child devices for the extra interfaces. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > We have the following logical levels: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Controller | Block device | Software Partition| File system > > > > > > > > > > > > > > > > ----------------+--------------+-------------------+------------ > > > > > > > > > > > > > > > > NVMe Drive | Namespace | Partition 1..n | FAT, EXT4 > > > > > > > > > > > > > > > > ATA Controller | ATA-Drive | | > > > > > > > > > > > > > > > > SCSI Controller | LUN | | > > > > > > > > > > > > > > > > MMC Controller | HW-Partition | | > > > > > > > > > > > > > > > > MMC Controller | SD-Card | | > > > > > > > > > > > > > > > > USB-Node | USB-Drive | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > In the device tree this could be modeled as: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |-- Controller (UCLASS_CTRL) > > > > > > > > > > > > > > > > | |-- Block device / HW Partition (UCLASS_BLK) (A) > > > > > > > > > > > > > > > > | | |-- Partition table (UCLASS_PARTITION_TABLE) (B) > > > > > > > > > > > > > > > > | | |-- Software Partition (UCLASS_BLK) > > > > > > > > > > > > > > > > | | |-- File system (UCLASS_FS) > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > | |-- Block device (UCLASS_BLK) > > > > > > > > > > > > > > > > | |-- File system (UCLASS_FS) > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > I don't know why we expect PARTITION_TABLE and FS to appear in DM tree. > > > > > > > > > > > > > > > What is the benefit? > > > > > > > > > > > > > > > (A) and (B) always have 1:1 relationship. > > > > > > > > > > > > > > > > > > > > > > > > > > > > No. You can have a bare device without a partition table. > > > > > > > > > > > > > > > > > > > > > > > > > > I can have a DOS partition that covers the whole device, without a > > > > > > > > > > > > > partition table. This is supported in U-Boot and Linux. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > We have several partition table drivers: DOS, GPT, OSX, ... . In future we should also have one for the NOR Flash partitions. All of these drivers have a common interface. As the partition table type is mostly independent of the block device type we should use separate uclasses and udevices. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > I also remember that you claimed that not all efi objects(handles and > > > > > > > > > > > > > > > protocols like SIMPE_FILE_SYSTEM_PROTOCOL) need to have corresponding > > > > > > > > > > > > > > > U-Boot counterparts in our 2019 discussion. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > If we *need* PARTITION_TALBLE, why don't we have HW_PARTITION_TABLE, > > > > > > > > > > > > > > > which should support other type of hw partitions as well? > > > > > > > > > > > > > > > > > > > > > > > > > > > > How hardware partitions, LUNs, ATA drives are enumerated is specific to the type of controller while the type of software partition table is independent of the block device. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |-- eMMC controller (UCLASS_MMC) > > > > > > > > > > > > > > > | |-- eMMC device1 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > > > > > > > > > > > > | |-- Block device / HW Partition:user data (UCLASS_BLK) > > > > > > > > > > > > > > > | | |-- Partition table (UCLASS_PARTITION_TABLE) > > > > > > > > > > > > > > > | | |-- Software Partition (UCLASS_BLK) > > > > > > > > > > > > > > > | | |-- File system (UCLASS_FS) > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > | |-- Block device / HW Partition:boot0 (UCLASS_BLK) > > > > > > > > > > > > > > > | |-- Block device / HW Partition:boot1 (UCLASS_BLK) > > > > > > > > > > > > > > > ... > > > > > > > > > > > > > > > | |-- eMMC device2 / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |-- scsi controller (UCLASS_SCSI) > > > > > > > > > > > > > > > | |-- scsi disk / Physical media (UCLASS_HW_PARTITION_TABLE?) > > > > > > > > > > > > > > > | |-- scsi LUN1 (UCLASS_HW_PARTITION_TABLE?) > > > > > > > > > > > > > > > | | |-- Partition table (UCLASS_PARTITION_TABLE) > > > > > > > > > > > > > > > | | |-- Software Partition (UCLASS_BLK) > > > > > > > > > > > > > > > | |-- scsi LUN2 (UCLASS_HW_PARTITION_TABLE?) > > > > > > > > > > > > > > > ... > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > (Here I ignored scsi buses/channels which make things more complicated.) > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > This kind of complex hierarchy doesn't benefit anybody. > > > > > > > > > > > > > > > > > > > > > > > > > > > > All these levels exist already. We simply do not model them yet in the DM way. > > > > > > > > > > > > > > > > > > > > > > > > > > > > The device tree depth is the outcome of the udevice exposing always only a single interface defined by the uclass. > > > > > > > > > > > > > > > > > > > > > > > > > > > > The UEFI design allows installing multiple protocol interfaces on a single handle. This may result in simpler device trees in some cases. > > > > > > > > > > > > > > > > > > > > > > > > > > Yes, the complexity has to go somewhere. With driver model I chose to > > > > > > > > > > > > > have a single interface per uclass, since it is simpler to understand, > > > > > > > > > > > > > no need to request a protocol for a device, etc. > > > > > > > > > > > > > > > > > > > > > > > > > > Our current setup is similar to this > > > > > > > > > > > > > > > > > > > > > > > > > > |-- Controller (UCLASS_MMC) > > > > > > > > > > > > > | |-- Block device (UCLASS_BLK) - 'usual' HW partition > > > > > > > > > > > > > | |-- Block device (UCLASS_BLK) - e.g. for a different HW partition* > > > > > > > > > > > > > > > > > > > > > > > > > > * although I don't think the MMC code actually supports it - SCSI does though > > > > > > > > > > > > > > > > > > > > > > > > > > We want to add devices for the partition table and the filesystem, so could do: > > > > > > > > > > > > > > > > > > > > > > > > > > |-- Controller (UCLASS_MMC) > > > > > > > > > > > > > | |-- Block device (UCLASS_BLK) - 'usual' HW partition (the whole device) > > > > > > > > > > > > > | | |-- Partition table (UCLASS_PART) - DOS partition (or EFI) > > > > > > > > > > > > > | | | |-- Block device (UCLASS_BLK) - partition 1 > > > > > > > > > > > > > | | | | |-- Filesystem (UCLASS_FS) - DOS filesystem > > > > > > > > > > > > > | | | |-- Block device (UCLASS_BLK) - partition 2 > > > > > > > > > > > > > | | | | |-- Filesystem (UCLASS_FS) - ext5 filesystem > > > > > > > > > > > > > | |-- Block device (UCLASS_BLK) - e.g. for a different HW > > > > > > > > > > > > > partition (the whole device) > > > > > > > > > > > > > > > > > > > > > > > > > > This is similar to Heinrich's, but without the top-level > > > > > > > > > > > > > UCLASS_HW_PARTITION_TABLE which I am not sure is necessary. > > > > > > > > > > > > > > > > > > > > > > > > Are further MMC hw partitions, multiple SCSI LUNs and multiple NVME namespaces already treated as separate BLK devices? > > > > > > > > > > > > > > > > > > > > > > Yes. > > > > > > > > > > > What I meant to say is that, if we don't need a partition table 'udevice' > > > > > > > > > > > for hw partitions, we don't need such a device for sw partitions neither. > > > > > > > > > > > > > > > > > > > > > > Meanwhile, what about UCLASS_FS? Why do we need this? > > > > > > > > > > > > > > > > > > > > We don't need it for our current discussion, but if we want to 'open' > > > > > > > > > > the filesystem and keep the metadata around, rather than reading it > > > > > > > > > > again every time we access a file, we might find it useful. Open files > > > > > > > > > > could be children of the FS uclass, perhaps, if we go a step further > > > > > > > > > > and create devices for them. > > > > > > > > > > > > > > > > > > Do you want to invent linux-like mount-point concepts or procfs? > > > > > > > > > I remember that you didn't want to have child nodes under BLK devices. > > > > > > > > > I'm getting confused about our goal. > > > > > > > > > > > > > > > > I think we are all a bit unsure. > > > > > > > > > > > > > > > > I think BLK devices can have children, sorry if I said the wrong thing > > > > > > > > somewhere along the way. For example, a partition would be under a BLK > > > > > > > > device, or a FS. > > > > > > > > > > > > > > > > > What should DM represent in U-Boot world? > > > > > > > > > > > > > > > > That is what we are trying to figure out. > > > > > > > > > > > > > > > > I think the minimum is to have a a way to represent partitions (s/w > > > > > > > > and hw/). As I understand it, that's what we've been discussing. > > > > > > > > > > > > > > The discovery of hardware partitions is specific to the block device > > > > > > > controller SCSI/MMC/ATA/NVMe. We currently do not provide any > > > > > > > manipulation commands to create hardware partitions (e.g. NVMe > > > > > > > namespaces, SCSI LUNs). This is why extracting a uclass for hardware > > > > > > > partitions does not seem necessary. > > > > > > > > > > > > I can see the reasoning here. It might not stand the test of time but > > > > > > how about we go with it for now? For MMC hardware partition we would > > > > > > just end up with multiple BLK devices, like we do with SCSI LUNs at > > > > > > present, which seems like it should work (with some code tweaks). > > > > > > > > > > > > > > > > > > > > Software partitioning (MBR, GPT, ...) is independent of the harboring > > > > > > > block device. > > > > > > > > > > > > > > We already have a set of drivers for software partition tables in disk/. > > > > > > > Currently the available methods of the drivers are defined in > > > > > > > U_BOOT_PART_TYPE referring to struct part_driver. > > > > > > > > > > > > > > Currently struct part_driver knows only the following methods: > > > > > > > > > > > > > > - get_info() > > > > > > > - print() > > > > > > > - test() > > > > > > > > > > > > > > These drivers should be ome a uclass. > > > > > > > > > > > > > > gpt.c and mbr.c allow to create and delete partitions. I think we should add > > > > > > > > > > > > > > - create_partition() > > > > > > > - delete_partition() > > > > > > > > > > > > > > to the uclass methods. > > > > > > > > > > > > That sounds good to me, although since it is a partition uclass, we > > > > > > can just use create() and delete(). > > > > > > > > > > I don't know why we need a "partition table" device in the middle > > > > > of DM hierarchy. > > > > > I believe that it simply makes the view of DM tree complicated > > > > > without any explicit benefit. > > > > > > > > Well we clearly have an API here. The partition uclass can: > > > > > > > > - hold the partition table in dev_get_uclass_priv() > > > > - support a read() operation to read the partition > > > > - support create() to rewrite the partition table > > > > - support delete() to overwrite/erase the partition table > > > > > > > > Then it means that filesystems have the partition table as a parent > > > > (unless they are whole-device filesystems), which makes sense > > > > > > > > So that's why I like the idea. > > > > > > > > Other than the extra complexity, is there anything else wrong with it? > > > > > > - First of all, a partition table doesn't look like a 'device' at all. > > > - Second, a partition table is just static data for block devices. > > > IMO, even if we want to have this data, we can simply hold it > > > as some sort of attribute of the device, or maybe as a 'tag' which > > > I will introduce in the next version. > > > > > > -Takahiro Akashi > > > > > > > I don't know how this affect the code, but I agree with Akashi-san > > here. It's indeed useful to keep the partition table stored > > somewhere, but I think not showing them as part of the device tree is > > more intuitive. > > Well I think I'm easy either way. I just thought that Heinrich made a > good case for having a partition uclass. > > But as Takahiro says, we can use a tag to attach the partition table > to the device. But it should be attached to the device's children (the > BLK device) not the media device itself, right?
As there has been no discussion in 5 days and Takahiro is writing this, let's go with no uclass for the partition table.
Without uclass you cannot bring the partition table drivers into th driver model.
This transition may be able to be done later when really necessary as long as we agree that a partition table be hold within a "raw" disk object (with a tag support). # I don't think we need it for now.
No clue what a tag should be in the driver model.
A tag is a way to associate data with a device. At present we do this with varoius built-in mechanisms (priv data, uclass-priv, plat, etc.) but with tags you can add something else.
Since this discussion thread is getting too long, I would like to respin my RFC. How should I deal with your "event notification" proposal?
Is the patch good enough to include in the series?
If not, you could reply to it with what needs doing.
? I have already replied to your patch :) Basically, it seems to be fine to me.
Regards, Simon
The patch is not usable as is. It assumes only GPT partioning is used.
@Heinrich I don't get your point. Either my patch or Simon's is not specific to GPT at all.
So I'm going to start respinning my patch for a next round of discussion.
-Takahiro Akashi
Instead all partition table drivers need to be converted to drivers for the new uclass.
Best regards
Heinrich

On 11/16/21 00:51, AKASHI Takahiro wrote:
Is the patch good enough to include in the series?
If not, you could reply to it with what needs doing.
? I have already replied to your patch:) Basically, it seems to be fine to me.
Regards, Simon
The patch is not usable as is. It assumes only GPT partioning is used.
@Heinrich I don't get your point. Either my patch or Simon's is not specific to GPT at all.
So I'm going to start respinning my patch for a next round of discussion.
A field name gpt_part_info obviously relates to GPT? Up to now this string exists only in cmd/gpt.c.
Best regards
Heinrich
-Takahiro Akashi
Instead all partition table drivers need to be converted to drivers for the new uclass.
Best regards
Heinrich

On Tue, Nov 16, 2021 at 01:02:55AM +0100, Heinrich Schuchardt wrote:
On 11/16/21 00:51, AKASHI Takahiro wrote:
Is the patch good enough to include in the series?
If not, you could reply to it with what needs doing.
? I have already replied to your patch:) Basically, it seems to be fine to me.
Regards, Simon
The patch is not usable as is. It assumes only GPT partioning is used.
@Heinrich I don't get your point. Either my patch or Simon's is not specific to GPT at all.
So I'm going to start respinning my patch for a next round of discussion.
A field name gpt_part_info obviously relates to GPT?
No.
IICU, the structure, disk_partition, is not particularly GPT-specific as such type of data are used over various partition drivers. In my patch series, I simply reuse "struct disk_part" as a structure holding a partition number and partition information (= disk_partition).
-Takahiro Akashi
Up to now this string exists only in cmd/gpt.c.
Best regards
Heinrich
-Takahiro Akashi
Instead all partition table drivers need to be converted to drivers for the new uclass.
Best regards
Heinrich

Heinrich,
On Tue, Nov 16, 2021 at 12:01:27PM +0900, AKASHI Takahiro wrote:
On Tue, Nov 16, 2021 at 01:02:55AM +0100, Heinrich Schuchardt wrote:
On 11/16/21 00:51, AKASHI Takahiro wrote:
Is the patch good enough to include in the series?
If not, you could reply to it with what needs doing.
? I have already replied to your patch:) Basically, it seems to be fine to me.
Regards, Simon
The patch is not usable as is. It assumes only GPT partioning is used.
@Heinrich I don't get your point. Either my patch or Simon's is not specific to GPT at all.
So I'm going to start respinning my patch for a next round of discussion.
A field name gpt_part_info obviously relates to GPT?
No.
IICU, the structure, disk_partition, is not particularly GPT-specific as such type of data are used over various partition drivers. In my patch series, I simply reuse "struct disk_part" as a structure holding a partition number and partition information (= disk_partition).
So do you agree that we won't have "partition-table" devices for now?
-Takahiro Akashi
-Takahiro Akashi
Up to now this string exists only in cmd/gpt.c.
Best regards
Heinrich
-Takahiro Akashi
Instead all partition table drivers need to be converted to drivers for the new uclass.
Best regards
Heinrich

On 12/3/21 08:16, AKASHI Takahiro wrote:
Heinrich,
On Tue, Nov 16, 2021 at 12:01:27PM +0900, AKASHI Takahiro wrote:
On Tue, Nov 16, 2021 at 01:02:55AM +0100, Heinrich Schuchardt wrote:
On 11/16/21 00:51, AKASHI Takahiro wrote:
Is the patch good enough to include in the series?
If not, you could reply to it with what needs doing.
? I have already replied to your patch:) Basically, it seems to be fine to me.
Regards, Simon
The patch is not usable as is. It assumes only GPT partioning is used.
@Heinrich I don't get your point. Either my patch or Simon's is not specific to GPT at all.
So I'm going to start respinning my patch for a next round of discussion.
A field name gpt_part_info obviously relates to GPT?
No.
IICU, the structure, disk_partition, is not particularly GPT-specific as such type of data are used over various partition drivers. In my patch series, I simply reuse "struct disk_part" as a structure holding a partition number and partition information (= disk_partition).
So do you agree that we won't have "partition-table" devices for now?
-Takahiro Akashi
We don't need the partition-table to be a udevice now. We still can later convert the partition drivers to a uclass if we deem it helpful.
Best regards
Heinrich
-Takahiro Akashi
Up to now this string exists only in cmd/gpt.c.
Best regards
Heinrich
-Takahiro Akashi
Instead all partition table drivers need to be converted to drivers for the new uclass.
Best regards
Heinrich

On Fri, Dec 03, 2021 at 05:06:56PM +0100, Heinrich Schuchardt wrote:
On 12/3/21 08:16, AKASHI Takahiro wrote:
Heinrich,
On Tue, Nov 16, 2021 at 12:01:27PM +0900, AKASHI Takahiro wrote:
On Tue, Nov 16, 2021 at 01:02:55AM +0100, Heinrich Schuchardt wrote:
On 11/16/21 00:51, AKASHI Takahiro wrote:
> Is the patch good enough to include in the series? > > If not, you could reply to it with what needs doing.
? I have already replied to your patch:) Basically, it seems to be fine to me.
> Regards, > Simon > The patch is not usable as is. It assumes only GPT partioning is used.
@Heinrich I don't get your point. Either my patch or Simon's is not specific to GPT at all.
So I'm going to start respinning my patch for a next round of discussion.
A field name gpt_part_info obviously relates to GPT?
No.
IICU, the structure, disk_partition, is not particularly GPT-specific as such type of data are used over various partition drivers. In my patch series, I simply reuse "struct disk_part" as a structure holding a partition number and partition information (= disk_partition).
So do you agree that we won't have "partition-table" devices for now?
-Takahiro Akashi
We don't need the partition-table to be a udevice now. We still can later convert the partition drivers to a uclass if we deem it helpful.
OK. I'm going to prepare for next RFC.
-Takahiro Akashi
Best regards
Heinrich
-Takahiro Akashi
Up to now this string exists only in cmd/gpt.c.
Best regards
Heinrich
-Takahiro Akashi
Instead all partition table drivers need to be converted to drivers for the new uclass.
Best regards
Heinrich

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{
int part, count;
struct blk_desc *desc = dev_get_uclass_plat(parent);
struct disk_partition info;
struct disk_part *part_data;
char devname[32];
struct udevice *dev;
int ret;
if (!CONFIG_IS_ENABLED(PARTITIONS) ||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
return 0;
/* Add devices for each partition */
for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", parent->name,
part);
ret = device_bind_driver(parent, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
device_probe(dev);
}
debug("%s: %d partitions found in %s\n", __func__, count, parent->name);
log_debug() and drop __func__
return 0;
+}
static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) && @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), };
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
part_blk_read() so that it is clear that this takes a UCLASS_PARTITION device, not a UCLASS_BLK
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->read)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
start += part->gpt_part_info.start;
return ops->read(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->write)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
start += part->gpt_part_info.start;
return ops->write(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->erase)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
start += part->gpt_part_info.start;
return ops->erase(parent, start, blkcnt);
+}
+static const struct blk_ops blk_part_ops = {
.read = blk_part_read,
.write = blk_part_write,
.erase = blk_part_erase,
+};
+U_BOOT_DRIVER(blk_partition) = {
.name = "blk_partition",
.id = UCLASS_PARTITION,
.ops = &blk_part_ops,
+};
Can you put this all in a separate part-uclass.c file? This too:
+UCLASS_DRIVER(partition) = {
.id = UCLASS_PARTITION,
.per_device_plat_auto = sizeof(struct disk_part),
.name = "partition",
+}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/**
- blk_create_partitions - Create block devices for disk partitions
- Create UCLASS_PARTITION udevices for each of disk partitions in @parent
- @parent: Whole disk device
UCLASS_BLK?
It is good to document the device types to avoid people getting confused later.
- */
+int blk_create_partitions(struct udevice *parent);
/**
- blk_unbind_all() - Unbind all device of the given interface type
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */
-- 2.33.0
This is a new uclass so needs a sandbox test.
Regards, Simon

Simon,
On Sun, Oct 10, 2021 at 08:14:34AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{
int part, count;
struct blk_desc *desc = dev_get_uclass_plat(parent);
struct disk_partition info;
struct disk_part *part_data;
char devname[32];
struct udevice *dev;
int ret;
if (!CONFIG_IS_ENABLED(PARTITIONS) ||
!CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
return 0;
/* Add devices for each partition */
for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info))
continue;
snprintf(devname, sizeof(devname), "%s:%d", parent->name,
part);
ret = device_bind_driver(parent, "blk_partition",
strdup(devname), &dev);
if (ret)
return ret;
part_data = dev_get_uclass_plat(dev);
part_data->partnum = part;
part_data->gpt_part_info = info;
count++;
device_probe(dev);
}
debug("%s: %d partitions found in %s\n", __func__, count, parent->name);
log_debug() and drop __func__
OK.
return 0;
+}
static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) && @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), };
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
part_blk_read() so that it is clear that this takes a UCLASS_PARTITION device, not a UCLASS_BLK
OK.
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->read)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
start += part->gpt_part_info.start;
return ops->read(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->write)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
start += part->gpt_part_info.start;
return ops->write(parent, start, blkcnt, buffer);
+}
+static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
struct udevice *parent;
struct disk_part *part;
const struct blk_ops *ops;
parent = dev_get_parent(dev);
ops = blk_get_ops(parent);
if (!ops->erase)
return -ENOSYS;
part = dev_get_uclass_plat(dev);
start += part->gpt_part_info.start;
return ops->erase(parent, start, blkcnt);
+}
+static const struct blk_ops blk_part_ops = {
.read = blk_part_read,
.write = blk_part_write,
.erase = blk_part_erase,
+};
+U_BOOT_DRIVER(blk_partition) = {
.name = "blk_partition",
.id = UCLASS_PARTITION,
.ops = &blk_part_ops,
+};
Can you put this all in a separate part-uclass.c file? This too:
OK. Then put the file under disk/, driver/block or driver/partition?
+UCLASS_DRIVER(partition) = {
.id = UCLASS_PARTITION,
.per_device_plat_auto = sizeof(struct disk_part),
.name = "partition",
+}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/**
- blk_create_partitions - Create block devices for disk partitions
- Create UCLASS_PARTITION udevices for each of disk partitions in @parent
- @parent: Whole disk device
UCLASS_BLK?
It is good to document the device types to avoid people getting confused later.
OK.
- */
+int blk_create_partitions(struct udevice *parent);
/**
- blk_unbind_all() - Unbind all device of the given interface type
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */
UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */
-- 2.33.0
This is a new uclass so needs a sandbox test.
Yes, I intend to do so with pytest once we have some consensus on interfaces.
-Takahiro Akashi
Regards, Simon

UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 111 +++++++++++++++++++++++++++++++++++++ include/blk.h | 9 +++ include/dm/uclass-id.h | 1 + 3 files changed, 121 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dcc181a..dd7f3c0fe31e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -12,6 +12,7 @@ #include <log.h> #include <malloc.h> #include <part.h> +#include <string.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/uclass-internal.h> @@ -695,6 +696,44 @@ int blk_unbind_all(int if_type) return 0; }
+int blk_create_partitions(struct udevice *parent) +{ + int part, count; + struct blk_desc *desc = dev_get_uclass_plat(parent); + struct disk_partition info; + struct disk_part *part_data; + char devname[32]; + struct udevice *dev; + int ret; + + if (!CONFIG_IS_ENABLED(PARTITIONS) || + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) + return 0; + + /* Add devices for each partition */ + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { + if (part_get_info(desc, part, &info)) + continue; + snprintf(devname, sizeof(devname), "%s:%d", parent->name, + part); + + ret = device_bind_driver(parent, "blk_partition", + strdup(devname), &dev); + if (ret) + return ret; + + part_data = dev_get_uclass_plat(dev); + part_data->partnum = part; + part_data->gpt_part_info = info; + count++; + + device_probe(dev); + } + debug("%s: %d partitions found in %s\n", __func__, count, parent->name); + + return 0; +} + static int blk_post_probe(struct udevice *dev) { if (IS_ENABLED(CONFIG_PARTITIONS) && @@ -713,3 +752,75 @@ UCLASS_DRIVER(blk) = { .post_probe = blk_post_probe, .per_device_plat_auto = sizeof(struct blk_desc), }; + +static ulong blk_part_read(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct udevice *parent; + struct disk_part *part; + const struct blk_ops *ops; + + parent = dev_get_parent(dev); + ops = blk_get_ops(parent); + if (!ops->read) + return -ENOSYS; + + part = dev_get_uclass_plat(dev); + start += part->gpt_part_info.start; + + return ops->read(parent, start, blkcnt, buffer); +} + +static ulong blk_part_write(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + struct udevice *parent; + struct disk_part *part; + const struct blk_ops *ops; + + parent = dev_get_parent(dev); + ops = blk_get_ops(parent); + if (!ops->write) + return -ENOSYS; + + part = dev_get_uclass_plat(dev); + start += part->gpt_part_info.start; + + return ops->write(parent, start, blkcnt, buffer); +} + +static ulong blk_part_erase(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt) +{ + struct udevice *parent; + struct disk_part *part; + const struct blk_ops *ops; + + parent = dev_get_parent(dev); + ops = blk_get_ops(parent); + if (!ops->erase) + return -ENOSYS; + + part = dev_get_uclass_plat(dev); + start += part->gpt_part_info.start; + + return ops->erase(parent, start, blkcnt); +} + +static const struct blk_ops blk_part_ops = { + .read = blk_part_read, + .write = blk_part_write, + .erase = blk_part_erase, +}; + +U_BOOT_DRIVER(blk_partition) = { + .name = "blk_partition", + .id = UCLASS_PARTITION, + .ops = &blk_part_ops, +}; + +UCLASS_DRIVER(partition) = { + .id = UCLASS_PARTITION, + .per_device_plat_auto = sizeof(struct disk_part), + .name = "partition", +}; diff --git a/include/blk.h b/include/blk.h index 19bab081c2cd..3d883eb1db64 100644 --- a/include/blk.h +++ b/include/blk.h @@ -366,6 +366,15 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t lba, struct udevice **devp);
+/** + * blk_create_partitions - Create block devices for disk partitions + * + * Create UCLASS_PARTITION udevices for each of disk partitions in @parent + * + * @parent: Whole disk device + */ +int blk_create_partitions(struct udevice *parent); + /** * blk_unbind_all() - Unbind all device of the given interface type * diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index e7edd409f307..30892d01ce13 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_P2SB, /* (x86) Primary-to-Sideband Bus */ UCLASS_PANEL, /* Display panel, such as an LCD */ UCLASS_PANEL_BACKLIGHT, /* Backlight controller for panel */ + UCLASS_PARTITION, /* Logical disk partition device */ UCLASS_PCH, /* x86 platform controller hub */ UCLASS_PCI, /* PCI bus */ UCLASS_PCI_EP, /* PCI endpoint device */

On 10/1/21 07:01, AKASHI Takahiro wrote:
UCLASS_PARTITION device will be created as a child node of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
This patch seems to duplicate 7/22.
Best regards
Heinrich

Now that all the block device drivers have enable a probe hook, we will call blk_create_partitions() to enumerate all the partitions and create associated udevices when a block device is detected.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index dd7f3c0fe31e..6ba11a8fa7f7 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -741,11 +741,25 @@ static int blk_post_probe(struct udevice *dev) struct blk_desc *desc = dev_get_uclass_plat(dev);
part_init(desc); + + if (desc->part_type != PART_TYPE_UNKNOWN && + blk_create_partitions(dev)) + debug("*** creating partitions failed\n"); }
return 0; }
+static int blk_part_post_probe(struct udevice *dev) +{ + /* + * TODO: + * If we call blk_creat_partitions() here, it would allow for + * "partitions in a partition". + */ + return 0; +} + UCLASS_DRIVER(blk) = { .id = UCLASS_BLK, .name = "blk", @@ -821,6 +835,7 @@ U_BOOT_DRIVER(blk_partition) = {
UCLASS_DRIVER(partition) = { .id = UCLASS_PARTITION, + .post_probe = blk_part_post_probe, .per_device_plat_auto = sizeof(struct disk_part), .name = "partition", };

On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Now that all the block device drivers have enable a probe hook, we will call blk_create_partitions() to enumerate all the partitions and create associated udevices when a block device is detected.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But I don't see blk_create_partitions() in this patch.
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index dd7f3c0fe31e..6ba11a8fa7f7 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -741,11 +741,25 @@ static int blk_post_probe(struct udevice *dev) struct blk_desc *desc = dev_get_uclass_plat(dev);
part_init(desc);
if (desc->part_type != PART_TYPE_UNKNOWN &&
blk_create_partitions(dev))
debug("*** creating partitions failed\n"); } return 0;
}
+static int blk_part_post_probe(struct udevice *dev) +{
/*
* TODO:
* If we call blk_creat_partitions() here, it would allow for
* "partitions in a partition".
*/
Would that be useful?
return 0;
+}
UCLASS_DRIVER(blk) = { .id = UCLASS_BLK, .name = "blk", @@ -821,6 +835,7 @@ U_BOOT_DRIVER(blk_partition) = {
UCLASS_DRIVER(partition) = { .id = UCLASS_PARTITION,
.post_probe = blk_part_post_probe, .per_device_plat_auto = sizeof(struct disk_part), .name = "partition",
};
2.33.0

Now that all the block device drivers have enable a probe hook, we will call blk_create_partitions() to enumerate all the partitions and create associated udevices when a block device is detected.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index dd7f3c0fe31e..6ba11a8fa7f7 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -741,11 +741,25 @@ static int blk_post_probe(struct udevice *dev) struct blk_desc *desc = dev_get_uclass_plat(dev);
part_init(desc); + + if (desc->part_type != PART_TYPE_UNKNOWN && + blk_create_partitions(dev)) + debug("*** creating partitions failed\n"); }
return 0; }
+static int blk_part_post_probe(struct udevice *dev) +{ + /* + * TODO: + * If we call blk_creat_partitions() here, it would allow for + * "partitions in a partition". + */ + return 0; +} + UCLASS_DRIVER(blk) = { .id = UCLASS_BLK, .name = "blk", @@ -821,6 +835,7 @@ U_BOOT_DRIVER(blk_partition) = {
UCLASS_DRIVER(partition) = { .id = UCLASS_PARTITION, + .post_probe = blk_part_post_probe, .per_device_plat_auto = sizeof(struct disk_part), .name = "partition", };

In include/blk.h, Simon suggested: ===> /* * These functions should take struct udevice instead of struct blk_desc, * but this is convenient for migration to driver model. Add a 'd' prefix * to the function operations, so that blk_read(), etc. can be reserved for * functions with the correct arguments. */ unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer); unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, const void *buffer); unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); <===
So new interfaces are provided with this patch.
They are expected to be used everywhere in U-Boot at the end. The exceptions are block device drivers, partition drivers and efi_disk which should know details of blk_desc structure.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 91 ++++++++++++++++++++++++++++++++++++++ include/blk.h | 6 +++ 2 files changed, 97 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 6ba11a8fa7f7..8fbec8779e1e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -482,6 +482,97 @@ unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, return ops->erase(dev, start, blkcnt); }
+static struct blk_desc *dev_get_blk(struct udevice *dev) +{ + struct blk_desc *block_dev; + + switch (device_get_uclass_id(dev)) { + case UCLASS_BLK: + block_dev = dev_get_uclass_plat(dev); + break; + case UCLASS_PARTITION: + block_dev = dev_get_uclass_plat(dev_get_parent(dev)); + break; + default: + block_dev = NULL; + break; + } + + return block_dev; +} + +unsigned long blk_read(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct blk_desc *block_dev; + const struct blk_ops *ops; + struct disk_part *part; + lbaint_t start_in_disk; + ulong blks_read; + + block_dev = dev_get_blk(dev); + if (!block_dev) + return -ENOSYS; + + ops = blk_get_ops(dev); + if (!ops->read) + return -ENOSYS; + + start_in_disk = start; + if (device_get_uclass_id(dev) == UCLASS_PARTITION) { + part = dev_get_uclass_plat(dev); + start_in_disk += part->gpt_part_info.start; + } + + if (blkcache_read(block_dev->if_type, block_dev->devnum, + start_in_disk, blkcnt, block_dev->blksz, buffer)) + return blkcnt; + blks_read = ops->read(dev, start, blkcnt, buffer); + if (blks_read == blkcnt) + blkcache_fill(block_dev->if_type, block_dev->devnum, + start_in_disk, blkcnt, block_dev->blksz, buffer); + + return blks_read; +} + +unsigned long blk_write(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + struct blk_desc *block_dev; + const struct blk_ops *ops; + + block_dev = dev_get_blk(dev); + if (!block_dev) + return -ENOSYS; + + ops = blk_get_ops(dev); + if (!ops->write) + return -ENOSYS; + + blkcache_invalidate(block_dev->if_type, block_dev->devnum); + + return ops->write(dev, start, blkcnt, buffer); +} + +unsigned long blk_erase(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt) +{ + struct blk_desc *block_dev; + const struct blk_ops *ops; + + block_dev = dev_get_blk(dev); + if (!block_dev) + return -ENOSYS; + + ops = blk_get_ops(dev); + if (!ops->erase) + return -ENOSYS; + + blkcache_invalidate(block_dev->if_type, block_dev->devnum); + + return ops->erase(dev, start, blkcnt); +} + int blk_get_from_parent(struct udevice *parent, struct udevice **devp) { struct udevice *dev; diff --git a/include/blk.h b/include/blk.h index 3d883eb1db64..f5fdd6633a09 100644 --- a/include/blk.h +++ b/include/blk.h @@ -284,6 +284,12 @@ unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt);
+unsigned long blk_read(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *buffer); +unsigned long blk_write(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer); +unsigned long blk_erase(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt); /** * blk_find_device() - Find a block device *

In include/blk.h, Simon suggested: ===> /* * These functions should take struct udevice instead of struct blk_desc, * but this is convenient for migration to driver model. Add a 'd' prefix * to the function operations, so that blk_read(), etc. can be reserved for * functions with the correct arguments. */ unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer); unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, const void *buffer); unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); <===
So new interfaces are provided with this patch.
They are expected to be used everywhere in U-Boot at the end. The exceptions are block device drivers, partition drivers and efi_disk which should know details of blk_desc structure.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 91 ++++++++++++++++++++++++++++++++++++++ include/blk.h | 6 +++ 2 files changed, 97 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 6ba11a8fa7f7..8fbec8779e1e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -482,6 +482,97 @@ unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, return ops->erase(dev, start, blkcnt); }
+static struct blk_desc *dev_get_blk(struct udevice *dev) +{ + struct blk_desc *block_dev; + + switch (device_get_uclass_id(dev)) { + case UCLASS_BLK: + block_dev = dev_get_uclass_plat(dev); + break; + case UCLASS_PARTITION: + block_dev = dev_get_uclass_plat(dev_get_parent(dev)); + break; + default: + block_dev = NULL; + break; + } + + return block_dev; +} + +unsigned long blk_read(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct blk_desc *block_dev; + const struct blk_ops *ops; + struct disk_part *part; + lbaint_t start_in_disk; + ulong blks_read; + + block_dev = dev_get_blk(dev); + if (!block_dev) + return -ENOSYS; + + ops = blk_get_ops(dev); + if (!ops->read) + return -ENOSYS; + + start_in_disk = start; + if (device_get_uclass_id(dev) == UCLASS_PARTITION) { + part = dev_get_uclass_plat(dev); + start_in_disk += part->gpt_part_info.start; + } + + if (blkcache_read(block_dev->if_type, block_dev->devnum, + start_in_disk, blkcnt, block_dev->blksz, buffer)) + return blkcnt; + blks_read = ops->read(dev, start, blkcnt, buffer); + if (blks_read == blkcnt) + blkcache_fill(block_dev->if_type, block_dev->devnum, + start_in_disk, blkcnt, block_dev->blksz, buffer); + + return blks_read; +} + +unsigned long blk_write(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + struct blk_desc *block_dev; + const struct blk_ops *ops; + + block_dev = dev_get_blk(dev); + if (!block_dev) + return -ENOSYS; + + ops = blk_get_ops(dev); + if (!ops->write) + return -ENOSYS; + + blkcache_invalidate(block_dev->if_type, block_dev->devnum); + + return ops->write(dev, start, blkcnt, buffer); +} + +unsigned long blk_erase(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt) +{ + struct blk_desc *block_dev; + const struct blk_ops *ops; + + block_dev = dev_get_blk(dev); + if (!block_dev) + return -ENOSYS; + + ops = blk_get_ops(dev); + if (!ops->erase) + return -ENOSYS; + + blkcache_invalidate(block_dev->if_type, block_dev->devnum); + + return ops->erase(dev, start, blkcnt); +} + int blk_get_from_parent(struct udevice *parent, struct udevice **devp) { struct udevice *dev; diff --git a/include/blk.h b/include/blk.h index 3d883eb1db64..f5fdd6633a09 100644 --- a/include/blk.h +++ b/include/blk.h @@ -284,6 +284,12 @@ unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt);
+unsigned long blk_read(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *buffer); +unsigned long blk_write(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer); +unsigned long blk_erase(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt); /** * blk_find_device() - Find a block device *

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:03, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In include/blk.h, Simon suggested: ===> /*
- These functions should take struct udevice instead of struct blk_desc,
- but this is convenient for migration to driver model. Add a 'd' prefix
- to the function operations, so that blk_read(), etc. can be reserved for
- functions with the correct arguments.
*/ unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *buffer); unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, const void *buffer); unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); <===
So new interfaces are provided with this patch.
They are expected to be used everywhere in U-Boot at the end. The exceptions are block device drivers, partition drivers and efi_disk which should know details of blk_desc structure.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 91 ++++++++++++++++++++++++++++++++++++++ include/blk.h | 6 +++ 2 files changed, 97 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 6ba11a8fa7f7..8fbec8779e1e 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -482,6 +482,97 @@ unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, return ops->erase(dev, start, blkcnt); }
+static struct blk_desc *dev_get_blk(struct udevice *dev) +{
struct blk_desc *block_dev;
switch (device_get_uclass_id(dev)) {
case UCLASS_BLK:
block_dev = dev_get_uclass_plat(dev);
break;
case UCLASS_PARTITION:
block_dev = dev_get_uclass_plat(dev_get_parent(dev));
break;
default:
block_dev = NULL;
break;
}
return block_dev;
+}
+unsigned long blk_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer)
+{
struct blk_desc *block_dev;
const struct blk_ops *ops;
struct disk_part *part;
lbaint_t start_in_disk;
ulong blks_read;
block_dev = dev_get_blk(dev);
if (!block_dev)
return -ENOSYS;
IMO blk_read() should take a block device. That is how all other DM APIs work. I think it is too confusing to use the parent device here.
So how about changing these functions to take a blk device, then adding new ones for what you want here, e.g.
int media_read(struct udevice *dev... { struct udevice *blk;
blk = dev_get_blk(dev); if (!blk) return -ENOSYS;
ret = blk_read(blk, ... }
Also can we use blk instead of block_dev?
ops = blk_get_ops(dev);
if (!ops->read)
return -ENOSYS;
start_in_disk = start;
if (device_get_uclass_id(dev) == UCLASS_PARTITION) {
part = dev_get_uclass_plat(dev);
start_in_disk += part->gpt_part_info.start;
}
if (blkcache_read(block_dev->if_type, block_dev->devnum,
start_in_disk, blkcnt, block_dev->blksz, buffer))
return blkcnt;
blks_read = ops->read(dev, start, blkcnt, buffer);
if (blks_read == blkcnt)
blkcache_fill(block_dev->if_type, block_dev->devnum,
start_in_disk, blkcnt, block_dev->blksz, buffer);
return blks_read;
+}
+unsigned long blk_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer)
+{
struct blk_desc *block_dev;
const struct blk_ops *ops;
block_dev = dev_get_blk(dev);
if (!block_dev)
return -ENOSYS;
ops = blk_get_ops(dev);
if (!ops->write)
return -ENOSYS;
blkcache_invalidate(block_dev->if_type, block_dev->devnum);
return ops->write(dev, start, blkcnt, buffer);
+}
+unsigned long blk_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt)
+{
struct blk_desc *block_dev;
const struct blk_ops *ops;
block_dev = dev_get_blk(dev);
if (!block_dev)
return -ENOSYS;
ops = blk_get_ops(dev);
if (!ops->erase)
return -ENOSYS;
blkcache_invalidate(block_dev->if_type, block_dev->devnum);
return ops->erase(dev, start, blkcnt);
+}
int blk_get_from_parent(struct udevice *parent, struct udevice **devp) { struct udevice *dev; diff --git a/include/blk.h b/include/blk.h index 3d883eb1db64..f5fdd6633a09 100644 --- a/include/blk.h +++ b/include/blk.h @@ -284,6 +284,12 @@ unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt);
+unsigned long blk_read(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, void *buffer);
+unsigned long blk_write(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt, const void *buffer);
+unsigned long blk_erase(struct udevice *dev, lbaint_t start,
lbaint_t blkcnt);
Please add full comments to these.
/**
- blk_find_device() - Find a block device
-- 2.33.0
Regards, Simon

In most of all usages, we can avoid using blk_desc which is expected to be data private to the device not be accessed outside device drivers.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_loader/efi_disk.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 988907ecb910..dfa6f898d586 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -45,7 +45,7 @@ struct efi_disk_obj { unsigned int part; struct efi_simple_file_system_protocol *volume; lbaint_t offset; - struct blk_desc *desc; + struct udevice *dev; /* TODO: move it to efi_object */ };
/** @@ -80,14 +80,12 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, void *buffer, enum efi_disk_direction direction) { struct efi_disk_obj *diskobj; - struct blk_desc *desc; int blksz; int blocks; unsigned long n;
diskobj = container_of(this, struct efi_disk_obj, ops); - desc = (struct blk_desc *) diskobj->desc; - blksz = desc->blksz; + blksz = diskobj->media.block_size; blocks = buffer_size / blksz; lba += diskobj->offset;
@@ -99,9 +97,9 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, return EFI_BAD_BUFFER_SIZE;
if (direction == EFI_DISK_READ) - n = blk_dread(desc, lba, blocks, buffer); + n = blk_read(diskobj->dev, lba, blocks, buffer); else - n = blk_dwrite(desc, lba, blocks, buffer); + n = blk_write(diskobj->dev, lba, blocks, buffer);
/* We don't do interrupts, so check for timers cooperatively */ efi_timer_check(); @@ -443,7 +441,6 @@ static efi_status_t efi_disk_add_dev( diskobj->ops = block_io_disk_template; diskobj->ifname = if_typename; diskobj->dev_index = dev_index; - diskobj->desc = desc;
/* Fill in EFI IO Media info (for read/write callbacks) */ diskobj->media.removable_media = desc->removable; @@ -647,20 +644,22 @@ bool efi_disk_is_system_part(efi_handle_t handle) { struct efi_handler *handler; struct efi_disk_obj *diskobj; - struct disk_partition info; + struct udevice *dev; + struct disk_part *part; efi_status_t ret; - int r;
/* check if this is a block device */ ret = efi_search_protocol(handle, &efi_block_io_guid, &handler); if (ret != EFI_SUCCESS) return false;
+ /* find a partition udevice */ diskobj = container_of(handle, struct efi_disk_obj, header); - - r = part_get_info(diskobj->desc, diskobj->part, &info); - if (r) + dev = diskobj->dev; + if (!dev || dev->driver->id != UCLASS_PARTITION) return false;
- return !!(info.bootable & PART_EFI_SYSTEM_PARTITION); + part = dev_get_uclass_plat(dev); + + return !!(part->gpt_part_info.bootable & PART_EFI_SYSTEM_PARTITION); }

This member field in udevice will be used to dereference from udevice to efi_object (or efi_handle).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/dm/device.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/dm/device.h b/include/dm/device.h index 0a9718a5b81a..33b09a836f06 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -190,6 +190,10 @@ struct udevice { #if CONFIG_IS_ENABLED(DM_DMA) ulong dma_offset; #endif +#if CONFIG_IS_ENABLED(EFI_LOADER) + /* link to efi_object */ + void *efi_obj; +#endif };
/**

In most of all usages, we can avoid accessing blk_desc which is eventually an internal data structure to be hided outside block device drivers.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_loader/efi_disk.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 988907ecb910..dfa6f898d586 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -45,7 +45,7 @@ struct efi_disk_obj { unsigned int part; struct efi_simple_file_system_protocol *volume; lbaint_t offset; - struct blk_desc *desc; + struct udevice *dev; /* TODO: move it to efi_object */ };
/** @@ -80,14 +80,12 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, void *buffer, enum efi_disk_direction direction) { struct efi_disk_obj *diskobj; - struct blk_desc *desc; int blksz; int blocks; unsigned long n;
diskobj = container_of(this, struct efi_disk_obj, ops); - desc = (struct blk_desc *) diskobj->desc; - blksz = desc->blksz; + blksz = diskobj->media.block_size; blocks = buffer_size / blksz; lba += diskobj->offset;
@@ -99,9 +97,9 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, return EFI_BAD_BUFFER_SIZE;
if (direction == EFI_DISK_READ) - n = blk_dread(desc, lba, blocks, buffer); + n = blk_read(diskobj->dev, lba, blocks, buffer); else - n = blk_dwrite(desc, lba, blocks, buffer); + n = blk_write(diskobj->dev, lba, blocks, buffer);
/* We don't do interrupts, so check for timers cooperatively */ efi_timer_check(); @@ -443,7 +441,6 @@ static efi_status_t efi_disk_add_dev( diskobj->ops = block_io_disk_template; diskobj->ifname = if_typename; diskobj->dev_index = dev_index; - diskobj->desc = desc;
/* Fill in EFI IO Media info (for read/write callbacks) */ diskobj->media.removable_media = desc->removable; @@ -647,20 +644,22 @@ bool efi_disk_is_system_part(efi_handle_t handle) { struct efi_handler *handler; struct efi_disk_obj *diskobj; - struct disk_partition info; + struct udevice *dev; + struct disk_part *part; efi_status_t ret; - int r;
/* check if this is a block device */ ret = efi_search_protocol(handle, &efi_block_io_guid, &handler); if (ret != EFI_SUCCESS) return false;
+ /* find a partition udevice */ diskobj = container_of(handle, struct efi_disk_obj, header); - - r = part_get_info(diskobj->desc, diskobj->part, &info); - if (r) + dev = diskobj->dev; + if (!dev || dev->driver->id != UCLASS_PARTITION) return false;
- return !!(info.bootable & PART_EFI_SYSTEM_PARTITION); + part = dev_get_uclass_plat(dev); + + return !!(part->gpt_part_info.bootable & PART_EFI_SYSTEM_PARTITION); }

On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
In most of all usages, we can avoid accessing blk_desc which is eventually an internal data structure to be hided outside block device drivers.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
lib/efi_loader/efi_disk.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
But needs updating to use media_read() or similar
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 988907ecb910..dfa6f898d586 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -45,7 +45,7 @@ struct efi_disk_obj { unsigned int part; struct efi_simple_file_system_protocol *volume; lbaint_t offset;
struct blk_desc *desc;
struct udevice *dev; /* TODO: move it to efi_object */
};
/** @@ -80,14 +80,12 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, void *buffer, enum efi_disk_direction direction) { struct efi_disk_obj *diskobj;
struct blk_desc *desc; int blksz; int blocks; unsigned long n; diskobj = container_of(this, struct efi_disk_obj, ops);
desc = (struct blk_desc *) diskobj->desc;
blksz = desc->blksz;
blksz = diskobj->media.block_size; blocks = buffer_size / blksz; lba += diskobj->offset;
@@ -99,9 +97,9 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, return EFI_BAD_BUFFER_SIZE;
if (direction == EFI_DISK_READ)
n = blk_dread(desc, lba, blocks, buffer);
n = blk_read(diskobj->dev, lba, blocks, buffer); else
n = blk_dwrite(desc, lba, blocks, buffer);
n = blk_write(diskobj->dev, lba, blocks, buffer); /* We don't do interrupts, so check for timers cooperatively */ efi_timer_check();
@@ -443,7 +441,6 @@ static efi_status_t efi_disk_add_dev( diskobj->ops = block_io_disk_template; diskobj->ifname = if_typename; diskobj->dev_index = dev_index;
diskobj->desc = desc; /* Fill in EFI IO Media info (for read/write callbacks) */ diskobj->media.removable_media = desc->removable;
@@ -647,20 +644,22 @@ bool efi_disk_is_system_part(efi_handle_t handle) { struct efi_handler *handler; struct efi_disk_obj *diskobj;
struct disk_partition info;
struct udevice *dev;
struct disk_part *part; efi_status_t ret;
int r; /* check if this is a block device */ ret = efi_search_protocol(handle, &efi_block_io_guid, &handler); if (ret != EFI_SUCCESS) return false;
/* find a partition udevice */ diskobj = container_of(handle, struct efi_disk_obj, header);
r = part_get_info(diskobj->desc, diskobj->part, &info);
if (r)
dev = diskobj->dev;
if (!dev || dev->driver->id != UCLASS_PARTITION) return false;
return !!(info.bootable & PART_EFI_SYSTEM_PARTITION);
part = dev_get_uclass_plat(dev);
return !!(part->gpt_part_info.bootable & PART_EFI_SYSTEM_PARTITION);
}
2.33.0

This member field in udevice will be used to dereference from udevice to efi_object (or efi_handle).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/dm/device.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/dm/device.h b/include/dm/device.h index 0a9718a5b81a..33b09a836f06 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -190,6 +190,10 @@ struct udevice { #if CONFIG_IS_ENABLED(DM_DMA) ulong dma_offset; #endif +#if CONFIG_IS_ENABLED(EFI_LOADER) + /* link to efi_object */ + void *efi_obj; +#endif };
/**

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
This member field in udevice will be used to dereference from udevice to efi_object (or efi_handle).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/dm/device.h | 4 ++++ 1 file changed, 4 insertions(+)
I think this should be generalised.
Can we add a simple API for attaching things to devices? Something like:
config DM_TAG bool "Support tags attached to devices"
enum dm_tag_t { DM_TAG_EFI = 0,
DM_TAG_COUNT, };
ret = dev_tag_set_ptr(dev, DM_TAG_EFI, ptr);
void *ptr = dev_tag_get_ptr(dev, DM_TAG_EFI);
ulong val = dev_tag_get_val(dev, DM_TAG_EFI);
Under the hood I think for now we could have a simple list of tags for all of DM:
struct dmtag_node { struct list_head sibling; struct udevice *dev; enum dm_tag_t tag; union { void *ptr; ulong val; }; };
This can be useful in other situations, for example I think we need to be able to send an event when a device is probed so that other devices (with tags attached) can take action. But in any case, it makes the API separate from the data structure, so aids refactoring later.
If we find that this is slow we can change the impl, but I doubt it will matter fornow.
diff --git a/include/dm/device.h b/include/dm/device.h index 0a9718a5b81a..33b09a836f06 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -190,6 +190,10 @@ struct udevice { #if CONFIG_IS_ENABLED(DM_DMA) ulong dma_offset; #endif +#if CONFIG_IS_ENABLED(EFI_LOADER)
/* link to efi_object */
void *efi_obj;
+#endif };
/**
2.33.0
Regards, Simon

Simon,
On Sun, Oct 10, 2021 at 08:14:18AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
This member field in udevice will be used to dereference from udevice to efi_object (or efi_handle).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/dm/device.h | 4 ++++ 1 file changed, 4 insertions(+)
I think this should be generalised.
Can we add a simple API for attaching things to devices? Something like:
Ok.
config DM_TAG bool "Support tags attached to devices"
enum dm_tag_t { DM_TAG_EFI = 0,
DM_TAG_COUNT,
};
ret = dev_tag_set_ptr(dev, DM_TAG_EFI, ptr);
void *ptr = dev_tag_get_ptr(dev, DM_TAG_EFI);
ulong val = dev_tag_get_val(dev, DM_TAG_EFI);
Under the hood I think for now we could have a simple list of tags for all of DM:
struct dmtag_node { struct list_head sibling; struct udevice *dev; enum dm_tag_t tag; union { void *ptr; ulong val; }; };
Just let me make sure; Do you intend that we have a *single* list of tags in the system instead of maintaining a list *per udevice*?
-Takahiro Akashi
This can be useful in other situations, for example I think we need to be able to send an event when a device is probed so that other devices (with tags attached) can take action. But in any case, it makes the API separate from the data structure, so aids refactoring later.
If we find that this is slow we can change the impl, but I doubt it will matter fornow.
diff --git a/include/dm/device.h b/include/dm/device.h index 0a9718a5b81a..33b09a836f06 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -190,6 +190,10 @@ struct udevice { #if CONFIG_IS_ENABLED(DM_DMA) ulong dma_offset; #endif +#if CONFIG_IS_ENABLED(EFI_LOADER)
/* link to efi_object */
void *efi_obj;
+#endif };
/**
2.33.0
Regards, Simon

Hi Takahiro,
On Mon, 11 Oct 2021 at 00:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Sun, Oct 10, 2021 at 08:14:18AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
This member field in udevice will be used to dereference from udevice to efi_object (or efi_handle).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/dm/device.h | 4 ++++ 1 file changed, 4 insertions(+)
I think this should be generalised.
Can we add a simple API for attaching things to devices? Something like:
Ok.
config DM_TAG bool "Support tags attached to devices"
enum dm_tag_t { DM_TAG_EFI = 0,
DM_TAG_COUNT,
};
ret = dev_tag_set_ptr(dev, DM_TAG_EFI, ptr);
void *ptr = dev_tag_get_ptr(dev, DM_TAG_EFI);
ulong val = dev_tag_get_val(dev, DM_TAG_EFI);
Under the hood I think for now we could have a simple list of tags for all of DM:
struct dmtag_node { struct list_head sibling; struct udevice *dev; enum dm_tag_t tag; union { void *ptr; ulong val; }; };
Just let me make sure; Do you intend that we have a *single* list of tags in the system instead of maintaining a list *per udevice*?
Yes I would prefer not to have a list per udevice, although the API could be adjusted to iterate through all tags for a particular udevice, if that is needed (dev_tag_first...() dev_tag_next...().
Looking at some of your other patches I think you might need to support multiple tags for EFI, if there are different things. But perhaps a list is necesary.
-Takahiro Akashi
This can be useful in other situations, for example I think we need to be able to send an event when a device is probed so that other devices (with tags attached) can take action. But in any case, it makes the API separate from the data structure, so aids refactoring later.
If we find that this is slow we can change the impl, but I doubt it will matter fornow.
[..]
Regards, Simon

On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Mon, 11 Oct 2021 at 00:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Sun, Oct 10, 2021 at 08:14:18AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
This member field in udevice will be used to dereference from udevice to efi_object (or efi_handle).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/dm/device.h | 4 ++++ 1 file changed, 4 insertions(+)
I think this should be generalised.
Can we add a simple API for attaching things to devices? Something like:
Ok.
config DM_TAG bool "Support tags attached to devices"
enum dm_tag_t { DM_TAG_EFI = 0,
DM_TAG_COUNT,
};
ret = dev_tag_set_ptr(dev, DM_TAG_EFI, ptr);
void *ptr = dev_tag_get_ptr(dev, DM_TAG_EFI);
ulong val = dev_tag_get_val(dev, DM_TAG_EFI);
Under the hood I think for now we could have a simple list of tags for all of DM:
struct dmtag_node { struct list_head sibling; struct udevice *dev; enum dm_tag_t tag; union { void *ptr; ulong val; }; };
Just let me make sure; Do you intend that we have a *single* list of tags in the system instead of maintaining a list *per udevice*?
Yes I would prefer not to have a list per udevice, although the API could be adjusted to iterate through all tags for a particular udevice, if that is needed (dev_tag_first...() dev_tag_next...().
There will never be more than one UEFI handle for one udevice. We need a single field that points to the the handle if such a handle exists. But there will be devices for which UEFI protocols don't exist and where we need no handle. In this case the value can be NULL.
Why should we complicate the picture with a list of tags?
Best regards
Heinrich
Looking at some of your other patches I think you might need to support multiple tags for EFI, if there are different things. But perhaps a list is necesary.
-Takahiro Akashi
This can be useful in other situations, for example I think we need to be able to send an event when a device is probed so that other devices (with tags attached) can take action. But in any case, it makes the API separate from the data structure, so aids refactoring later.
If we find that this is slow we can change the impl, but I doubt it will matter fornow.
[..]
Regards, Simon

Hi Heinrich,
On Mon, 11 Oct 2021 at 09:31, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Mon, 11 Oct 2021 at 00:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Sun, Oct 10, 2021 at 08:14:18AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
This member field in udevice will be used to dereference from udevice to efi_object (or efi_handle).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/dm/device.h | 4 ++++ 1 file changed, 4 insertions(+)
I think this should be generalised.
Can we add a simple API for attaching things to devices? Something like:
Ok.
config DM_TAG bool "Support tags attached to devices"
enum dm_tag_t { DM_TAG_EFI = 0,
DM_TAG_COUNT,
};
ret = dev_tag_set_ptr(dev, DM_TAG_EFI, ptr);
void *ptr = dev_tag_get_ptr(dev, DM_TAG_EFI);
ulong val = dev_tag_get_val(dev, DM_TAG_EFI);
Under the hood I think for now we could have a simple list of tags for all of DM:
struct dmtag_node { struct list_head sibling; struct udevice *dev; enum dm_tag_t tag; union { void *ptr; ulong val; }; };
Just let me make sure; Do you intend that we have a *single* list of tags in the system instead of maintaining a list *per udevice*?
Yes I would prefer not to have a list per udevice, although the API could be adjusted to iterate through all tags for a particular udevice, if that is needed (dev_tag_first...() dev_tag_next...().
There will never be more than one UEFI handle for one udevice. We need a single field that points to the the handle if such a handle exists. But there will be devices for which UEFI protocols don't exist and where we need no handle. In this case the value can be NULL.
Why should we complicate the picture with a list of tags?
Let's not talk about complexity while we are discussing UEFI :-)
There are other cases where we need to add info to a device. We cover almost all the cases with the uclass-private, plat and priv data attached to each device. But in some cases that is not enough, as with EFI. I have hit this before in a few other places but have tried to work around it rather than extending driver model and adding to the already-large struct udevice. But I think we are at the end of the road on that.
I'd also like to look at how much (for example) uclass-plat data is used for devices, in case it would be more efficient to move it to a tag model.
I should also point out you are talking about the implementation rather than the API. We can always change the impl later, so long as we have a suitable API.
Looking at some of your other patches I think you might need to support multiple tags for EFI, if there are different things. But perhaps a list is necesary.
-Takahiro Akashi
This can be useful in other situations, for example I think we need to be able to send an event when a device is probed so that other devices (with tags attached) can take action. But in any case, it makes the API separate from the data structure, so aids refactoring later.
If we find that this is slow we can change the impl, but I doubt it will matter fornow.
Regards, Simon

On Mon, Oct 11, 2021 at 10:09:19AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:31, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Mon, 11 Oct 2021 at 00:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Sun, Oct 10, 2021 at 08:14:18AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
This member field in udevice will be used to dereference from udevice to efi_object (or efi_handle).
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/dm/device.h | 4 ++++ 1 file changed, 4 insertions(+)
I think this should be generalised.
Can we add a simple API for attaching things to devices? Something like:
Ok.
config DM_TAG bool "Support tags attached to devices"
enum dm_tag_t { DM_TAG_EFI = 0,
DM_TAG_COUNT,
};
ret = dev_tag_set_ptr(dev, DM_TAG_EFI, ptr);
void *ptr = dev_tag_get_ptr(dev, DM_TAG_EFI);
ulong val = dev_tag_get_val(dev, DM_TAG_EFI);
Under the hood I think for now we could have a simple list of tags for all of DM:
struct dmtag_node { struct list_head sibling; struct udevice *dev; enum dm_tag_t tag; union { void *ptr; ulong val; }; };
Just let me make sure; Do you intend that we have a *single* list of tags in the system instead of maintaining a list *per udevice*?
Yes I would prefer not to have a list per udevice, although the API could be adjusted to iterate through all tags for a particular udevice, if that is needed (dev_tag_first...() dev_tag_next...().
There will never be more than one UEFI handle for one udevice. We need a single field that points to the the handle if such a handle exists. But there will be devices for which UEFI protocols don't exist and where we need no handle. In this case the value can be NULL.
Why should we complicate the picture with a list of tags?
Let's not talk about complexity while we are discussing UEFI :-)
There are other cases where we need to add info to a device. We cover almost all the cases with the uclass-private, plat and priv data attached to each device. But in some cases that is not enough,
While I'm not sure whether it is "not enough", I used to think of using 'priv_auto' (or per_device_auto of UCLASS) to hold a pointer to efi_object, but we might see a conflicting situation in the future where some driver may also want to use 'priv_auto' for their own purpose. That is why I added an extra member to udevice.
# The real benefit might be to keep the size of udevice unchanged?
-Takahiro Akashi
as with EFI. I have hit this before in a few other places but have tried to work around it rather than extending driver model and adding to the already-large struct udevice. But I think we are at the end of the road on that.
I'd also like to look at how much (for example) uclass-plat data is used for devices, in case it would be more efficient to move it to a tag model.
I should also point out you are talking about the implementation rather than the API. We can always change the impl later, so long as we have a suitable API.
Looking at some of your other patches I think you might need to support multiple tags for EFI, if there are different things. But perhaps a list is necesary.
-Takahiro Akashi
This can be useful in other situations, for example I think we need to be able to send an event when a device is probed so that other devices (with tags attached) can take action. But in any case, it makes the API separate from the data structure, so aids refactoring later.
If we find that this is slow we can change the impl, but I doubt it will matter fornow.
Regards, Simon

Hi Takahiro,
On Mon, 11 Oct 2021 at 20:09, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Mon, Oct 11, 2021 at 10:09:19AM -0600, Simon Glass wrote:
Hi Heinrich,
On Mon, 11 Oct 2021 at 09:31, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/11/21 16:54, Simon Glass wrote:
Hi Takahiro,
On Mon, 11 Oct 2021 at 00:43, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Sun, Oct 10, 2021 at 08:14:18AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote: > > This member field in udevice will be used to dereference from udevice > to efi_object (or efi_handle). > > Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org > --- > include/dm/device.h | 4 ++++ > 1 file changed, 4 insertions(+)
I think this should be generalised.
Can we add a simple API for attaching things to devices? Something like:
Ok.
config DM_TAG bool "Support tags attached to devices"
enum dm_tag_t { DM_TAG_EFI = 0,
DM_TAG_COUNT,
};
ret = dev_tag_set_ptr(dev, DM_TAG_EFI, ptr);
void *ptr = dev_tag_get_ptr(dev, DM_TAG_EFI);
ulong val = dev_tag_get_val(dev, DM_TAG_EFI);
Under the hood I think for now we could have a simple list of tags for all of DM:
struct dmtag_node { struct list_head sibling; struct udevice *dev; enum dm_tag_t tag; union { void *ptr; ulong val; }; };
Just let me make sure; Do you intend that we have a *single* list of tags in the system instead of maintaining a list *per udevice*?
Yes I would prefer not to have a list per udevice, although the API could be adjusted to iterate through all tags for a particular udevice, if that is needed (dev_tag_first...() dev_tag_next...().
There will never be more than one UEFI handle for one udevice. We need a single field that points to the the handle if such a handle exists. But there will be devices for which UEFI protocols don't exist and where we need no handle. In this case the value can be NULL.
Why should we complicate the picture with a list of tags?
Let's not talk about complexity while we are discussing UEFI :-)
There are other cases where we need to add info to a device. We cover almost all the cases with the uclass-private, plat and priv data attached to each device. But in some cases that is not enough,
While I'm not sure whether it is "not enough", I used to think of using 'priv_auto' (or per_device_auto of UCLASS) to hold a pointer to efi_object, but we might see a conflicting situation in the future where some driver may also want to use 'priv_auto' for their own purpose. That is why I added an extra member to udevice.
Yes indeed, we are finding a few situations where there are not enough places to put data attached to devices.
# The real benefit might be to keep the size of udevice unchanged?
Yes, although I hope we can actually reduce it. Needs some analysis though.
-Takahiro Akashi
as with EFI. I have hit this before in a few other places but have tried to work around it rather than extending driver model and adding to the already-large struct udevice. But I think we are at the end of the road on that.
I'd also like to look at how much (for example) uclass-plat data is used for devices, in case it would be more efficient to move it to a tag model.
I should also point out you are talking about the implementation rather than the API. We can always change the impl later, so long as we have a suitable API.
Looking at some of your other patches I think you might need to support multiple tags for EFI, if there are different things. But perhaps a list is necesary.
-Takahiro Akashi
This can be useful in other situations, for example I think we need to be able to send an event when a device is probed so that other devices (with tags attached) can take action. But in any case, it makes the API separate from the data structure, so aids refactoring later.
If we find that this is slow we can change the impl, but I doubt it will matter fornow.
Regards, SImon

The change in this patch will probably have been covered by other guy's patch.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_loader/efi_disk.c | 49 --------------------------------------- 1 file changed, 49 deletions(-)
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index dfa6f898d586..cd5528046251 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -552,7 +552,6 @@ efi_status_t efi_disk_register(void) struct efi_disk_obj *disk; int disks = 0; efi_status_t ret; -#ifdef CONFIG_BLK struct udevice *dev;
for (uclass_first_device_check(UCLASS_BLK, &dev); dev; @@ -580,54 +579,6 @@ efi_status_t efi_disk_register(void) &disk->header, desc, if_typename, desc->devnum, dev->name); } -#else - int i, if_type; - - /* Search for all available disk devices */ - for (if_type = 0; if_type < IF_TYPE_COUNT; if_type++) { - const struct blk_driver *cur_drvr; - const char *if_typename; - - cur_drvr = blk_driver_lookup_type(if_type); - if (!cur_drvr) - continue; - - if_typename = cur_drvr->if_typename; - log_info("Scanning disks on %s...\n", if_typename); - for (i = 0; i < 4; i++) { - struct blk_desc *desc; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - - desc = blk_get_devnum_by_type(if_type, i); - if (!desc) - continue; - if (desc->type == DEV_TYPE_UNKNOWN) - continue; - - snprintf(devname, sizeof(devname), "%s%d", - if_typename, i); - - /* Add block device for the full device */ - ret = efi_disk_add_dev(NULL, NULL, if_typename, desc, - i, NULL, 0, &disk); - if (ret == EFI_NOT_READY) { - log_notice("Disk %s not ready\n", devname); - continue; - } - if (ret) { - log_err("ERROR: failure to add disk device %s, r = %lu\n", - devname, ret & ~EFI_ERROR_MASK); - return ret; - } - disks++; - - /* Partitions show up as block devices in EFI */ - disks += efi_disk_create_partitions - (&disk->header, desc, - if_typename, i, devname); - } - } -#endif log_info("Found %d disks\n", disks);
return EFI_SUCCESS;

Add efi_disk_create() function.
Any UEFI handle created by efi_disk_create() can be treated as a efi_disk object, the udevice is either a UCLASS_BLK (a whole raw disk) or UCLASS_PARTITION (a disk partition).
So this function is expected to be called every time such an udevice is detected and activated through a device model's "probe" interface.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 + lib/efi_loader/efi_disk.c | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h index c440962fe522..751fde7fb153 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -517,6 +517,8 @@ efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition, void efi_carve_out_dt_rsv(void *fdt); /* Called by bootefi to make console interface available */ efi_status_t efi_console_register(void); +/* Called when a block devices has been probed */ +int efi_disk_create(struct udevice *dev); /* Called by bootefi to make all disk storage accessible as EFI objects */ efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index cd5528046251..3fae40e034fb 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -10,6 +10,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <dm/device-internal.h> #include <efi_loader.h> #include <fs.h> #include <log.h> @@ -484,6 +485,7 @@ error: return ret; }
+#ifndef CONFIG_BLK /** * efi_disk_create_partitions() - create handles and protocols for partitions * @@ -531,6 +533,96 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
return disks; } +#endif /* CONFIG_BLK */ + +/* + * Create a handle for a whole raw disk + * + * @dev uclass device + * @return 0 on success, -1 otherwise + */ +static int efi_disk_create_raw(struct udevice *dev) +{ + struct efi_disk_obj *disk; + struct blk_desc *desc; + const char *if_typename; + int diskid; + efi_status_t ret; + + desc = dev_get_uclass_plat(dev); + if_typename = blk_get_if_type_name(desc->if_type); + diskid = desc->devnum; + + ret = efi_disk_add_dev(NULL, NULL, if_typename, desc, + diskid, NULL, 0, &disk); + if (ret != EFI_SUCCESS) { + log_err("Adding disk %s%d failed\n", if_typename, diskid); + return -1; + } + disk->dev = dev; + dev->efi_obj = &disk->header; + + return 0; +} + +/* + * Create a handle for a disk partition + * + * @dev uclass device + * @return 0 on success, -1 otherwise + */ +static int efi_disk_create_part(struct udevice *dev) +{ + efi_handle_t parent; + struct blk_desc *desc; + const char *if_typename; + struct disk_part *part_data; + struct disk_partition *info; + unsigned int part; + int diskid; + struct efi_device_path *dp = NULL; + struct efi_disk_obj *disk; + efi_status_t ret; + + parent = dev->parent->efi_obj; + desc = dev_get_uclass_plat(dev->parent); + if_typename = blk_get_if_type_name(desc->if_type); + diskid = desc->devnum; + + part_data = dev_get_uclass_plat(dev); + part = part_data->partnum; + info = &part_data->gpt_part_info; + + /* TODO: should not use desc? */ + dp = efi_dp_from_part(desc, 0); + + ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid, + info, part, &disk); + if (ret != EFI_SUCCESS) { + log_err("Adding partition %s%d:%x failed\n", + if_typename, diskid, part); + return -1; + } + disk->dev = dev; + dev->efi_obj = &disk->header; + + return 0; +} + +int efi_disk_create(struct udevice *dev) +{ + enum uclass_id id; + + id = device_get_uclass_id(dev); + + if (id == UCLASS_BLK) + return efi_disk_create_raw(dev); + + if (id == UCLASS_PARTITION) + return efi_disk_create_part(dev); + + return -1; +}
/** * efi_disk_register() - register block devices

The change in this patch will probably have been covered by other guy's patch.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_loader/efi_disk.c | 49 --------------------------------------- 1 file changed, 49 deletions(-)
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index dfa6f898d586..cd5528046251 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -552,7 +552,6 @@ efi_status_t efi_disk_register(void) struct efi_disk_obj *disk; int disks = 0; efi_status_t ret; -#ifdef CONFIG_BLK struct udevice *dev;
for (uclass_first_device_check(UCLASS_BLK, &dev); dev; @@ -580,54 +579,6 @@ efi_status_t efi_disk_register(void) &disk->header, desc, if_typename, desc->devnum, dev->name); } -#else - int i, if_type; - - /* Search for all available disk devices */ - for (if_type = 0; if_type < IF_TYPE_COUNT; if_type++) { - const struct blk_driver *cur_drvr; - const char *if_typename; - - cur_drvr = blk_driver_lookup_type(if_type); - if (!cur_drvr) - continue; - - if_typename = cur_drvr->if_typename; - log_info("Scanning disks on %s...\n", if_typename); - for (i = 0; i < 4; i++) { - struct blk_desc *desc; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - - desc = blk_get_devnum_by_type(if_type, i); - if (!desc) - continue; - if (desc->type == DEV_TYPE_UNKNOWN) - continue; - - snprintf(devname, sizeof(devname), "%s%d", - if_typename, i); - - /* Add block device for the full device */ - ret = efi_disk_add_dev(NULL, NULL, if_typename, desc, - i, NULL, 0, &disk); - if (ret == EFI_NOT_READY) { - log_notice("Disk %s not ready\n", devname); - continue; - } - if (ret) { - log_err("ERROR: failure to add disk device %s, r = %lu\n", - devname, ret & ~EFI_ERROR_MASK); - return ret; - } - disks++; - - /* Partitions show up as block devices in EFI */ - disks += efi_disk_create_partitions - (&disk->header, desc, - if_typename, i, devname); - } - } -#endif log_info("Found %d disks\n", disks);
return EFI_SUCCESS;

On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
The change in this patch will probably have been covered by other guy's patch.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
lib/efi_loader/efi_disk.c | 49 --------------------------------------- 1 file changed, 49 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Adding this callback function, efi_disk_create() in block devices's post_probe hook will allows for automatically creating efi_disk objects per block device.
This will end up not only eliminating efi_disk_register() called in UEFI initialization, but also enabling detections of new block devices even after the initialization.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 8fbec8779e1e..ce45cf0a8768 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -9,6 +9,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <efi_loader.h> #include <log.h> #include <malloc.h> #include <part.h> @@ -827,6 +828,11 @@ int blk_create_partitions(struct udevice *parent)
static int blk_post_probe(struct udevice *dev) { + if (CONFIG_IS_ENABLED(EFI_LOADER)) { + if (efi_disk_create(dev)) + debug("*** efi_post_probe_device failed\n"); + } + if (IS_ENABLED(CONFIG_PARTITIONS) && IS_ENABLED(CONFIG_HAVE_BLOCK_DEVICE)) { struct blk_desc *desc = dev_get_uclass_plat(dev); @@ -843,6 +849,10 @@ static int blk_post_probe(struct udevice *dev)
static int blk_part_post_probe(struct udevice *dev) { + if (CONFIG_IS_ENABLED(EFI_LOADER)) { + if (efi_disk_create(dev)) + debug("*** efi_post_probe_device failed\n"); + } /* * TODO: * If we call blk_creat_partitions() here, it would allow for

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Adding this callback function, efi_disk_create() in block devices's post_probe hook will allows for automatically creating efi_disk objects per block device.
This will end up not only eliminating efi_disk_register() called in UEFI initialization, but also enabling detections of new block devices even after the initialization.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
This is where events come in. We need a way to notify things when devices go through different stages, etc.
I am thinking of:
enum dm_event_t { DMEVT_PROBE, DMEVT_POST_PROBE, ... };
struct dm_event { enum dm_event_t type; union { // add data for different event types in here } data; }
int (*dm_handler_t)(void *ctx, struct dm_event *event);
int dm_register(enum dm_event_t evtype, dm_handler_t func, void *ctx)
int dm_notify(struct udevice *dev, enum dm_event_t type, void *data);
Then the code below becomes:
dm_notify(struct udevice *dev, DMEVT_POST_PROBE, NULL);
the implementation of which will call the handler.
If you like I could create an impl of the above as a separate patch for discussion.
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 8fbec8779e1e..ce45cf0a8768 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -9,6 +9,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <efi_loader.h> #include <log.h> #include <malloc.h> #include <part.h> @@ -827,6 +828,11 @@ int blk_create_partitions(struct udevice *parent)
static int blk_post_probe(struct udevice *dev) {
if (CONFIG_IS_ENABLED(EFI_LOADER)) {
if (efi_disk_create(dev))
debug("*** efi_post_probe_device failed\n");
}
if (IS_ENABLED(CONFIG_PARTITIONS) && IS_ENABLED(CONFIG_HAVE_BLOCK_DEVICE)) { struct blk_desc *desc = dev_get_uclass_plat(dev);
@@ -843,6 +849,10 @@ static int blk_post_probe(struct udevice *dev)
static int blk_part_post_probe(struct udevice *dev) {
if (CONFIG_IS_ENABLED(EFI_LOADER)) {
if (efi_disk_create(dev))
debug("*** efi_post_probe_device failed\n");
} /* * TODO: * If we call blk_creat_partitions() here, it would allow for
-- 2.33.0
Regards, Simon

Hi Simon,
On Sun, Oct 10, 2021 at 08:14:23AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Adding this callback function, efi_disk_create() in block devices's post_probe hook will allows for automatically creating efi_disk objects per block device.
This will end up not only eliminating efi_disk_register() called in UEFI initialization, but also enabling detections of new block devices even after the initialization.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
This is where events come in. We need a way to notify things when devices go through different stages, etc.
I favor your idea of event notification to decouple subsystems from the core block layer.
I am thinking of:
enum dm_event_t { DMEVT_PROBE, DMEVT_POST_PROBE, ... };
struct dm_event { enum dm_event_t type; union { // add data for different event types in here } data; }
int (*dm_handler_t)(void *ctx, struct dm_event *event);
int dm_register(enum dm_event_t evtype, dm_handler_t func, void *ctx)
int dm_notify(struct udevice *dev, enum dm_event_t type, void *data);
Then the code below becomes:
dm_notify(struct udevice *dev, DMEVT_POST_PROBE, NULL);
the implementation of which will call the handler.
If you like I could create an impl of the above as a separate patch for discussion.
Yes, please. I'm willing to rebase my code on top of your patch.
-Takahiro Akashi
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 8fbec8779e1e..ce45cf0a8768 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -9,6 +9,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <efi_loader.h> #include <log.h> #include <malloc.h> #include <part.h> @@ -827,6 +828,11 @@ int blk_create_partitions(struct udevice *parent)
static int blk_post_probe(struct udevice *dev) {
if (CONFIG_IS_ENABLED(EFI_LOADER)) {
if (efi_disk_create(dev))
debug("*** efi_post_probe_device failed\n");
}
if (IS_ENABLED(CONFIG_PARTITIONS) && IS_ENABLED(CONFIG_HAVE_BLOCK_DEVICE)) { struct blk_desc *desc = dev_get_uclass_plat(dev);
@@ -843,6 +849,10 @@ static int blk_post_probe(struct udevice *dev)
static int blk_part_post_probe(struct udevice *dev) {
if (CONFIG_IS_ENABLED(EFI_LOADER)) {
if (efi_disk_create(dev))
debug("*** efi_post_probe_device failed\n");
} /* * TODO: * If we call blk_creat_partitions() here, it would allow for
-- 2.33.0
Regards, Simon

Hi Takahiro,
On Sun, 10 Oct 2021 at 21:15, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Hi Simon,
On Sun, Oct 10, 2021 at 08:14:23AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Adding this callback function, efi_disk_create() in block devices's post_probe hook will allows for automatically creating efi_disk objects per block device.
This will end up not only eliminating efi_disk_register() called in UEFI initialization, but also enabling detections of new block devices even after the initialization.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
This is where events come in. We need a way to notify things when devices go through different stages, etc.
I favor your idea of event notification to decouple subsystems from the core block layer.
I am thinking of:
enum dm_event_t { DMEVT_PROBE, DMEVT_POST_PROBE, ... };
struct dm_event { enum dm_event_t type; union { // add data for different event types in here } data; }
int (*dm_handler_t)(void *ctx, struct dm_event *event);
int dm_register(enum dm_event_t evtype, dm_handler_t func, void *ctx)
int dm_notify(struct udevice *dev, enum dm_event_t type, void *data);
Then the code below becomes:
dm_notify(struct udevice *dev, DMEVT_POST_PROBE, NULL);
the implementation of which will call the handler.
If you like I could create an impl of the above as a separate patch for discussion.
Yes, please. I'm willing to rebase my code on top of your patch.
OK I will give it a crack, hopefully around the end of the week.
Regards, Simon

Hi Takahiro,
On Mon, 11 Oct 2021 at 08:54, Simon Glass sjg@chromium.org wrote:
Hi Takahiro,
On Sun, 10 Oct 2021 at 21:15, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Hi Simon,
On Sun, Oct 10, 2021 at 08:14:23AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Adding this callback function, efi_disk_create() in block devices's post_probe hook will allows for automatically creating efi_disk objects per block device.
This will end up not only eliminating efi_disk_register() called in UEFI initialization, but also enabling detections of new block devices even after the initialization.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
This is where events come in. We need a way to notify things when devices go through different stages, etc.
I favor your idea of event notification to decouple subsystems from the core block layer.
I am thinking of:
enum dm_event_t { DMEVT_PROBE, DMEVT_POST_PROBE, ... };
struct dm_event { enum dm_event_t type; union { // add data for different event types in here } data; }
int (*dm_handler_t)(void *ctx, struct dm_event *event);
int dm_register(enum dm_event_t evtype, dm_handler_t func, void *ctx)
int dm_notify(struct udevice *dev, enum dm_event_t type, void *data);
Then the code below becomes:
dm_notify(struct udevice *dev, DMEVT_POST_PROBE, NULL);
the implementation of which will call the handler.
If you like I could create an impl of the above as a separate patch for discussion.
Yes, please. I'm willing to rebase my code on top of your patch.
OK I will give it a crack, hopefully around the end of the week.
Well that didn't happen as the two things ahead of it expanded.
I'll send a patch with a sketch soon, for you to look at.
Regards, Simon

Add efi_disk_create() function.
Any UEFI handle created by efi_disk_create() can be treated as a efi_disk object, the udevice is either a UCLASS_BLK (a whole raw disk) or UCLASS_PARTITION (a disk partition).
So this function is expected to be called every time such an udevice is detected and activated through a device model's "probe" interface.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 + lib/efi_loader/efi_disk.c | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h index c440962fe522..751fde7fb153 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -517,6 +517,8 @@ efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition, void efi_carve_out_dt_rsv(void *fdt); /* Called by bootefi to make console interface available */ efi_status_t efi_console_register(void); +/* Called when a block devices has been probed */ +int efi_disk_create(struct udevice *dev); /* Called by bootefi to make all disk storage accessible as EFI objects */ efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index cd5528046251..3fae40e034fb 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -10,6 +10,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <dm/device-internal.h> #include <efi_loader.h> #include <fs.h> #include <log.h> @@ -484,6 +485,7 @@ error: return ret; }
+#ifndef CONFIG_BLK /** * efi_disk_create_partitions() - create handles and protocols for partitions * @@ -531,6 +533,96 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
return disks; } +#endif /* CONFIG_BLK */ + +/* + * Create a handle for a whole raw disk + * + * @dev uclass device + * @return 0 on success, -1 otherwise + */ +static int efi_disk_create_raw(struct udevice *dev) +{ + struct efi_disk_obj *disk; + struct blk_desc *desc; + const char *if_typename; + int diskid; + efi_status_t ret; + + desc = dev_get_uclass_plat(dev); + if_typename = blk_get_if_type_name(desc->if_type); + diskid = desc->devnum; + + ret = efi_disk_add_dev(NULL, NULL, if_typename, desc, + diskid, NULL, 0, &disk); + if (ret != EFI_SUCCESS) { + log_err("Adding disk %s%d failed\n", if_typename, diskid); + return -1; + } + disk->dev = dev; + dev->efi_obj = &disk->header; + + return 0; +} + +/* + * Create a handle for a disk partition + * + * @dev uclass device + * @return 0 on success, -1 otherwise + */ +static int efi_disk_create_part(struct udevice *dev) +{ + efi_handle_t parent; + struct blk_desc *desc; + const char *if_typename; + struct disk_part *part_data; + struct disk_partition *info; + unsigned int part; + int diskid; + struct efi_device_path *dp = NULL; + struct efi_disk_obj *disk; + efi_status_t ret; + + parent = dev->parent->efi_obj; + desc = dev_get_uclass_plat(dev->parent); + if_typename = blk_get_if_type_name(desc->if_type); + diskid = desc->devnum; + + part_data = dev_get_uclass_plat(dev); + part = part_data->partnum; + info = &part_data->gpt_part_info; + + /* TODO: should not use desc? */ + dp = efi_dp_from_part(desc, 0); + + ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid, + info, part, &disk); + if (ret != EFI_SUCCESS) { + log_err("Adding partition %s%d:%x failed\n", + if_typename, diskid, part); + return -1; + } + disk->dev = dev; + dev->efi_obj = &disk->header; + + return 0; +} + +int efi_disk_create(struct udevice *dev) +{ + enum uclass_id id; + + id = device_get_uclass_id(dev); + + if (id == UCLASS_BLK) + return efi_disk_create_raw(dev); + + if (id == UCLASS_PARTITION) + return efi_disk_create_part(dev); + + return -1; +}
/** * efi_disk_register() - register block devices

On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Add efi_disk_create() function.
Any UEFI handle created by efi_disk_create() can be treated as a efi_disk object, the udevice is either a UCLASS_BLK (a whole raw disk) or UCLASS_PARTITION (a disk partition).
So this function is expected to be called every time such an udevice is detected and activated through a device model's "probe" interface.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 + lib/efi_loader/efi_disk.c | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But some nits below.
Don't worry about !CONFIG_BLK - that code should be removed.
diff --git a/include/efi_loader.h b/include/efi_loader.h index c440962fe522..751fde7fb153 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -517,6 +517,8 @@ efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition, void efi_carve_out_dt_rsv(void *fdt); /* Called by bootefi to make console interface available */ efi_status_t efi_console_register(void); +/* Called when a block devices has been probed */ +int efi_disk_create(struct udevice *dev);
Please buck the trend in this file and add a full function comment. In this case it needs to cover @dev and the return value and also explain what the function does.
/* Called by bootefi to make all disk storage accessible as EFI objects */ efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index cd5528046251..3fae40e034fb 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -10,6 +10,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <dm/device-internal.h> #include <efi_loader.h> #include <fs.h> #include <log.h> @@ -484,6 +485,7 @@ error: return ret; }
+#ifndef CONFIG_BLK /**
- efi_disk_create_partitions() - create handles and protocols for partitions
@@ -531,6 +533,96 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
return disks;
} +#endif /* CONFIG_BLK */
+/*
- Create a handle for a whole raw disk
- @dev uclass device
?? what type of device?
- @return 0 on success, -1 otherwise
- */
+static int efi_disk_create_raw(struct udevice *dev) +{
struct efi_disk_obj *disk;
struct blk_desc *desc;
const char *if_typename;
int diskid;
efi_status_t ret;
desc = dev_get_uclass_plat(dev);
if_typename = blk_get_if_type_name(desc->if_type);
diskid = desc->devnum;
ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
diskid, NULL, 0, &disk);
if (ret != EFI_SUCCESS) {
if (ret)
is much shorter and easier to read
log_err("Adding disk %s%d failed\n", if_typename, diskid);
return -1;
}
disk->dev = dev;
dev->efi_obj = &disk->header;
return 0;
+}
+/*
- Create a handle for a disk partition
- @dev uclass device
??
- @return 0 on success, -1 otherwise
- */
+static int efi_disk_create_part(struct udevice *dev) +{
efi_handle_t parent;
struct blk_desc *desc;
const char *if_typename;
struct disk_part *part_data;
struct disk_partition *info;
unsigned int part;
int diskid;
struct efi_device_path *dp = NULL;
struct efi_disk_obj *disk;
efi_status_t ret;
parent = dev->parent->efi_obj;
dev_get_parent(dev)
desc = dev_get_uclass_plat(dev->parent);
if_typename = blk_get_if_type_name(desc->if_type);
diskid = desc->devnum;
part_data = dev_get_uclass_plat(dev);
part = part_data->partnum;
info = &part_data->gpt_part_info;
/* TODO: should not use desc? */
dp = efi_dp_from_part(desc, 0);
ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
info, part, &disk);
if (ret != EFI_SUCCESS) {
log_err("Adding partition %s%d:%x failed\n",
if_typename, diskid, part);
return -1;
}
disk->dev = dev;
dev->efi_obj = &disk->header;
return 0;
+}
+int efi_disk_create(struct udevice *dev) +{
enum uclass_id id;
id = device_get_uclass_id(dev);
if (id == UCLASS_BLK)
return efi_disk_create_raw(dev);
if (id == UCLASS_PARTITION)
return efi_disk_create_part(dev);
return -1;
+}
/**
- efi_disk_register() - register block devices
-- 2.33.0
Regards, Simon

On Sun, Oct 10, 2021 at 08:14:21AM -0600, Simon Glass wrote:
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Add efi_disk_create() function.
Any UEFI handle created by efi_disk_create() can be treated as a efi_disk object, the udevice is either a UCLASS_BLK (a whole raw disk) or UCLASS_PARTITION (a disk partition).
So this function is expected to be called every time such an udevice is detected and activated through a device model's "probe" interface.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 + lib/efi_loader/efi_disk.c | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But some nits below.
Don't worry about !CONFIG_BLK - that code should be removed.
Yes. I added a tentative patch to remove !CONFIG_BLK code in efi_disk in patch#13.
diff --git a/include/efi_loader.h b/include/efi_loader.h index c440962fe522..751fde7fb153 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -517,6 +517,8 @@ efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition, void efi_carve_out_dt_rsv(void *fdt); /* Called by bootefi to make console interface available */ efi_status_t efi_console_register(void); +/* Called when a block devices has been probed */ +int efi_disk_create(struct udevice *dev);
Please buck the trend in this file and add a full function comment. In this case it needs to cover @dev and the return value and also explain what the function does.
OK.
/* Called by bootefi to make all disk storage accessible as EFI objects */ efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index cd5528046251..3fae40e034fb 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -10,6 +10,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <dm/device-internal.h> #include <efi_loader.h> #include <fs.h> #include <log.h> @@ -484,6 +485,7 @@ error: return ret; }
+#ifndef CONFIG_BLK /**
- efi_disk_create_partitions() - create handles and protocols for partitions
@@ -531,6 +533,96 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
return disks;
} +#endif /* CONFIG_BLK */
+/*
- Create a handle for a whole raw disk
- @dev uclass device
?? what type of device?
(Will fix: UCLASS_BLK)
- @return 0 on success, -1 otherwise
- */
+static int efi_disk_create_raw(struct udevice *dev) +{
struct efi_disk_obj *disk;
struct blk_desc *desc;
const char *if_typename;
int diskid;
efi_status_t ret;
desc = dev_get_uclass_plat(dev);
if_typename = blk_get_if_type_name(desc->if_type);
diskid = desc->devnum;
ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
diskid, NULL, 0, &disk);
if (ret != EFI_SUCCESS) {
if (ret)
is much shorter and easier to read
Yeah, but I don't want to assume EFI_SUCCESS is *zero*.
log_err("Adding disk %s%d failed\n", if_typename, diskid);
return -1;
}
disk->dev = dev;
dev->efi_obj = &disk->header;
return 0;
+}
+/*
- Create a handle for a disk partition
- @dev uclass device
??
(UCLASS_PARTITION)
- @return 0 on success, -1 otherwise
- */
+static int efi_disk_create_part(struct udevice *dev) +{
efi_handle_t parent;
struct blk_desc *desc;
const char *if_typename;
struct disk_part *part_data;
struct disk_partition *info;
unsigned int part;
int diskid;
struct efi_device_path *dp = NULL;
struct efi_disk_obj *disk;
efi_status_t ret;
parent = dev->parent->efi_obj;
dev_get_parent(dev)
I will replace all of "dev->parent" with dev_get_parent() if I will not forget to do that in the next version :)
Thanks, -Takahiro Akashi
desc = dev_get_uclass_plat(dev->parent);
if_typename = blk_get_if_type_name(desc->if_type);
diskid = desc->devnum;
part_data = dev_get_uclass_plat(dev);
part = part_data->partnum;
info = &part_data->gpt_part_info;
/* TODO: should not use desc? */
dp = efi_dp_from_part(desc, 0);
ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
info, part, &disk);
if (ret != EFI_SUCCESS) {
log_err("Adding partition %s%d:%x failed\n",
if_typename, diskid, part);
return -1;
}
disk->dev = dev;
dev->efi_obj = &disk->header;
return 0;
+}
+int efi_disk_create(struct udevice *dev) +{
enum uclass_id id;
id = device_get_uclass_id(dev);
if (id == UCLASS_BLK)
return efi_disk_create_raw(dev);
if (id == UCLASS_PARTITION)
return efi_disk_create_part(dev);
return -1;
+}
/**
- efi_disk_register() - register block devices
-- 2.33.0
Regards, Simon

Hi Takahiro,
On Mon, 11 Oct 2021 at 00:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 10, 2021 at 08:14:21AM -0600, Simon Glass wrote:
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Add efi_disk_create() function.
Any UEFI handle created by efi_disk_create() can be treated as a efi_disk object, the udevice is either a UCLASS_BLK (a whole raw disk) or UCLASS_PARTITION (a disk partition).
So this function is expected to be called every time such an udevice is detected and activated through a device model's "probe" interface.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 + lib/efi_loader/efi_disk.c | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But some nits below.
Don't worry about !CONFIG_BLK - that code should be removed.
Yes. I added a tentative patch to remove !CONFIG_BLK code in efi_disk in patch#13.
diff --git a/include/efi_loader.h b/include/efi_loader.h index c440962fe522..751fde7fb153 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -517,6 +517,8 @@ efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition, void efi_carve_out_dt_rsv(void *fdt); /* Called by bootefi to make console interface available */ efi_status_t efi_console_register(void); +/* Called when a block devices has been probed */ +int efi_disk_create(struct udevice *dev);
Please buck the trend in this file and add a full function comment. In this case it needs to cover @dev and the return value and also explain what the function does.
OK.
/* Called by bootefi to make all disk storage accessible as EFI objects */ efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index cd5528046251..3fae40e034fb 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -10,6 +10,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <dm/device-internal.h> #include <efi_loader.h> #include <fs.h> #include <log.h> @@ -484,6 +485,7 @@ error: return ret; }
+#ifndef CONFIG_BLK /**
- efi_disk_create_partitions() - create handles and protocols for partitions
@@ -531,6 +533,96 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
return disks;
} +#endif /* CONFIG_BLK */
+/*
- Create a handle for a whole raw disk
- @dev uclass device
?? what type of device?
(Will fix: UCLASS_BLK)
- @return 0 on success, -1 otherwise
- */
+static int efi_disk_create_raw(struct udevice *dev) +{
struct efi_disk_obj *disk;
struct blk_desc *desc;
const char *if_typename;
int diskid;
efi_status_t ret;
desc = dev_get_uclass_plat(dev);
if_typename = blk_get_if_type_name(desc->if_type);
diskid = desc->devnum;
ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
diskid, NULL, 0, &disk);
if (ret != EFI_SUCCESS) {
if (ret)
is much shorter and easier to read
Yeah, but I don't want to assume EFI_SUCCESS is *zero*.
It is defined as 0 in 'Appendix D - Status Code' and cannot change, as I understand it. This is one of the things I don't like about the EFI code in U-Boot. Presumably the people who wrote the spec defined it as 0 to make use of C constructs.
[..]
Regards, Simon

Simon,
On Mon, Oct 11, 2021 at 08:54:06AM -0600, Simon Glass wrote:
Hi Takahiro,
On Mon, 11 Oct 2021 at 00:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 10, 2021 at 08:14:21AM -0600, Simon Glass wrote:
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Add efi_disk_create() function.
Any UEFI handle created by efi_disk_create() can be treated as a efi_disk object, the udevice is either a UCLASS_BLK (a whole raw disk) or UCLASS_PARTITION (a disk partition).
So this function is expected to be called every time such an udevice is detected and activated through a device model's "probe" interface.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 + lib/efi_loader/efi_disk.c | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But some nits below.
Don't worry about !CONFIG_BLK - that code should be removed.
Yes. I added a tentative patch to remove !CONFIG_BLK code in efi_disk in patch#13.
diff --git a/include/efi_loader.h b/include/efi_loader.h index c440962fe522..751fde7fb153 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -517,6 +517,8 @@ efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition, void efi_carve_out_dt_rsv(void *fdt); /* Called by bootefi to make console interface available */ efi_status_t efi_console_register(void); +/* Called when a block devices has been probed */ +int efi_disk_create(struct udevice *dev);
Please buck the trend in this file and add a full function comment. In this case it needs to cover @dev and the return value and also explain what the function does.
OK.
/* Called by bootefi to make all disk storage accessible as EFI objects */ efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index cd5528046251..3fae40e034fb 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -10,6 +10,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <dm/device-internal.h> #include <efi_loader.h> #include <fs.h> #include <log.h> @@ -484,6 +485,7 @@ error: return ret; }
+#ifndef CONFIG_BLK /**
- efi_disk_create_partitions() - create handles and protocols for partitions
@@ -531,6 +533,96 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
return disks;
} +#endif /* CONFIG_BLK */
+/*
- Create a handle for a whole raw disk
- @dev uclass device
?? what type of device?
(Will fix: UCLASS_BLK)
- @return 0 on success, -1 otherwise
- */
+static int efi_disk_create_raw(struct udevice *dev) +{
struct efi_disk_obj *disk;
struct blk_desc *desc;
const char *if_typename;
int diskid;
efi_status_t ret;
desc = dev_get_uclass_plat(dev);
if_typename = blk_get_if_type_name(desc->if_type);
diskid = desc->devnum;
ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
diskid, NULL, 0, &disk);
if (ret != EFI_SUCCESS) {
if (ret)
is much shorter and easier to read
Yeah, but I don't want to assume EFI_SUCCESS is *zero*.
It is defined as 0 in 'Appendix D - Status Code' and cannot change, as I understand it. This is one of the things I don't like about the EFI code in U-Boot. Presumably the people who wrote the spec defined it as 0 to make use of C constructs.
Yeah, I confirmed that, but still want to keep the code as "ret != EFI_SUCCESS" is used everywhere in UEFI code :)
-Takahiro Akashi
[..]
Regards, Simon

Hi Akashi,
On Mon, 11 Oct 2021 at 19:09, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Simon,
On Mon, Oct 11, 2021 at 08:54:06AM -0600, Simon Glass wrote:
Hi Takahiro,
On Mon, 11 Oct 2021 at 00:52, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
On Sun, Oct 10, 2021 at 08:14:21AM -0600, Simon Glass wrote:
On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Add efi_disk_create() function.
Any UEFI handle created by efi_disk_create() can be treated as a efi_disk object, the udevice is either a UCLASS_BLK (a whole raw disk) or UCLASS_PARTITION (a disk partition).
So this function is expected to be called every time such an udevice is detected and activated through a device model's "probe" interface.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 + lib/efi_loader/efi_disk.c | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
But some nits below.
Don't worry about !CONFIG_BLK - that code should be removed.
Yes. I added a tentative patch to remove !CONFIG_BLK code in efi_disk in patch#13.
diff --git a/include/efi_loader.h b/include/efi_loader.h index c440962fe522..751fde7fb153 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -517,6 +517,8 @@ efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition, void efi_carve_out_dt_rsv(void *fdt); /* Called by bootefi to make console interface available */ efi_status_t efi_console_register(void); +/* Called when a block devices has been probed */ +int efi_disk_create(struct udevice *dev);
Please buck the trend in this file and add a full function comment. In this case it needs to cover @dev and the return value and also explain what the function does.
OK.
/* Called by bootefi to make all disk storage accessible as EFI objects */ efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index cd5528046251..3fae40e034fb 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -10,6 +10,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <dm/device-internal.h> #include <efi_loader.h> #include <fs.h> #include <log.h> @@ -484,6 +485,7 @@ error: return ret; }
+#ifndef CONFIG_BLK /**
- efi_disk_create_partitions() - create handles and protocols for partitions
@@ -531,6 +533,96 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
return disks;
} +#endif /* CONFIG_BLK */
+/*
- Create a handle for a whole raw disk
- @dev uclass device
?? what type of device?
(Will fix: UCLASS_BLK)
- @return 0 on success, -1 otherwise
- */
+static int efi_disk_create_raw(struct udevice *dev) +{
struct efi_disk_obj *disk;
struct blk_desc *desc;
const char *if_typename;
int diskid;
efi_status_t ret;
desc = dev_get_uclass_plat(dev);
if_typename = blk_get_if_type_name(desc->if_type);
diskid = desc->devnum;
ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
diskid, NULL, 0, &disk);
if (ret != EFI_SUCCESS) {
if (ret)
is much shorter and easier to read
Yeah, but I don't want to assume EFI_SUCCESS is *zero*.
It is defined as 0 in 'Appendix D - Status Code' and cannot change, as I understand it. This is one of the things I don't like about the EFI code in U-Boot. Presumably the people who wrote the spec defined it as 0 to make use of C constructs.
Yeah, I confirmed that, but still want to keep the code as "ret != EFI_SUCCESS" is used everywhere in UEFI code :)
OK that can be a clean-up for another day, along with the overly long types and naming in general.
At least we managed to avoid all the capital letters and camel case...
Regards, Simon

Adding this callback function, efi_disk_create() in block devices's post_probe hook will allows for automatically creating efi_disk objects per block device.
This will end up not only eliminating efi_disk_register() called in UEFI initialization, but also enabling detections of new block devices even after the initialization.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 8fbec8779e1e..ce45cf0a8768 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -9,6 +9,7 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <efi_loader.h> #include <log.h> #include <malloc.h> #include <part.h> @@ -827,6 +828,11 @@ int blk_create_partitions(struct udevice *parent)
static int blk_post_probe(struct udevice *dev) { + if (CONFIG_IS_ENABLED(EFI_LOADER)) { + if (efi_disk_create(dev)) + debug("*** efi_post_probe_device failed\n"); + } + if (IS_ENABLED(CONFIG_PARTITIONS) && IS_ENABLED(CONFIG_HAVE_BLOCK_DEVICE)) { struct blk_desc *desc = dev_get_uclass_plat(dev); @@ -843,6 +849,10 @@ static int blk_post_probe(struct udevice *dev)
static int blk_part_post_probe(struct udevice *dev) { + if (CONFIG_IS_ENABLED(EFI_LOADER)) { + if (efi_disk_create(dev)) + debug("*** efi_post_probe_device failed\n"); + } /* * TODO: * If we call blk_creat_partitions() here, it would allow for

efi_disk_register() will be no longer needed now that all efi_disks are set to be created with device model thanks to efi_disk-dm integration.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 - lib/efi_loader/efi_disk.c | 102 ------------------------------------- lib/efi_loader/efi_setup.c | 5 -- 3 files changed, 109 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 751fde7fb153..cfbe1fe659ef 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -519,8 +519,6 @@ void efi_carve_out_dt_rsv(void *fdt); efi_status_t efi_console_register(void); /* Called when a block devices has been probed */ int efi_disk_create(struct udevice *dev); -/* Called by bootefi to make all disk storage accessible as EFI objects */ -efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ efi_status_t efi_rng_register(void); /* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 3fae40e034fb..74ef923d1d67 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -485,56 +485,6 @@ error: return ret; }
-#ifndef CONFIG_BLK -/** - * efi_disk_create_partitions() - create handles and protocols for partitions - * - * Create handles and protocols for the partitions of a block device. - * - * @parent: handle of the parent disk - * @desc: block device - * @if_typename: interface type - * @diskid: device number - * @pdevname: device name - * Return: number of partitions created - */ -int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, - const char *if_typename, int diskid, - const char *pdevname) -{ - int disks = 0; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - int part; - struct efi_device_path *dp = NULL; - efi_status_t ret; - struct efi_handler *handler; - - /* Get the device path of the parent */ - ret = efi_search_protocol(parent, &efi_guid_device_path, &handler); - if (ret == EFI_SUCCESS) - dp = handler->protocol_interface; - - /* Add devices for each partition */ - for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { - struct disk_partition info; - - if (part_get_info(desc, part, &info)) - continue; - snprintf(devname, sizeof(devname), "%s:%x", pdevname, - part); - ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid, - &info, part, NULL); - if (ret != EFI_SUCCESS) { - log_err("Adding partition %s failed\n", pdevname); - continue; - } - disks++; - } - - return disks; -} -#endif /* CONFIG_BLK */ - /* * Create a handle for a whole raw disk * @@ -624,58 +574,6 @@ int efi_disk_create(struct udevice *dev) return -1; }
-/** - * efi_disk_register() - register block devices - * - * U-Boot doesn't have a list of all online disk devices. So when running our - * EFI payload, we scan through all of the potentially available ones and - * store them in our object pool. - * - * This function is called in efi_init_obj_list(). - * - * TODO(sjg@chromium.org): Actually with CONFIG_BLK, U-Boot does have this. - * Consider converting the code to look up devices as needed. The EFI device - * could be a child of the UCLASS_BLK block device, perhaps. - * - * Return: status code - */ -efi_status_t efi_disk_register(void) -{ - struct efi_disk_obj *disk; - int disks = 0; - efi_status_t ret; - struct udevice *dev; - - for (uclass_first_device_check(UCLASS_BLK, &dev); dev; - uclass_next_device_check(&dev)) { - struct blk_desc *desc = dev_get_uclass_plat(dev); - const char *if_typename = blk_get_if_type_name(desc->if_type); - - /* Add block device for the full device */ - log_info("Scanning disk %s...\n", dev->name); - ret = efi_disk_add_dev(NULL, NULL, if_typename, - desc, desc->devnum, NULL, 0, &disk); - if (ret == EFI_NOT_READY) { - log_notice("Disk %s not ready\n", dev->name); - continue; - } - if (ret) { - log_err("ERROR: failure to add disk device %s, r = %lu\n", - dev->name, ret & ~EFI_ERROR_MASK); - return ret; - } - disks++; - - /* Partitions show up as block devices in EFI */ - disks += efi_disk_create_partitions( - &disk->header, desc, if_typename, - desc->devnum, dev->name); - } - log_info("Found %d disks\n", disks); - - return EFI_SUCCESS; -} - /** * efi_disk_is_system_part() - check if handle refers to an EFI system partition * diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index a2338d74afac..618526eaa7c6 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -230,11 +230,6 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out;
-#ifdef CONFIG_PARTITIONS - ret = efi_disk_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif if (IS_ENABLED(CONFIG_EFI_RNG_PROTOCOL)) { ret = efi_rng_register(); if (ret != EFI_SUCCESS)

This function is a counterpart of efi_add_handle() and will be used in order to remove an efi_disk object in a later patch.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 ++ lib/efi_loader/efi_boottime.c | 8 ++++++++ 2 files changed, 10 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h index cfbe1fe659ef..50f4119dcdfb 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -579,6 +579,8 @@ void efi_save_gd(void); void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); /* Add a new object to the object list. */ void efi_add_handle(efi_handle_t obj); +/* Remove a object from the object list. */ +void efi_remove_handle(efi_handle_t obj); /* Create handle */ efi_status_t efi_create_handle(efi_handle_t *handle); /* Delete handle */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index f0283b539e46..b2503b74233b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -503,6 +503,14 @@ void efi_add_handle(efi_handle_t handle) list_add_tail(&handle->link, &efi_obj_list); }
+void efi_remove_handle(efi_handle_t handle) +{ + if (!handle) + return; + + list_del(&handle->link); +} + /** * efi_create_handle() - create handle * @handle: new handle

efi_disk_register() will be no longer needed now that all efi_disks are set to be created with device model thanks to efi_disk-dm integration.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 - lib/efi_loader/efi_disk.c | 102 ------------------------------------- lib/efi_loader/efi_setup.c | 5 -- 3 files changed, 109 deletions(-)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 751fde7fb153..cfbe1fe659ef 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -519,8 +519,6 @@ void efi_carve_out_dt_rsv(void *fdt); efi_status_t efi_console_register(void); /* Called when a block devices has been probed */ int efi_disk_create(struct udevice *dev); -/* Called by bootefi to make all disk storage accessible as EFI objects */ -efi_status_t efi_disk_register(void); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ efi_status_t efi_rng_register(void); /* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 3fae40e034fb..74ef923d1d67 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -485,56 +485,6 @@ error: return ret; }
-#ifndef CONFIG_BLK -/** - * efi_disk_create_partitions() - create handles and protocols for partitions - * - * Create handles and protocols for the partitions of a block device. - * - * @parent: handle of the parent disk - * @desc: block device - * @if_typename: interface type - * @diskid: device number - * @pdevname: device name - * Return: number of partitions created - */ -int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, - const char *if_typename, int diskid, - const char *pdevname) -{ - int disks = 0; - char devname[32] = { 0 }; /* dp->str is u16[32] long */ - int part; - struct efi_device_path *dp = NULL; - efi_status_t ret; - struct efi_handler *handler; - - /* Get the device path of the parent */ - ret = efi_search_protocol(parent, &efi_guid_device_path, &handler); - if (ret == EFI_SUCCESS) - dp = handler->protocol_interface; - - /* Add devices for each partition */ - for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { - struct disk_partition info; - - if (part_get_info(desc, part, &info)) - continue; - snprintf(devname, sizeof(devname), "%s:%x", pdevname, - part); - ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid, - &info, part, NULL); - if (ret != EFI_SUCCESS) { - log_err("Adding partition %s failed\n", pdevname); - continue; - } - disks++; - } - - return disks; -} -#endif /* CONFIG_BLK */ - /* * Create a handle for a whole raw disk * @@ -624,58 +574,6 @@ int efi_disk_create(struct udevice *dev) return -1; }
-/** - * efi_disk_register() - register block devices - * - * U-Boot doesn't have a list of all online disk devices. So when running our - * EFI payload, we scan through all of the potentially available ones and - * store them in our object pool. - * - * This function is called in efi_init_obj_list(). - * - * TODO(sjg@chromium.org): Actually with CONFIG_BLK, U-Boot does have this. - * Consider converting the code to look up devices as needed. The EFI device - * could be a child of the UCLASS_BLK block device, perhaps. - * - * Return: status code - */ -efi_status_t efi_disk_register(void) -{ - struct efi_disk_obj *disk; - int disks = 0; - efi_status_t ret; - struct udevice *dev; - - for (uclass_first_device_check(UCLASS_BLK, &dev); dev; - uclass_next_device_check(&dev)) { - struct blk_desc *desc = dev_get_uclass_plat(dev); - const char *if_typename = blk_get_if_type_name(desc->if_type); - - /* Add block device for the full device */ - log_info("Scanning disk %s...\n", dev->name); - ret = efi_disk_add_dev(NULL, NULL, if_typename, - desc, desc->devnum, NULL, 0, &disk); - if (ret == EFI_NOT_READY) { - log_notice("Disk %s not ready\n", dev->name); - continue; - } - if (ret) { - log_err("ERROR: failure to add disk device %s, r = %lu\n", - dev->name, ret & ~EFI_ERROR_MASK); - return ret; - } - disks++; - - /* Partitions show up as block devices in EFI */ - disks += efi_disk_create_partitions( - &disk->header, desc, if_typename, - desc->devnum, dev->name); - } - log_info("Found %d disks\n", disks); - - return EFI_SUCCESS; -} - /** * efi_disk_is_system_part() - check if handle refers to an EFI system partition * diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index a2338d74afac..618526eaa7c6 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -230,11 +230,6 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out;
-#ifdef CONFIG_PARTITIONS - ret = efi_disk_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif if (IS_ENABLED(CONFIG_EFI_RNG_PROTOCOL)) { ret = efi_rng_register(); if (ret != EFI_SUCCESS)

On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
efi_disk_register() will be no longer needed now that all efi_disks are set to be created with device model thanks to efi_disk-dm integration.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 - lib/efi_loader/efi_disk.c | 102 ------------------------------------- lib/efi_loader/efi_setup.c | 5 -- 3 files changed, 109 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

This function is a counterpart of efi_add_handle() and will be used in order to remove an efi_disk object in a later patch.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 ++ lib/efi_loader/efi_boottime.c | 8 ++++++++ 2 files changed, 10 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h index cfbe1fe659ef..50f4119dcdfb 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -579,6 +579,8 @@ void efi_save_gd(void); void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); /* Add a new object to the object list. */ void efi_add_handle(efi_handle_t obj); +/* Remove a object from the object list. */ +void efi_remove_handle(efi_handle_t obj); /* Create handle */ efi_status_t efi_create_handle(efi_handle_t *handle); /* Delete handle */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index f0283b539e46..b2503b74233b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -503,6 +503,14 @@ void efi_add_handle(efi_handle_t handle) list_add_tail(&handle->link, &efi_obj_list); }
+void efi_remove_handle(efi_handle_t handle) +{ + if (!handle) + return; + + list_del(&handle->link); +} + /** * efi_create_handle() - create handle * @handle: new handle

On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
This function is a counterpart of efi_add_handle() and will be used in order to remove an efi_disk object in a later patch.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 ++ lib/efi_loader/efi_boottime.c | 8 ++++++++ 2 files changed, 10 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

This function is expected to be called, in particular from dm's pre_remove hook, when associated block devices no longer exist.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 ++ lib/efi_loader/efi_disk.c | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 50f4119dcdfb..7079549bea70 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -519,6 +519,8 @@ void efi_carve_out_dt_rsv(void *fdt); efi_status_t efi_console_register(void); /* Called when a block devices has been probed */ int efi_disk_create(struct udevice *dev); +/* Called when a block devices is to be removed */ +int efi_disk_delete(struct udevice *dev); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ efi_status_t efi_rng_register(void); /* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 74ef923d1d67..dfd06dd31e4a 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -574,6 +574,60 @@ int efi_disk_create(struct udevice *dev) return -1; }
+static int efi_disk_delete_raw(struct udevice *dev) +{ + efi_handle_t handle = dev->efi_obj; + struct blk_desc *desc; + struct efi_disk_obj *diskobj; + + desc = dev_get_uclass_plat(dev); + if (desc->if_type != IF_TYPE_EFI) { + diskobj = container_of(handle, struct efi_disk_obj, header); + efi_free_pool(diskobj->dp); + } + + /* + * TODO: Can we use efi_delete_handle() here? + */ + efi_remove_all_protocols(handle); + + efi_remove_handle(handle); + free(diskobj); + + return 0; +} + +static int efi_disk_delete_part(struct udevice *dev) +{ + efi_handle_t handle = dev->efi_obj; + struct efi_disk_obj *diskobj; + + diskobj = container_of(handle, struct efi_disk_obj, header); + + efi_free_pool(diskobj->dp); + + efi_remove_all_protocols(handle); + + efi_remove_handle(handle); + free(diskobj); + + return 0; +} + +int efi_disk_delete(struct udevice *dev) +{ + enum uclass_id id; + + id = device_get_uclass_id(dev); + + if (id == UCLASS_BLK) + return efi_disk_delete_raw(dev); + else if (id == UCLASS_PARTITION) + return efi_disk_delete_part(dev); + else + return -1; +} + /** * efi_disk_is_system_part() - check if handle refers to an EFI system partition *

Adding the callback function, efi_disk_delete(), in block devices's pre_remove hook will allows for automatically deleting efi_disk objects per block device.
This will eliminate any improper efi_disk objects which hold a link to non-existing udevice structures when associated block devices are physically un-plugged or udevices are once removed (and re-created) by executing commands like "scsi rescan."
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index ce45cf0a8768..b8ad267c6c61 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -847,6 +847,16 @@ static int blk_post_probe(struct udevice *dev) return 0; }
+static int blk_pre_remove(struct udevice *dev) +{ + if (CONFIG_IS_ENABLED(EFI_LOADER)) { + if (efi_disk_delete(dev)) + debug("*** efi_pre_remove_device failed\n"); + } + + return 0; +} + static int blk_part_post_probe(struct udevice *dev) { if (CONFIG_IS_ENABLED(EFI_LOADER)) { @@ -861,10 +871,21 @@ static int blk_part_post_probe(struct udevice *dev) return 0; }
+static int blk_part_pre_remove(struct udevice *dev) +{ + if (CONFIG_IS_ENABLED(EFI_LOADER)) { + if (efi_disk_delete(dev)) + debug("*** efi_pre_remove_device failed\n"); + } + + return 0; +} + UCLASS_DRIVER(blk) = { .id = UCLASS_BLK, .name = "blk", .post_probe = blk_post_probe, + .pre_remove = blk_pre_remove, .per_device_plat_auto = sizeof(struct blk_desc), };
@@ -937,6 +958,7 @@ U_BOOT_DRIVER(blk_partition) = { UCLASS_DRIVER(partition) = { .id = UCLASS_PARTITION, .post_probe = blk_part_post_probe, + .pre_remove = blk_part_pre_remove, .per_device_plat_auto = sizeof(struct disk_part), .name = "partition", };

This function is expected to be called, in particular from dm's pre_remove hook, when associated block devices no longer exist.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- include/efi_loader.h | 2 ++ lib/efi_loader/efi_disk.c | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h index 50f4119dcdfb..7079549bea70 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -519,6 +519,8 @@ void efi_carve_out_dt_rsv(void *fdt); efi_status_t efi_console_register(void); /* Called when a block devices has been probed */ int efi_disk_create(struct udevice *dev); +/* Called when a block devices is to be removed */ +int efi_disk_delete(struct udevice *dev); /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ efi_status_t efi_rng_register(void); /* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 74ef923d1d67..dfd06dd31e4a 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -574,6 +574,60 @@ int efi_disk_create(struct udevice *dev) return -1; }
+static int efi_disk_delete_raw(struct udevice *dev) +{ + efi_handle_t handle = dev->efi_obj; + struct blk_desc *desc; + struct efi_disk_obj *diskobj; + + desc = dev_get_uclass_plat(dev); + if (desc->if_type != IF_TYPE_EFI) { + diskobj = container_of(handle, struct efi_disk_obj, header); + efi_free_pool(diskobj->dp); + } + + /* + * TODO: Can we use efi_delete_handle() here? + */ + efi_remove_all_protocols(handle); + + efi_remove_handle(handle); + free(diskobj); + + return 0; +} + +static int efi_disk_delete_part(struct udevice *dev) +{ + efi_handle_t handle = dev->efi_obj; + struct efi_disk_obj *diskobj; + + diskobj = container_of(handle, struct efi_disk_obj, header); + + efi_free_pool(diskobj->dp); + + efi_remove_all_protocols(handle); + + efi_remove_handle(handle); + free(diskobj); + + return 0; +} + +int efi_disk_delete(struct udevice *dev) +{ + enum uclass_id id; + + id = device_get_uclass_id(dev); + + if (id == UCLASS_BLK) + return efi_disk_delete_raw(dev); + else if (id == UCLASS_PARTITION) + return efi_disk_delete_part(dev); + else + return -1; +} + /** * efi_disk_is_system_part() - check if handle refers to an EFI system partition *

On Thu, 30 Sept 2021 at 23:04, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
This function is expected to be called, in particular from dm's pre_remove hook, when associated block devices no longer exist.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
include/efi_loader.h | 2 ++ lib/efi_loader/efi_disk.c | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
Please add full function comments.

Adding the callback function, efi_disk_delete(), in block devices's pre_remove hook will allows for automatically deleting efi_disk objects per block device.
This will eliminate any improper efi_disk objects which hold a link to non-existing udevice structures when associated block devices are physically un-plugged or udevices are once removed (and re-created) by executing commands like "scsi rescan."
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- drivers/block/blk-uclass.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index ce45cf0a8768..b8ad267c6c61 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -847,6 +847,16 @@ static int blk_post_probe(struct udevice *dev) return 0; }
+static int blk_pre_remove(struct udevice *dev) +{ + if (CONFIG_IS_ENABLED(EFI_LOADER)) { + if (efi_disk_delete(dev)) + debug("*** efi_pre_remove_device failed\n"); + } + + return 0; +} + static int blk_part_post_probe(struct udevice *dev) { if (CONFIG_IS_ENABLED(EFI_LOADER)) { @@ -861,10 +871,21 @@ static int blk_part_post_probe(struct udevice *dev) return 0; }
+static int blk_part_pre_remove(struct udevice *dev) +{ + if (CONFIG_IS_ENABLED(EFI_LOADER)) { + if (efi_disk_delete(dev)) + debug("*** efi_pre_remove_device failed\n"); + } + + return 0; +} + UCLASS_DRIVER(blk) = { .id = UCLASS_BLK, .name = "blk", .post_probe = blk_post_probe, + .pre_remove = blk_pre_remove, .per_device_plat_auto = sizeof(struct blk_desc), };
@@ -937,6 +958,7 @@ U_BOOT_DRIVER(blk_partition) = { UCLASS_DRIVER(partition) = { .id = UCLASS_PARTITION, .post_probe = blk_part_post_probe, + .pre_remove = blk_part_pre_remove, .per_device_plat_auto = sizeof(struct disk_part), .name = "partition", };

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:05, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Adding the callback function, efi_disk_delete(), in block devices's pre_remove hook will allows for automatically deleting efi_disk objects per block device.
This will eliminate any improper efi_disk objects which hold a link to non-existing udevice structures when associated block devices are physically un-plugged or udevices are once removed (and re-created) by executing commands like "scsi rescan."
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
drivers/block/blk-uclass.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
Should use event mechanism as mentioned in previous patch.
Regards, Simon

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_driver/efi_block_device.c | 6 ++++++ lib/efi_loader/efi_device_path.c | 29 +++++++++++++++++++++++++++++ lib/efi_loader/efi_disk.c | 12 +++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 0937e3595a43..b6afa939e1d1 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -173,6 +173,12 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) plat->handle = handle; plat->io = interface;
+ /* + * FIXME: necessary because we won't do almost nothing in + * efi_disk_create() when called from device_probe(). + */ + bdev->efi_obj = handle; + ret = device_probe(bdev); if (ret) return ret; diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index cbdb466da41c..36c77bce9a05 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -628,6 +628,35 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp->vendor_data[1]; } #endif +#ifdef CONFIG_EFI_LOADER + /* + * FIXME: conflicting with CONFIG_SANDBOX + * This case is necessary to support efi_disk's created by + * efi_driver (and efi_driver_binding_protocol). + * TODO: + * The best way to work around here is to create efi_root as + * udevice and put all efi_driver objects under it. + */ + case UCLASS_ROOT: { + struct efi_device_path_vendor *dp; + struct blk_desc *desc = dev_get_uclass_plat(dev); + /* FIXME: guid_vendor used in selftest_block_device */ + static efi_guid_t guid_vendor = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8); + + + dp_fill(buf, dev->parent); + dp = buf; + ++dp; + dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; + dp->dp.length = sizeof(*dp) + 1; + memcpy(&dp->guid, &guid_vendor, sizeof(efi_guid_t)); + dp->vendor_data[0] = desc->devnum; + return &dp->vendor_data[1]; + } +#endif #ifdef CONFIG_VIRTIO_BLK case UCLASS_VIRTIO: { struct efi_device_path_vendor *dp; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index dfd06dd31e4a..e7cf1567929b 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -562,11 +562,21 @@ static int efi_disk_create_part(struct udevice *dev) int efi_disk_create(struct udevice *dev) { enum uclass_id id; + struct blk_desc *desc;
id = device_get_uclass_id(dev);
- if (id == UCLASS_BLK) + if (id == UCLASS_BLK) { + /* + * avoid creating duplicated objects now that efi_driver + * has already created an efi_disk at this moment. + */ + desc = dev_get_uclass_plat(dev); + if (desc->if_type == IF_TYPE_EFI) + return 0; + return efi_disk_create_raw(dev); + }
if (id == UCLASS_PARTITION) return efi_disk_create_part(dev);

Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_driver/efi_block_device.c | 6 ++++++ lib/efi_loader/efi_device_path.c | 29 +++++++++++++++++++++++++++++ lib/efi_loader/efi_disk.c | 12 +++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 0937e3595a43..b6afa939e1d1 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -173,6 +173,12 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) plat->handle = handle; plat->io = interface;
+ /* + * FIXME: necessary because we won't do almost nothing in + * efi_disk_create() when called from device_probe(). + */ + bdev->efi_obj = handle; + ret = device_probe(bdev); if (ret) return ret; diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index cbdb466da41c..36c77bce9a05 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -628,6 +628,35 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp->vendor_data[1]; } #endif +#ifdef CONFIG_EFI_LOADER + /* + * FIXME: conflicting with CONFIG_SANDBOX + * This case is necessary to support efi_disk's created by + * efi_driver (and efi_driver_binding_protocol). + * TODO: + * The best way to work around here is to create efi_root as + * udevice and put all efi_driver objects under it. + */ + case UCLASS_ROOT: { + struct efi_device_path_vendor *dp; + struct blk_desc *desc = dev_get_uclass_plat(dev); + /* FIXME: guid_vendor used in selftest_block_device */ + static efi_guid_t guid_vendor = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8); + + + dp_fill(buf, dev->parent); + dp = buf; + ++dp; + dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; + dp->dp.length = sizeof(*dp) + 1; + memcpy(&dp->guid, &guid_vendor, sizeof(efi_guid_t)); + dp->vendor_data[0] = desc->devnum; + return &dp->vendor_data[1]; + } +#endif #ifdef CONFIG_VIRTIO_BLK case UCLASS_VIRTIO: { struct efi_device_path_vendor *dp; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index dfd06dd31e4a..e7cf1567929b 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -562,11 +562,21 @@ static int efi_disk_create_part(struct udevice *dev) int efi_disk_create(struct udevice *dev) { enum uclass_id id; + struct blk_desc *desc;
id = device_get_uclass_id(dev);
- if (id == UCLASS_BLK) + if (id == UCLASS_BLK) { + /* + * avoid creating duplicated objects now that efi_driver + * has already created an efi_disk at this moment. + */ + desc = dev_get_uclass_plat(dev); + if (desc->if_type == IF_TYPE_EFI) + return 0; + return efi_disk_create_raw(dev); + }
if (id == UCLASS_PARTITION) return efi_disk_create_part(dev);

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:05, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Can you please add a commit message as I am not sure what this patch is doing.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
lib/efi_driver/efi_block_device.c | 6 ++++++ lib/efi_loader/efi_device_path.c | 29 +++++++++++++++++++++++++++++ lib/efi_loader/efi_disk.c | 12 +++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 0937e3595a43..b6afa939e1d1 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -173,6 +173,12 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) plat->handle = handle; plat->io = interface;
/*
* FIXME: necessary because we won't do almost nothing in
* efi_disk_create() when called from device_probe().
*/
bdev->efi_obj = handle;
ret = device_probe(bdev); if (ret) return ret;
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index cbdb466da41c..36c77bce9a05 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -628,6 +628,35 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp->vendor_data[1]; } #endif +#ifdef CONFIG_EFI_LOADER
/*
* FIXME: conflicting with CONFIG_SANDBOX
In what way? If it is just a test we should be able to update the test to avoid the conflict.
* This case is necessary to support efi_disk's created by
* efi_driver (and efi_driver_binding_protocol).
* TODO:
* The best way to work around here is to create efi_root as
* udevice and put all efi_driver objects under it.
*/
case UCLASS_ROOT: {
struct efi_device_path_vendor *dp;
struct blk_desc *desc = dev_get_uclass_plat(dev);
/* FIXME: guid_vendor used in selftest_block_device */
static efi_guid_t guid_vendor =
EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8);
dp_fill(buf, dev->parent);
dp = buf;
++dp;
dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
dp->dp.length = sizeof(*dp) + 1;
memcpy(&dp->guid, &guid_vendor, sizeof(efi_guid_t));
dp->vendor_data[0] = desc->devnum;
return &dp->vendor_data[1];
}
+#endif #ifdef CONFIG_VIRTIO_BLK case UCLASS_VIRTIO: { struct efi_device_path_vendor *dp; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index dfd06dd31e4a..e7cf1567929b 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -562,11 +562,21 @@ static int efi_disk_create_part(struct udevice *dev) int efi_disk_create(struct udevice *dev) { enum uclass_id id;
struct blk_desc *desc; id = device_get_uclass_id(dev);
if (id == UCLASS_BLK)
if (id == UCLASS_BLK) {
/*
* avoid creating duplicated objects now that efi_driver
* has already created an efi_disk at this moment.
*/
desc = dev_get_uclass_plat(dev);
if (desc->if_type == IF_TYPE_EFI)
return 0;
return efi_disk_create_raw(dev);
} if (id == UCLASS_PARTITION) return efi_disk_create_part(dev);
-- 2.33.0
Regards, Simon

On Sun, Oct 10, 2021 at 08:14:30AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:05, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
Can you please add a commit message as I am not sure what this patch is doing.
Sure.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
lib/efi_driver/efi_block_device.c | 6 ++++++ lib/efi_loader/efi_device_path.c | 29 +++++++++++++++++++++++++++++ lib/efi_loader/efi_disk.c | 12 +++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 0937e3595a43..b6afa939e1d1 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -173,6 +173,12 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) plat->handle = handle; plat->io = interface;
/*
* FIXME: necessary because we won't do almost nothing in
* efi_disk_create() when called from device_probe().
*/
bdev->efi_obj = handle;
ret = device_probe(bdev); if (ret) return ret;
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index cbdb466da41c..36c77bce9a05 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -628,6 +628,35 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp->vendor_data[1]; } #endif +#ifdef CONFIG_EFI_LOADER
/*
* FIXME: conflicting with CONFIG_SANDBOX
In what way? If it is just a test we should be able to update the test to avoid the conflict.
I will revisit the issue because this hack may be linked to one of my patches in my repository which is not posted yet. You can ignore it for now.
-Takahiro Akashi
* This case is necessary to support efi_disk's created by
* efi_driver (and efi_driver_binding_protocol).
* TODO:
* The best way to work around here is to create efi_root as
* udevice and put all efi_driver objects under it.
*/
case UCLASS_ROOT: {
struct efi_device_path_vendor *dp;
struct blk_desc *desc = dev_get_uclass_plat(dev);
/* FIXME: guid_vendor used in selftest_block_device */
static efi_guid_t guid_vendor =
EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8);
dp_fill(buf, dev->parent);
dp = buf;
++dp;
dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
dp->dp.length = sizeof(*dp) + 1;
memcpy(&dp->guid, &guid_vendor, sizeof(efi_guid_t));
dp->vendor_data[0] = desc->devnum;
return &dp->vendor_data[1];
}
+#endif #ifdef CONFIG_VIRTIO_BLK case UCLASS_VIRTIO: { struct efi_device_path_vendor *dp; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index dfd06dd31e4a..e7cf1567929b 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -562,11 +562,21 @@ static int efi_disk_create_part(struct udevice *dev) int efi_disk_create(struct udevice *dev) { enum uclass_id id;
struct blk_desc *desc; id = device_get_uclass_id(dev);
if (id == UCLASS_BLK)
if (id == UCLASS_BLK) {
/*
* avoid creating duplicated objects now that efi_driver
* has already created an efi_disk at this moment.
*/
desc = dev_get_uclass_plat(dev);
if (desc->if_type == IF_TYPE_EFI)
return 0;
return efi_disk_create_raw(dev);
} if (id == UCLASS_PARTITION) return efi_disk_create_part(dev);
-- 2.33.0
Regards, Simon

efi_driver-specific binding will be no longer needed now that efi_disk- dm integration takes care of efi_driver case as well.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_driver/efi_block_device.c | 24 ------------------------ 1 file changed, 24 deletions(-)
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index b6afa939e1d1..1f39c93f7754 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -106,25 +106,6 @@ static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, return blkcnt; }
-/** - * Create partions for the block device. - * - * @handle: EFI handle of the block device - * @dev: udevice of the block device - * Return: number of partitions created - */ -static int efi_bl_bind_partitions(efi_handle_t handle, struct udevice *dev) -{ - struct blk_desc *desc; - const char *if_typename; - - desc = dev_get_uclass_plat(dev); - if_typename = blk_get_if_type_name(desc->if_type); - - return efi_disk_create_partitions(handle, desc, if_typename, - desc->devnum, dev->name); -} - /** * Create a block device for a handle * @@ -139,7 +120,6 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) char *name; struct efi_object *obj = efi_search_obj(handle); struct efi_block_io *io = interface; - int disks; struct efi_blk_plat *plat;
EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io); @@ -184,10 +164,6 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) return ret; EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
- /* Create handles for the partions of the block device */ - disks = efi_bl_bind_partitions(handle, bdev); - EFI_PRINT("Found %d partitions\n", disks); - return 0; }

efi_driver-specific binding will be no longer needed now that efi_disk- dm integration takes care of efi_driver case as well.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_driver/efi_block_device.c | 24 ------------------------ 1 file changed, 24 deletions(-)
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index b6afa939e1d1..1f39c93f7754 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -106,25 +106,6 @@ static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, return blkcnt; }
-/** - * Create partions for the block device. - * - * @handle: EFI handle of the block device - * @dev: udevice of the block device - * Return: number of partitions created - */ -static int efi_bl_bind_partitions(efi_handle_t handle, struct udevice *dev) -{ - struct blk_desc *desc; - const char *if_typename; - - desc = dev_get_uclass_plat(dev); - if_typename = blk_get_if_type_name(desc->if_type); - - return efi_disk_create_partitions(handle, desc, if_typename, - desc->devnum, dev->name); -} - /** * Create a block device for a handle * @@ -139,7 +120,6 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) char *name; struct efi_object *obj = efi_search_obj(handle); struct efi_block_io *io = interface; - int disks; struct efi_blk_plat *plat;
EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io); @@ -184,10 +164,6 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) return ret; EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
- /* Create handles for the partions of the block device */ - disks = efi_bl_bind_partitions(handle, bdev); - EFI_PRINT("Found %d partitions\n", disks); - return 0; }

On Thu, 30 Sept 2021 at 23:05, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
efi_driver-specific binding will be no longer needed now that efi_disk- dm integration takes care of efi_driver case as well.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
lib/efi_driver/efi_block_device.c | 24 ------------------------ 1 file changed, 24 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Due to efi_disk-dm integration, the resultant device path for a test disk got slightly changed, with efi_root contained as the first component.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_selftest/efi_selftest_block_device.c | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index 15f03751ac87..cac76249e6b4 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -30,6 +30,9 @@ static const efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; static const efi_guid_t guid_simple_file_system_protocol = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; static const efi_guid_t guid_file_system_info = EFI_FILE_SYSTEM_INFO_GUID; +static efi_guid_t guid_uboot = + EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \ + 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b); static efi_guid_t guid_vendor = EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8); @@ -206,25 +209,44 @@ static int setup(const efi_handle_t handle,
ret = boottime->allocate_pool(EFI_LOADER_DATA, sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path_vendor) + + sizeof(u8) + sizeof(struct efi_device_path), (void **)&dp); if (ret != EFI_SUCCESS) { efi_st_error("Out of memory\n"); return EFI_ST_FAILURE; } + /* first part */ vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; vendor_node.dp.length = sizeof(struct efi_device_path_vendor);
- boottime->copy_mem(&vendor_node.guid, &guid_vendor, + boottime->copy_mem(&vendor_node.guid, &guid_uboot, sizeof(efi_guid_t)); boottime->copy_mem(dp, &vendor_node, sizeof(struct efi_device_path_vendor)); + + /* second part */ + vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; + vendor_node.dp.length = sizeof(struct efi_device_path_vendor) + 1; + + boottime->copy_mem(&vendor_node.guid, &guid_vendor, + sizeof(efi_guid_t)); + boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor), + &vendor_node, + sizeof(struct efi_device_path_vendor)); + /* vendor_data[0] */ + *((char *)dp + sizeof(struct efi_device_path_vendor) * 2) = 0; + end_node.type = DEVICE_PATH_TYPE_END; end_node.sub_type = DEVICE_PATH_SUB_TYPE_END; end_node.length = sizeof(struct efi_device_path);
- boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor), + boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path_vendor) + + sizeof(u8), &end_node, sizeof(struct efi_device_path)); ret = boottime->install_protocol_interface(&disk_handle, &guid_device_path,

--- lib/efi_selftest/efi_selftest_block_device.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index cac76249e6b4..358797d224dc 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -268,6 +268,7 @@ static int teardown(void) { efi_status_t r = EFI_ST_SUCCESS;
+#if 0 /* TEMP */ if (disk_handle) { r = boottime->uninstall_protocol_interface(disk_handle, &guid_device_path, @@ -285,6 +286,7 @@ static int teardown(void) return EFI_ST_FAILURE; } } +#endif
if (image) { r = boottime->free_pool(image);

Due to efi_disk-dm integration, the resultant device path for a test disk got slightly changed, with efi_root contained as the first component.
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org --- lib/efi_selftest/efi_selftest_block_device.c | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index 15f03751ac87..cac76249e6b4 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -30,6 +30,9 @@ static const efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; static const efi_guid_t guid_simple_file_system_protocol = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; static const efi_guid_t guid_file_system_info = EFI_FILE_SYSTEM_INFO_GUID; +static efi_guid_t guid_uboot = + EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \ + 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b); static efi_guid_t guid_vendor = EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8); @@ -206,25 +209,44 @@ static int setup(const efi_handle_t handle,
ret = boottime->allocate_pool(EFI_LOADER_DATA, sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path_vendor) + + sizeof(u8) + sizeof(struct efi_device_path), (void **)&dp); if (ret != EFI_SUCCESS) { efi_st_error("Out of memory\n"); return EFI_ST_FAILURE; } + /* first part */ vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; vendor_node.dp.length = sizeof(struct efi_device_path_vendor);
- boottime->copy_mem(&vendor_node.guid, &guid_vendor, + boottime->copy_mem(&vendor_node.guid, &guid_uboot, sizeof(efi_guid_t)); boottime->copy_mem(dp, &vendor_node, sizeof(struct efi_device_path_vendor)); + + /* second part */ + vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; + vendor_node.dp.length = sizeof(struct efi_device_path_vendor) + 1; + + boottime->copy_mem(&vendor_node.guid, &guid_vendor, + sizeof(efi_guid_t)); + boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor), + &vendor_node, + sizeof(struct efi_device_path_vendor)); + /* vendor_data[0] */ + *((char *)dp + sizeof(struct efi_device_path_vendor) * 2) = 0; + end_node.type = DEVICE_PATH_TYPE_END; end_node.sub_type = DEVICE_PATH_SUB_TYPE_END; end_node.length = sizeof(struct efi_device_path);
- boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor), + boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path_vendor) + + sizeof(u8), &end_node, sizeof(struct efi_device_path)); ret = boottime->install_protocol_interface(&disk_handle, &guid_device_path,

On 10/1/21 07:02, AKASHI Takahiro wrote:
Due to efi_disk-dm integration, the resultant device path for a test disk got slightly changed, with efi_root contained as the first component.
The caller of ConnectController() creates a handle with a devicepath and a block IO protocol. The caller can choose whatever devicepath he wants.
If this test fails without this patch, this indicates that you broke the code. Please, review your design.
Best regards
Heinrich
Signed-off-by: AKASHI Takahiro takahiro.akashi@linaro.org
lib/efi_selftest/efi_selftest_block_device.c | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index 15f03751ac87..cac76249e6b4 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -30,6 +30,9 @@ static const efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; static const efi_guid_t guid_simple_file_system_protocol = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; static const efi_guid_t guid_file_system_info = EFI_FILE_SYSTEM_INFO_GUID; +static efi_guid_t guid_uboot =
- EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \
static efi_guid_t guid_vendor = EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8);0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b);
@@ -206,25 +209,44 @@ static int setup(const efi_handle_t handle,
ret = boottime->allocate_pool(EFI_LOADER_DATA, sizeof(struct efi_device_path_vendor) +
sizeof(struct efi_device_path_vendor) +
if (ret != EFI_SUCCESS) { efi_st_error("Out of memory\n"); return EFI_ST_FAILURE; }sizeof(u8) + sizeof(struct efi_device_path), (void **)&dp);
- /* first part */ vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; vendor_node.dp.length = sizeof(struct efi_device_path_vendor);
- boottime->copy_mem(&vendor_node.guid, &guid_vendor,
- boottime->copy_mem(&vendor_node.guid, &guid_uboot, sizeof(efi_guid_t)); boottime->copy_mem(dp, &vendor_node, sizeof(struct efi_device_path_vendor));
- /* second part */
- vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
- vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
- vendor_node.dp.length = sizeof(struct efi_device_path_vendor) + 1;
- boottime->copy_mem(&vendor_node.guid, &guid_vendor,
sizeof(efi_guid_t));
- boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor),
&vendor_node,
sizeof(struct efi_device_path_vendor));
- /* vendor_data[0] */
- *((char *)dp + sizeof(struct efi_device_path_vendor) * 2) = 0;
- end_node.type = DEVICE_PATH_TYPE_END; end_node.sub_type = DEVICE_PATH_SUB_TYPE_END; end_node.length = sizeof(struct efi_device_path);
- boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor),
- boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor)
+ sizeof(struct efi_device_path_vendor)
ret = boottime->install_protocol_interface(&disk_handle, &guid_device_path,+ sizeof(u8), &end_node, sizeof(struct efi_device_path));

Hi Takahiro,
On Thu, 30 Sept 2021 at 23:02, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
The purpose of this RPC is to reignite the discussion about how UEFI subystem would best be integrated into U-Boot device model. In the past, I poposed a couple of patch series, the latest one[1], while Heinrich revealed his idea[2], and the approach taken here is something between them, with a focus on block device handlings.
# The code is a PoC and not well tested yet.
Disks in UEFI world:
In general in UEFI world, accessing to any device is performed through a 'protocol' interface which are installed to (or associated with) the device's UEFI handle (or an opaque pointer to UEFI object data). Protocols are implemented by either the UEFI system itself or UEFI drivers.
For block IO's, it is a device which has EFI_BLOCK_IO_PROTOCOL (efi_disk hereafter). Currently, every efi_disk may have one of two origins: a.U-Boot's block devices or related partitions (lib/efi_loader/efi_disk.c) b.UEFI objects which are implemented as a block device by UEFI drivers. (lib/efi_driver/efi_block_device.c)
All the efi_diskss as (a) will be enumelated and created only once at UEFI subsystem initialization (efi_disk_register()), which is triggered by first executing one of UEFI-related U-Boot commands, like "bootefi", "setenv -e" or "efidebug". EFI_BLOCK_IO_PROTOCOL is implemented by UEFI system using blk_desc(->ops) in the corresponding udevice(UCLASS_BLK).
On the other hand, efi_disk as (b) will be created each time UEFI boot services' connect_controller() is executed in UEFI app which, as a (device) controller, gives the method to access the device's data, ie. EFI_BLOCK_IO_PROTOCOL.
more details >>>
Internally, connect_controller() search for UEFI driver that can support this controller/protocol, 'efi_block' driver(UCLASS_EFI) in this case, then calls the driver's 'bind' interface, which eventually installs the controller's EFI_BLOCK_IO_PROTOCOL to efi_disk object. 'efi_block' driver also create a corresponding udevice(UCLASS_BLK) for
- creating additional partitions efi_disk's, and
- supporting a file system (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL) on it.
<<< <<<
Issues:
While an efi_disk represents a device equally for either a whole disk or a partition in UEFI world, the device model treats only a whole disk as a real block device or udevice(UCLASS_BLK).
efi_disk holds and makes use of "blk_desc" data even though blk_desc in plat_data is supposed to be private and not to be accessed outside the device model. # This issue, though, exists for all the implmenetation of U-Boot # file systems as well.
Yes, this was a migration convenience and we should be able to unpick it now.
However we still have SPL_BLK so need to consider whether we can drop that.
For efi_disk(a), 3. A block device can be enumelated dynamically by 'scanning' a device bus in U-Boot, but UEFI subsystem is not able to update efi_disks accordingly. For examples, => scsi rescan; efidebug devices => usb start; efidebug devices ... (A) (A) doesn't show any usb devices detected.
=> scsi rescan; efidebug boot add -b 0 TEST scsi 0:1 ... => scsi rescan ... (B) => bootefi bootmgr ... (C)
(C) may de-reference a bogus blk_desc pointer which has been freed by (B). (Please note that "scsi rescan" removes all udevices/blk_desc and then re-create them even if nothing is changed on a bus.)
This is something your series will help with.
For efi_disk(b), 4. A controller (handle), combined with efi_block driver, has no corresponding udevice as a parent of efi_disks in DM tree, unlike, say, a scsi controller, even though it provides methods for block io perations.
Can we just create a udevice?
- There is no way supported to remove efi_disk's even after disconnect_controller() is called.
Do we want to remove disks? I don't really understand the context, but if EFI wants to forget about a disk, that should not affect the rest of U-Boot.
My approach in this RFC:
Due to functional differences in semantics, it would be difficult to identify "udevice" structure as a handle in UEFI world. Instead, we will have to somehow maintain a relationship between a udevice and a handle.
1-1. add a dedicated uclass, UCLASS_PARTITION, for partitions Currently, the uclass for paritions is not a UCLASS_BLK. It can be possible to define partitions as UCLASS_BLK (with IF_TYPE_PARTION?), but I'm afraid that it may introduce some chaos since udevice(UCLASS_BLK) is tightly coupled with 'struct blk_desc' data which is still used as a "structure to a whole disk" in a lot of interfaces. (I hope that you understand what it means.)
In DM tree, a UCLASS_PARTITON instance has a UCLASS_BLK parent: For instance, UCLASS_SCSI --- UCLASS_BLK --- UCLASS_PARTITION (IF_TYPE_SCSI) | +- struct blk_desc +- struct disk_part +- scsi_blk_ops +- blk_part_ops
Seems right to me. But I think a partition should also have a BLK child, so that only block devices can be read/written. In fact, perhaps a partition should be a child of the media device (e.g. MMC), not of the BLK device? That might make more sense.
1-2. create partition udevices in the context of device_probe() part_init() is already called in blk_post_probe(). See the commit d0851c893706 ("blk: Call part_init() in the post_probe() method"). Why not enumelate partitions as well in there.
Sounds reasonable.
- add new block access interfaces, which takes "udevice" as a target device, in U-Boot and use those functions to implement efi_disk operations (i.e. EFI_BLOCK_IO_PROTOCOL).
Nice.
3-1. maintain a bi-directional link by adding
- a UEFI handle pointer in "struct udevice"
- a udevice pointer in UEFI handle (in fact, in "struct efi_disk_obj")
We should generalise the API here, but otherwise seems right. See my comment on the patch.
3-2. use device model's post_probe/pre_remove hook to synchronize the lifetime of efi_disk objects in UEFI world with the device model.
We should add an event mechanism to generalise this a bit. See my comment on the patch.
- I have no answer to issue(4) and (5) yet.
See above.
Patchs:
For easy understandings, patches may be categorized into seperate groups of changes.
Patch#1-#9: DM: create udevices for partitions Patch#11,#12: UEFI: use udevice interfaces Patch#13-#16: UEFI: sync up with the device model for adding Patch#17-#19: UEFI: sync up with the device model for removing For removal case, we may need more consideration since removing handles unconditionally may end up breaking integrity of handles (some may still be held and referenced to by a UEFI app). Patch#20-#22: UEFI: align efi_driver with changes by the integration
This looks great to me and is the first real step I have seen to actually solving the problem of all this duplication.
I think we need a few more DM APIs as I suggest in a few of the patches. I am happy to help with these if you like.
I wonder if it is possible to get some version of at least part of this code applied in this merge window? It helps to set things on a much better direction.
I also worry that continuing to develop the EFI impl while it is such a sorry state is adding to the difficulty of fixing it up.
Regards, Simon
[1] https://lists.denx.de/pipermail/u-boot/2019-February/357923.html [2] https://lists.denx.de/pipermail/u-boot/2021-June/452297.html
AKASHI Takahiro (22): scsi: call device_probe() after scanning usb: storage: call device_probe() after scanning mmc: call device_probe() after scanning nvme: call device_probe() after scanning sata: call device_probe() after scanning block: ide: call device_probe() after scanning dm: blk: add UCLASS_PARTITION dm: blk: add a device-probe hook for scanning disk partitions dm: blk: add read/write interfaces with udevice efi_loader: disk: use udevice instead of blk_desc dm: add a hidden link to efi object efi_loader: remove !CONFIG_BLK code from efi_disk efi_loader: disk: a helper function to create efi_disk objects from udevice dm: blk: call efi's device-probe hook efi_loader: cleanup after efi_disk-dm integration efi_loader: add efi_remove_handle() efi_loader: efi_disk: a helper function to delete efi_disk objects dm: blk: call efi's device-removal hook efi_driver: align with efi_disk-dm integration efi_driver: cleanup after efi_disk-dm integration efi_selftest: block device: adjust dp for a test disk (TEST) let dm-tree unchanged after block_io testing is done
common/usb_storage.c | 6 + drivers/ata/dwc_ahsata.c | 10 + drivers/ata/fsl_sata.c | 11 + drivers/ata/sata_mv.c | 9 + drivers/ata/sata_sil.c | 12 + drivers/block/blk-uclass.c | 249 ++++++++++++++++ drivers/block/ide.c | 6 + drivers/mmc/mmc-uclass.c | 7 + drivers/nvme/nvme.c | 6 + drivers/scsi/scsi.c | 10 + include/blk.h | 15 + include/dm/device.h | 4 + include/dm/uclass-id.h | 1 + include/efi_loader.h | 8 +- lib/efi_driver/efi_block_device.c | 30 +- lib/efi_loader/efi_boottime.c | 8 + lib/efi_loader/efi_device_path.c | 29 ++ lib/efi_loader/efi_disk.c | 286 ++++++++++--------- lib/efi_loader/efi_setup.c | 5 - lib/efi_selftest/efi_selftest_block_device.c | 28 +- 20 files changed, 566 insertions(+), 174 deletions(-)
-- 2.33.0

On Sun, Oct 10, 2021 at 08:14:00AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:02, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
The purpose of this RPC is to reignite the discussion about how UEFI subystem would best be integrated into U-Boot device model. In the past, I poposed a couple of patch series, the latest one[1], while Heinrich revealed his idea[2], and the approach taken here is something between them, with a focus on block device handlings.
# The code is a PoC and not well tested yet.
Disks in UEFI world:
In general in UEFI world, accessing to any device is performed through a 'protocol' interface which are installed to (or associated with) the device's UEFI handle (or an opaque pointer to UEFI object data). Protocols are implemented by either the UEFI system itself or UEFI drivers.
For block IO's, it is a device which has EFI_BLOCK_IO_PROTOCOL (efi_disk hereafter). Currently, every efi_disk may have one of two origins: a.U-Boot's block devices or related partitions (lib/efi_loader/efi_disk.c) b.UEFI objects which are implemented as a block device by UEFI drivers. (lib/efi_driver/efi_block_device.c)
All the efi_diskss as (a) will be enumelated and created only once at UEFI subsystem initialization (efi_disk_register()), which is triggered by first executing one of UEFI-related U-Boot commands, like "bootefi", "setenv -e" or "efidebug". EFI_BLOCK_IO_PROTOCOL is implemented by UEFI system using blk_desc(->ops) in the corresponding udevice(UCLASS_BLK).
On the other hand, efi_disk as (b) will be created each time UEFI boot services' connect_controller() is executed in UEFI app which, as a (device) controller, gives the method to access the device's data, ie. EFI_BLOCK_IO_PROTOCOL.
more details >>>
Internally, connect_controller() search for UEFI driver that can support this controller/protocol, 'efi_block' driver(UCLASS_EFI) in this case, then calls the driver's 'bind' interface, which eventually installs the controller's EFI_BLOCK_IO_PROTOCOL to efi_disk object. 'efi_block' driver also create a corresponding udevice(UCLASS_BLK) for
- creating additional partitions efi_disk's, and
- supporting a file system (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL) on it.
<<< <<<
Issues:
While an efi_disk represents a device equally for either a whole disk or a partition in UEFI world, the device model treats only a whole disk as a real block device or udevice(UCLASS_BLK).
efi_disk holds and makes use of "blk_desc" data even though blk_desc in plat_data is supposed to be private and not to be accessed outside the device model. # This issue, though, exists for all the implmenetation of U-Boot # file systems as well.
Yes, this was a migration convenience and we should be able to unpick it now.
However we still have SPL_BLK so need to consider whether we can drop that.
To be clear here, in that I can hand-wave my way to seeing a use case for lib/efi_loader/ under SPL, it would not be in a world where we also still would be supporting the non-DM infrastructure, and is also not a near-term goal.

Hi Tom,
On Tue, 12 Oct 2021 at 09:00, Tom Rini trini@konsulko.com wrote:
On Sun, Oct 10, 2021 at 08:14:00AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:02, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
The purpose of this RPC is to reignite the discussion about how UEFI subystem would best be integrated into U-Boot device model. In the past, I poposed a couple of patch series, the latest one[1], while Heinrich revealed his idea[2], and the approach taken here is something between them, with a focus on block device handlings.
# The code is a PoC and not well tested yet.
Disks in UEFI world:
In general in UEFI world, accessing to any device is performed through a 'protocol' interface which are installed to (or associated with) the device's UEFI handle (or an opaque pointer to UEFI object data). Protocols are implemented by either the UEFI system itself or UEFI drivers.
For block IO's, it is a device which has EFI_BLOCK_IO_PROTOCOL (efi_disk hereafter). Currently, every efi_disk may have one of two origins: a.U-Boot's block devices or related partitions (lib/efi_loader/efi_disk.c) b.UEFI objects which are implemented as a block device by UEFI drivers. (lib/efi_driver/efi_block_device.c)
All the efi_diskss as (a) will be enumelated and created only once at UEFI subsystem initialization (efi_disk_register()), which is triggered by first executing one of UEFI-related U-Boot commands, like "bootefi", "setenv -e" or "efidebug". EFI_BLOCK_IO_PROTOCOL is implemented by UEFI system using blk_desc(->ops) in the corresponding udevice(UCLASS_BLK).
On the other hand, efi_disk as (b) will be created each time UEFI boot services' connect_controller() is executed in UEFI app which, as a (device) controller, gives the method to access the device's data, ie. EFI_BLOCK_IO_PROTOCOL.
more details >>>
Internally, connect_controller() search for UEFI driver that can support this controller/protocol, 'efi_block' driver(UCLASS_EFI) in this case, then calls the driver's 'bind' interface, which eventually installs the controller's EFI_BLOCK_IO_PROTOCOL to efi_disk object. 'efi_block' driver also create a corresponding udevice(UCLASS_BLK) for
- creating additional partitions efi_disk's, and
- supporting a file system (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL) on it.
<<< <<<
Issues:
While an efi_disk represents a device equally for either a whole disk or a partition in UEFI world, the device model treats only a whole disk as a real block device or udevice(UCLASS_BLK).
efi_disk holds and makes use of "blk_desc" data even though blk_desc in plat_data is supposed to be private and not to be accessed outside the device model. # This issue, though, exists for all the implmenetation of U-Boot # file systems as well.
Yes, this was a migration convenience and we should be able to unpick it now.
However we still have SPL_BLK so need to consider whether we can drop that.
To be clear here, in that I can hand-wave my way to seeing a use case for lib/efi_loader/ under SPL, it would not be in a world where we also still would be supporting the non-DM infrastructure, and is also not a near-term goal.
OK good. Perhaps we should add a migration method for SPL_BLK? It would be good to know where we are in terms of the size stuff. I don't see a lot of boards rushing to use of-platdata, though.
Regards, Simon

On Tue, Oct 12, 2021 at 02:31:15PM -0600, Simon Glass wrote:
Hi Tom,
On Tue, 12 Oct 2021 at 09:00, Tom Rini trini@konsulko.com wrote:
On Sun, Oct 10, 2021 at 08:14:00AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:02, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
The purpose of this RPC is to reignite the discussion about how UEFI subystem would best be integrated into U-Boot device model. In the past, I poposed a couple of patch series, the latest one[1], while Heinrich revealed his idea[2], and the approach taken here is something between them, with a focus on block device handlings.
# The code is a PoC and not well tested yet.
Disks in UEFI world:
In general in UEFI world, accessing to any device is performed through a 'protocol' interface which are installed to (or associated with) the device's UEFI handle (or an opaque pointer to UEFI object data). Protocols are implemented by either the UEFI system itself or UEFI drivers.
For block IO's, it is a device which has EFI_BLOCK_IO_PROTOCOL (efi_disk hereafter). Currently, every efi_disk may have one of two origins: a.U-Boot's block devices or related partitions (lib/efi_loader/efi_disk.c) b.UEFI objects which are implemented as a block device by UEFI drivers. (lib/efi_driver/efi_block_device.c)
All the efi_diskss as (a) will be enumelated and created only once at UEFI subsystem initialization (efi_disk_register()), which is triggered by first executing one of UEFI-related U-Boot commands, like "bootefi", "setenv -e" or "efidebug". EFI_BLOCK_IO_PROTOCOL is implemented by UEFI system using blk_desc(->ops) in the corresponding udevice(UCLASS_BLK).
On the other hand, efi_disk as (b) will be created each time UEFI boot services' connect_controller() is executed in UEFI app which, as a (device) controller, gives the method to access the device's data, ie. EFI_BLOCK_IO_PROTOCOL.
> more details >>>
Internally, connect_controller() search for UEFI driver that can support this controller/protocol, 'efi_block' driver(UCLASS_EFI) in this case, then calls the driver's 'bind' interface, which eventually installs the controller's EFI_BLOCK_IO_PROTOCOL to efi_disk object. 'efi_block' driver also create a corresponding udevice(UCLASS_BLK) for
- creating additional partitions efi_disk's, and
- supporting a file system (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL) on it.
<<< <<<
Issues:
While an efi_disk represents a device equally for either a whole disk or a partition in UEFI world, the device model treats only a whole disk as a real block device or udevice(UCLASS_BLK).
efi_disk holds and makes use of "blk_desc" data even though blk_desc in plat_data is supposed to be private and not to be accessed outside the device model. # This issue, though, exists for all the implmenetation of U-Boot # file systems as well.
Yes, this was a migration convenience and we should be able to unpick it now.
However we still have SPL_BLK so need to consider whether we can drop that.
To be clear here, in that I can hand-wave my way to seeing a use case for lib/efi_loader/ under SPL, it would not be in a world where we also still would be supporting the non-DM infrastructure, and is also not a near-term goal.
OK good. Perhaps we should add a migration method for SPL_BLK? It would be good to know where we are in terms of the size stuff. I don't see a lot of boards rushing to use of-platdata, though.
What do you mean? Since we have platforms that need to support 12 or 16 KiB of space for SPL, we're not going to enforce SPL_DM. But those platforms can / do need to boot from MMC (SD card I think usually).
In terms of platforms that could, but don't, enable SPL_BLK, that's just the platforms that disable SPL_BLK today as it defaults to enabled when possible.

Hi Tom,
On Tue, 12 Oct 2021 at 15:13, Tom Rini trini@konsulko.com wrote:
On Tue, Oct 12, 2021 at 02:31:15PM -0600, Simon Glass wrote:
Hi Tom,
On Tue, 12 Oct 2021 at 09:00, Tom Rini trini@konsulko.com wrote:
On Sun, Oct 10, 2021 at 08:14:00AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:02, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
The purpose of this RPC is to reignite the discussion about how UEFI subystem would best be integrated into U-Boot device model. In the past, I poposed a couple of patch series, the latest one[1], while Heinrich revealed his idea[2], and the approach taken here is something between them, with a focus on block device handlings.
# The code is a PoC and not well tested yet.
Disks in UEFI world:
In general in UEFI world, accessing to any device is performed through a 'protocol' interface which are installed to (or associated with) the device's UEFI handle (or an opaque pointer to UEFI object data). Protocols are implemented by either the UEFI system itself or UEFI drivers.
For block IO's, it is a device which has EFI_BLOCK_IO_PROTOCOL (efi_disk hereafter). Currently, every efi_disk may have one of two origins: a.U-Boot's block devices or related partitions (lib/efi_loader/efi_disk.c) b.UEFI objects which are implemented as a block device by UEFI drivers. (lib/efi_driver/efi_block_device.c)
All the efi_diskss as (a) will be enumelated and created only once at UEFI subsystem initialization (efi_disk_register()), which is triggered by first executing one of UEFI-related U-Boot commands, like "bootefi", "setenv -e" or "efidebug". EFI_BLOCK_IO_PROTOCOL is implemented by UEFI system using blk_desc(->ops) in the corresponding udevice(UCLASS_BLK).
On the other hand, efi_disk as (b) will be created each time UEFI boot services' connect_controller() is executed in UEFI app which, as a (device) controller, gives the method to access the device's data, ie. EFI_BLOCK_IO_PROTOCOL.
>> more details >>>
Internally, connect_controller() search for UEFI driver that can support this controller/protocol, 'efi_block' driver(UCLASS_EFI) in this case, then calls the driver's 'bind' interface, which eventually installs the controller's EFI_BLOCK_IO_PROTOCOL to efi_disk object. 'efi_block' driver also create a corresponding udevice(UCLASS_BLK) for
- creating additional partitions efi_disk's, and
- supporting a file system (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL) on it.
<<< <<<
Issues:
While an efi_disk represents a device equally for either a whole disk or a partition in UEFI world, the device model treats only a whole disk as a real block device or udevice(UCLASS_BLK).
efi_disk holds and makes use of "blk_desc" data even though blk_desc in plat_data is supposed to be private and not to be accessed outside the device model. # This issue, though, exists for all the implmenetation of U-Boot # file systems as well.
Yes, this was a migration convenience and we should be able to unpick it now.
However we still have SPL_BLK so need to consider whether we can drop that.
To be clear here, in that I can hand-wave my way to seeing a use case for lib/efi_loader/ under SPL, it would not be in a world where we also still would be supporting the non-DM infrastructure, and is also not a near-term goal.
OK good. Perhaps we should add a migration method for SPL_BLK? It would be good to know where we are in terms of the size stuff. I don't see a lot of boards rushing to use of-platdata, though.
What do you mean? Since we have platforms that need to support 12 or 16 KiB of space for SPL, we're not going to enforce SPL_DM. But those platforms can / do need to boot from MMC (SD card I think usually).
In terms of platforms that could, but don't, enable SPL_BLK, that's just the platforms that disable SPL_BLK today as it defaults to enabled when possible.
Well I wonder if we can use of-platdata and DM then perhaps some of these will fit. The OMAP platform I sent patches for was close to complete, I think, and I believe that was one of the tightest. Actually I cannot remember what board that was...
The overhead is perhaps 7KB though, so maybe not suitable for 16KB.
Regards, Simon

On Tue, Oct 12, 2021 at 05:37:45PM -0600, Simon Glass wrote:
Hi Tom,
On Tue, 12 Oct 2021 at 15:13, Tom Rini trini@konsulko.com wrote:
On Tue, Oct 12, 2021 at 02:31:15PM -0600, Simon Glass wrote:
Hi Tom,
On Tue, 12 Oct 2021 at 09:00, Tom Rini trini@konsulko.com wrote:
On Sun, Oct 10, 2021 at 08:14:00AM -0600, Simon Glass wrote:
Hi Takahiro,
On Thu, 30 Sept 2021 at 23:02, AKASHI Takahiro takahiro.akashi@linaro.org wrote:
The purpose of this RPC is to reignite the discussion about how UEFI subystem would best be integrated into U-Boot device model. In the past, I poposed a couple of patch series, the latest one[1], while Heinrich revealed his idea[2], and the approach taken here is something between them, with a focus on block device handlings.
# The code is a PoC and not well tested yet.
Disks in UEFI world:
In general in UEFI world, accessing to any device is performed through a 'protocol' interface which are installed to (or associated with) the device's UEFI handle (or an opaque pointer to UEFI object data). Protocols are implemented by either the UEFI system itself or UEFI drivers.
For block IO's, it is a device which has EFI_BLOCK_IO_PROTOCOL (efi_disk hereafter). Currently, every efi_disk may have one of two origins: a.U-Boot's block devices or related partitions (lib/efi_loader/efi_disk.c) b.UEFI objects which are implemented as a block device by UEFI drivers. (lib/efi_driver/efi_block_device.c)
All the efi_diskss as (a) will be enumelated and created only once at UEFI subsystem initialization (efi_disk_register()), which is triggered by first executing one of UEFI-related U-Boot commands, like "bootefi", "setenv -e" or "efidebug". EFI_BLOCK_IO_PROTOCOL is implemented by UEFI system using blk_desc(->ops) in the corresponding udevice(UCLASS_BLK).
On the other hand, efi_disk as (b) will be created each time UEFI boot services' connect_controller() is executed in UEFI app which, as a (device) controller, gives the method to access the device's data, ie. EFI_BLOCK_IO_PROTOCOL.
>>> more details >>> Internally, connect_controller() search for UEFI driver that can support this controller/protocol, 'efi_block' driver(UCLASS_EFI) in this case, then calls the driver's 'bind' interface, which eventually installs the controller's EFI_BLOCK_IO_PROTOCOL to efi_disk object. 'efi_block' driver also create a corresponding udevice(UCLASS_BLK) for
- creating additional partitions efi_disk's, and
- supporting a file system (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL) on it.
<<< <<<
Issues:
While an efi_disk represents a device equally for either a whole disk or a partition in UEFI world, the device model treats only a whole disk as a real block device or udevice(UCLASS_BLK).
efi_disk holds and makes use of "blk_desc" data even though blk_desc in plat_data is supposed to be private and not to be accessed outside the device model. # This issue, though, exists for all the implmenetation of U-Boot # file systems as well.
Yes, this was a migration convenience and we should be able to unpick it now.
However we still have SPL_BLK so need to consider whether we can drop that.
To be clear here, in that I can hand-wave my way to seeing a use case for lib/efi_loader/ under SPL, it would not be in a world where we also still would be supporting the non-DM infrastructure, and is also not a near-term goal.
OK good. Perhaps we should add a migration method for SPL_BLK? It would be good to know where we are in terms of the size stuff. I don't see a lot of boards rushing to use of-platdata, though.
What do you mean? Since we have platforms that need to support 12 or 16 KiB of space for SPL, we're not going to enforce SPL_DM. But those platforms can / do need to boot from MMC (SD card I think usually).
In terms of platforms that could, but don't, enable SPL_BLK, that's just the platforms that disable SPL_BLK today as it defaults to enabled when possible.
Well I wonder if we can use of-platdata and DM then perhaps some of these will fit. The OMAP platform I sent patches for was close to complete, I think, and I believe that was one of the tightest. Actually I cannot remember what board that was...
The overhead is perhaps 7KB though, so maybe not suitable for 16KB.
It's only disabled on the vboot config, on am335x platforms. Honestly, I would suggest a separate thread and ask the board maintainers in question why specifically it's off. I know for am335x_boneblack_vboot_defconfig it's inadvertent, it could be turned on no problem I suspect.
participants (6)
-
AKASHI Takahiro
-
Heinrich Schuchardt
-
Ilias Apalodimas
-
Peter Robinson
-
Simon Glass
-
Tom Rini