]>
Commit | Line | Data |
---|---|---|
4d3c95f5 JL |
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 | * | |
1a459660 | 8 | * SPDX-License-Identifier: GPL-2.0+ |
4d3c95f5 JL |
9 | */ |
10 | ||
11 | ||
12 | #include <common.h> | |
13 | #include <config.h> | |
14 | #include <zfs_common.h> | |
15 | ||
4101f687 | 16 | static struct blk_desc *zfs_blk_desc; |
41204570 | 17 | static disk_partition_t *part_info; |
4d3c95f5 | 18 | |
4101f687 | 19 | void zfs_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info) |
4d3c95f5 | 20 | { |
4101f687 | 21 | zfs_blk_desc = rbdd; |
41204570 | 22 | part_info = info; |
4d3c95f5 JL |
23 | } |
24 | ||
25 | /* err */ | |
26 | int 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)) >= | |
41204570 | 37 | part_info->size)) { |
4d3c95f5 JL |
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 | ||
4101f687 | 51 | if (zfs_blk_desc == NULL) { |
4d3c95f5 JL |
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 */ | |
4101f687 SG |
58 | if (zfs_blk_desc->block_read(zfs_blk_desc, |
59 | part_info->start + sector, 1, | |
60 | (void *)sec_buf) != 1) { | |
4d3c95f5 JL |
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; | |
4101f687 SG |
81 | zfs_blk_desc->block_read(zfs_blk_desc, |
82 | part_info->start + sector, | |
83 | 1, (void *)p); | |
4d3c95f5 JL |
84 | memcpy(buf, p, byte_len); |
85 | return 0; | |
86 | } | |
87 | ||
4101f687 SG |
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) { | |
4d3c95f5 JL |
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 */ | |
4101f687 SG |
102 | if (zfs_blk_desc->block_read(zfs_blk_desc, |
103 | part_info->start + sector, | |
104 | 1, (void *)sec_buf) != 1) { | |
4d3c95f5 JL |
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 | } |