uboot/fs/zfs/dev.c
<<
>>
Prefs
   1/*
   2 *
   3 *      based on code of fs/reiserfs/dev.c by
   4 *
   5 *      (C) Copyright 2003 - 2004
   6 *      Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11
  12#include <common.h>
  13#include <config.h>
  14#include <zfs_common.h>
  15
  16static struct blk_desc *zfs_blk_desc;
  17static disk_partition_t *part_info;
  18
  19void zfs_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info)
  20{
  21        zfs_blk_desc = rbdd;
  22        part_info = info;
  23}
  24
  25/* err */
  26int zfs_devread(int sector, int byte_offset, int byte_len, char *buf)
  27{
  28        short sec_buffer[SECTOR_SIZE/sizeof(short)];
  29        char *sec_buf = (char *)sec_buffer;
  30        unsigned block_len;
  31
  32        /*
  33         *      Check partition boundaries
  34         */
  35        if ((sector < 0) ||
  36                ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >=
  37                 part_info->size)) {
  38                /*              errnum = ERR_OUTSIDE_PART; */
  39                printf(" ** zfs_devread() read outside partition sector %d\n", sector);
  40                return 1;
  41        }
  42
  43        /*
  44         *      Get the read to the beginning of a partition.
  45         */
  46        sector += byte_offset >> SECTOR_BITS;
  47        byte_offset &= SECTOR_SIZE - 1;
  48
  49        debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len);
  50
  51        if (zfs_blk_desc == NULL) {
  52                printf("** Invalid Block Device Descriptor (NULL)\n");
  53                return 1;
  54        }
  55
  56        if (byte_offset != 0) {
  57                /* read first part which isn't aligned with start of sector */
  58                if (zfs_blk_desc->block_read(zfs_blk_desc,
  59                                             part_info->start + sector, 1,
  60                                             (void *)sec_buf) != 1) {
  61                        printf(" ** zfs_devread() read error **\n");
  62                        return 1;
  63                }
  64                memcpy(buf, sec_buf + byte_offset,
  65                           min(SECTOR_SIZE - byte_offset, byte_len));
  66                buf += min(SECTOR_SIZE - byte_offset, byte_len);
  67                byte_len -= min(SECTOR_SIZE - byte_offset, byte_len);
  68                sector++;
  69        }
  70
  71        if (byte_len == 0)
  72                return 0;
  73
  74        /*      read sector aligned part */
  75        block_len = byte_len & ~(SECTOR_SIZE - 1);
  76
  77        if (block_len == 0) {
  78                u8 p[SECTOR_SIZE];
  79
  80                block_len = SECTOR_SIZE;
  81                zfs_blk_desc->block_read(zfs_blk_desc,
  82                                         part_info->start + sector,
  83                                         1, (void *)p);
  84                memcpy(buf, p, byte_len);
  85                return 0;
  86        }
  87
  88        if (zfs_blk_desc->block_read(zfs_blk_desc, part_info->start + sector,
  89                                     block_len / SECTOR_SIZE,
  90                                     (void *)buf) != block_len / SECTOR_SIZE) {
  91                printf(" ** zfs_devread() read error - block\n");
  92                return 1;
  93        }
  94
  95        block_len = byte_len & ~(SECTOR_SIZE - 1);
  96        buf += block_len;
  97        byte_len -= block_len;
  98        sector += block_len / SECTOR_SIZE;
  99
 100        if (byte_len != 0) {
 101                /* read rest of data which are not in whole sector */
 102                if (zfs_blk_desc->block_read(zfs_blk_desc,
 103                                             part_info->start + sector,
 104                                             1, (void *)sec_buf) != 1) {
 105                        printf(" ** zfs_devread() read error - last part\n");
 106                        return 1;
 107                }
 108                memcpy(buf, sec_buf, byte_len);
 109        }
 110        return 0;
 111}
 112