14d3c95f5SJorgen Lundman /* 24d3c95f5SJorgen Lundman * 34d3c95f5SJorgen Lundman * based on code of fs/reiserfs/dev.c by 44d3c95f5SJorgen Lundman * 54d3c95f5SJorgen Lundman * (C) Copyright 2003 - 2004 64d3c95f5SJorgen Lundman * Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com> 74d3c95f5SJorgen Lundman * 8*1a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 94d3c95f5SJorgen Lundman */ 104d3c95f5SJorgen Lundman 114d3c95f5SJorgen Lundman 124d3c95f5SJorgen Lundman #include <common.h> 134d3c95f5SJorgen Lundman #include <config.h> 144d3c95f5SJorgen Lundman #include <zfs_common.h> 154d3c95f5SJorgen Lundman 164d3c95f5SJorgen Lundman static block_dev_desc_t *zfs_block_dev_desc; 1741204570SRob Herring static disk_partition_t *part_info; 184d3c95f5SJorgen Lundman 1941204570SRob Herring void zfs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info) 204d3c95f5SJorgen Lundman { 214d3c95f5SJorgen Lundman zfs_block_dev_desc = rbdd; 2241204570SRob Herring part_info = info; 234d3c95f5SJorgen Lundman } 244d3c95f5SJorgen Lundman 254d3c95f5SJorgen Lundman /* err */ 264d3c95f5SJorgen Lundman int zfs_devread(int sector, int byte_offset, int byte_len, char *buf) 274d3c95f5SJorgen Lundman { 284d3c95f5SJorgen Lundman short sec_buffer[SECTOR_SIZE/sizeof(short)]; 294d3c95f5SJorgen Lundman char *sec_buf = (char *)sec_buffer; 304d3c95f5SJorgen Lundman unsigned block_len; 314d3c95f5SJorgen Lundman 324d3c95f5SJorgen Lundman /* 334d3c95f5SJorgen Lundman * Check partition boundaries 344d3c95f5SJorgen Lundman */ 354d3c95f5SJorgen Lundman if ((sector < 0) || 364d3c95f5SJorgen Lundman ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >= 3741204570SRob Herring part_info->size)) { 384d3c95f5SJorgen Lundman /* errnum = ERR_OUTSIDE_PART; */ 394d3c95f5SJorgen Lundman printf(" ** zfs_devread() read outside partition sector %d\n", sector); 404d3c95f5SJorgen Lundman return 1; 414d3c95f5SJorgen Lundman } 424d3c95f5SJorgen Lundman 434d3c95f5SJorgen Lundman /* 444d3c95f5SJorgen Lundman * Get the read to the beginning of a partition. 454d3c95f5SJorgen Lundman */ 464d3c95f5SJorgen Lundman sector += byte_offset >> SECTOR_BITS; 474d3c95f5SJorgen Lundman byte_offset &= SECTOR_SIZE - 1; 484d3c95f5SJorgen Lundman 494d3c95f5SJorgen Lundman debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len); 504d3c95f5SJorgen Lundman 514d3c95f5SJorgen Lundman if (zfs_block_dev_desc == NULL) { 524d3c95f5SJorgen Lundman printf("** Invalid Block Device Descriptor (NULL)\n"); 534d3c95f5SJorgen Lundman return 1; 544d3c95f5SJorgen Lundman } 554d3c95f5SJorgen Lundman 564d3c95f5SJorgen Lundman if (byte_offset != 0) { 574d3c95f5SJorgen Lundman /* read first part which isn't aligned with start of sector */ 584d3c95f5SJorgen Lundman if (zfs_block_dev_desc->block_read(zfs_block_dev_desc->dev, 5941204570SRob Herring part_info->start + sector, 1, 604d3c95f5SJorgen Lundman (unsigned long *)sec_buf) != 1) { 614d3c95f5SJorgen Lundman printf(" ** zfs_devread() read error **\n"); 624d3c95f5SJorgen Lundman return 1; 634d3c95f5SJorgen Lundman } 644d3c95f5SJorgen Lundman memcpy(buf, sec_buf + byte_offset, 654d3c95f5SJorgen Lundman min(SECTOR_SIZE - byte_offset, byte_len)); 664d3c95f5SJorgen Lundman buf += min(SECTOR_SIZE - byte_offset, byte_len); 674d3c95f5SJorgen Lundman byte_len -= min(SECTOR_SIZE - byte_offset, byte_len); 684d3c95f5SJorgen Lundman sector++; 694d3c95f5SJorgen Lundman } 704d3c95f5SJorgen Lundman 714d3c95f5SJorgen Lundman if (byte_len == 0) 724d3c95f5SJorgen Lundman return 0; 734d3c95f5SJorgen Lundman 744d3c95f5SJorgen Lundman /* read sector aligned part */ 754d3c95f5SJorgen Lundman block_len = byte_len & ~(SECTOR_SIZE - 1); 764d3c95f5SJorgen Lundman 774d3c95f5SJorgen Lundman if (block_len == 0) { 784d3c95f5SJorgen Lundman u8 p[SECTOR_SIZE]; 794d3c95f5SJorgen Lundman 804d3c95f5SJorgen Lundman block_len = SECTOR_SIZE; 814d3c95f5SJorgen Lundman zfs_block_dev_desc->block_read(zfs_block_dev_desc->dev, 8241204570SRob Herring part_info->start + sector, 834d3c95f5SJorgen Lundman 1, (unsigned long *)p); 844d3c95f5SJorgen Lundman memcpy(buf, p, byte_len); 854d3c95f5SJorgen Lundman return 0; 864d3c95f5SJorgen Lundman } 874d3c95f5SJorgen Lundman 884d3c95f5SJorgen Lundman if (zfs_block_dev_desc->block_read(zfs_block_dev_desc->dev, 8941204570SRob Herring part_info->start + sector, block_len / SECTOR_SIZE, 9041204570SRob Herring (unsigned long *) buf) != block_len / SECTOR_SIZE) { 914d3c95f5SJorgen Lundman printf(" ** zfs_devread() read error - block\n"); 924d3c95f5SJorgen Lundman return 1; 934d3c95f5SJorgen Lundman } 944d3c95f5SJorgen Lundman 954d3c95f5SJorgen Lundman block_len = byte_len & ~(SECTOR_SIZE - 1); 964d3c95f5SJorgen Lundman buf += block_len; 974d3c95f5SJorgen Lundman byte_len -= block_len; 984d3c95f5SJorgen Lundman sector += block_len / SECTOR_SIZE; 994d3c95f5SJorgen Lundman 1004d3c95f5SJorgen Lundman if (byte_len != 0) { 1014d3c95f5SJorgen Lundman /* read rest of data which are not in whole sector */ 1024d3c95f5SJorgen Lundman if (zfs_block_dev_desc-> 1034d3c95f5SJorgen Lundman block_read(zfs_block_dev_desc->dev, 10441204570SRob Herring part_info->start + sector, 1, 1054d3c95f5SJorgen Lundman (unsigned long *) sec_buf) != 1) { 1064d3c95f5SJorgen Lundman printf(" ** zfs_devread() read error - last part\n"); 1074d3c95f5SJorgen Lundman return 1; 1084d3c95f5SJorgen Lundman } 1094d3c95f5SJorgen Lundman memcpy(buf, sec_buf, byte_len); 1104d3c95f5SJorgen Lundman } 1114d3c95f5SJorgen Lundman return 0; 1124d3c95f5SJorgen Lundman } 113