"Das U-Boot" Source Tree
at master 141 lines 3.8 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Software partition device (UCLASS_PARTITION) 4 * 5 * Copyright (c) 2021 Linaro Limited 6 * Author: AKASHI Takahiro 7 */ 8 9#define LOG_CATEGORY UCLASS_PARTITION 10 11#include <blk.h> 12#include <dm.h> 13#include <log.h> 14#include <part.h> 15#include <vsprintf.h> 16#include <dm/device-internal.h> 17#include <dm/lists.h> 18 19/** 20 * disk_blk_part_validate() - Check whether access to partition is within limits 21 * 22 * @dev: Device (partition udevice) 23 * @start: Start block for the access(from start of partition) 24 * @blkcnt: Number of blocks to access (within the partition) 25 * @return 0 on valid block range, or -ve on error. 26 */ 27static int disk_blk_part_validate(struct udevice *dev, lbaint_t start, lbaint_t blkcnt) 28{ 29 struct disk_part *part = dev_get_uclass_plat(dev); 30 31 if (device_get_uclass_id(dev) != UCLASS_PARTITION) 32 return -ENOSYS; 33 34 if (start >= part->gpt_part_info.size) 35 return -E2BIG; 36 37 if ((start + blkcnt) > part->gpt_part_info.size) 38 return -ERANGE; 39 40 return 0; 41} 42 43/** 44 * disk_blk_part_offset() - Compute offset from start of block device 45 * 46 * @dev: Device (partition udevice) 47 * @start: Start block for the access (from start of partition) 48 * @return Start block for the access (from start of block device) 49 */ 50static lbaint_t disk_blk_part_offset(struct udevice *dev, lbaint_t start) 51{ 52 struct disk_part *part = dev_get_uclass_plat(dev); 53 54 return start + part->gpt_part_info.start; 55} 56 57/* 58 * BLOCK IO APIs 59 */ 60/** 61 * disk_blk_read() - Read from a block device partition 62 * 63 * @dev: Device to read from (partition udevice) 64 * @start: Start block for the read (from start of partition) 65 * @blkcnt: Number of blocks to read (within the partition) 66 * @buffer: Place to put the data 67 * @return number of blocks read (which may be less than @blkcnt), 68 * or -ve on error. This never returns 0 unless @blkcnt is 0 69 */ 70unsigned long disk_blk_read(struct udevice *dev, lbaint_t start, 71 lbaint_t blkcnt, void *buffer) 72{ 73 int ret = disk_blk_part_validate(dev, start, blkcnt); 74 75 if (ret) 76 return ret; 77 78 return blk_read(dev_get_parent(dev), disk_blk_part_offset(dev, start), 79 blkcnt, buffer); 80} 81 82/** 83 * disk_blk_write() - Write to a block device 84 * 85 * @dev: Device to write to (partition udevice) 86 * @start: Start block for the write (from start of partition) 87 * @blkcnt: Number of blocks to write (within the partition) 88 * @buffer: Data to write 89 * @return number of blocks written (which may be less than @blkcnt), 90 * or -ve on error. This never returns 0 unless @blkcnt is 0 91 */ 92unsigned long disk_blk_write(struct udevice *dev, lbaint_t start, 93 lbaint_t blkcnt, const void *buffer) 94{ 95 int ret = disk_blk_part_validate(dev, start, blkcnt); 96 97 if (ret) 98 return ret; 99 100 return blk_write(dev_get_parent(dev), disk_blk_part_offset(dev, start), 101 blkcnt, buffer); 102} 103 104/** 105 * disk_blk_erase() - Erase part of a block device 106 * 107 * @dev: Device to erase (partition udevice) 108 * @start: Start block for the erase (from start of partition) 109 * @blkcnt: Number of blocks to erase (within the partition) 110 * @return number of blocks erased (which may be less than @blkcnt), 111 * or -ve on error. This never returns 0 unless @blkcnt is 0 112 */ 113unsigned long disk_blk_erase(struct udevice *dev, lbaint_t start, 114 lbaint_t blkcnt) 115{ 116 int ret = disk_blk_part_validate(dev, start, blkcnt); 117 118 if (ret) 119 return ret; 120 121 return blk_erase(dev_get_parent(dev), disk_blk_part_offset(dev, start), 122 blkcnt); 123} 124 125UCLASS_DRIVER(partition) = { 126 .id = UCLASS_PARTITION, 127 .per_device_plat_auto = sizeof(struct disk_part), 128 .name = "partition", 129}; 130 131static const struct blk_ops blk_part_ops = { 132 .read = disk_blk_read, 133 .write = disk_blk_write, 134 .erase = disk_blk_erase, 135}; 136 137U_BOOT_DRIVER(blk_partition) = { 138 .name = "blk_partition", 139 .id = UCLASS_PARTITION, 140 .ops = &blk_part_ops, 141};