]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
5994e8b6 | 2 | /* |
61143f74 | 3 | * 2017 by Marek Behún <kabel@kernel.org> |
5994e8b6 MB |
4 | * |
5 | * Derived from code in ext4/dev.c, which was based on reiserfs/dev.c | |
5994e8b6 MB |
6 | */ |
7 | ||
0d32d8cf HS |
8 | #define LOG_CATEGORY LOGC_CORE |
9 | ||
5994e8b6 | 10 | #include <common.h> |
e6f6f9e6 | 11 | #include <blk.h> |
5994e8b6 | 12 | #include <compiler.h> |
f7ae49fc | 13 | #include <log.h> |
5994e8b6 MB |
14 | #include <part.h> |
15 | #include <memalign.h> | |
16 | ||
0528979f | 17 | int fs_devread(struct blk_desc *blk, struct disk_partition *partition, |
5994e8b6 MB |
18 | lbaint_t sector, int byte_offset, int byte_len, char *buf) |
19 | { | |
20 | unsigned block_len; | |
24f48416 | 21 | int log2blksz; |
5994e8b6 MB |
22 | ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, (blk ? blk->blksz : 0)); |
23 | if (blk == NULL) { | |
0d32d8cf | 24 | log_err("** Invalid Block Device Descriptor (NULL)\n"); |
5994e8b6 MB |
25 | return 0; |
26 | } | |
24f48416 | 27 | log2blksz = blk->log2blksz; |
5994e8b6 MB |
28 | |
29 | /* Check partition boundaries */ | |
30 | if ((sector + ((byte_offset + byte_len - 1) >> log2blksz)) | |
31 | >= partition->size) { | |
f337fb9e | 32 | log_debug("read outside partition " LBAFU "\n", sector); |
5994e8b6 MB |
33 | return 0; |
34 | } | |
35 | ||
36 | /* Get the read to the beginning of a partition */ | |
37 | sector += byte_offset >> log2blksz; | |
38 | byte_offset &= blk->blksz - 1; | |
39 | ||
0d32d8cf | 40 | log_debug(" <" LBAFU ", %d, %d>\n", sector, byte_offset, byte_len); |
5994e8b6 MB |
41 | |
42 | if (byte_offset != 0) { | |
43 | int readlen; | |
44 | /* read first part which isn't aligned with start of sector */ | |
45 | if (blk_dread(blk, partition->start + sector, 1, | |
46 | (void *)sec_buf) != 1) { | |
0d32d8cf | 47 | log_err(" ** %s read error **\n", __func__); |
5994e8b6 MB |
48 | return 0; |
49 | } | |
50 | readlen = min((int)blk->blksz - byte_offset, | |
51 | byte_len); | |
52 | memcpy(buf, sec_buf + byte_offset, readlen); | |
53 | buf += readlen; | |
54 | byte_len -= readlen; | |
55 | sector++; | |
56 | } | |
57 | ||
58 | if (byte_len == 0) | |
59 | return 1; | |
60 | ||
61 | /* read sector aligned part */ | |
62 | block_len = byte_len & ~(blk->blksz - 1); | |
63 | ||
64 | if (block_len == 0) { | |
65 | ALLOC_CACHE_ALIGN_BUFFER(u8, p, blk->blksz); | |
66 | ||
67 | block_len = blk->blksz; | |
68 | blk_dread(blk, partition->start + sector, 1, | |
69 | (void *)p); | |
70 | memcpy(buf, p, byte_len); | |
71 | return 1; | |
72 | } | |
73 | ||
74 | if (blk_dread(blk, partition->start + sector, | |
75 | block_len >> log2blksz, (void *)buf) != | |
76 | block_len >> log2blksz) { | |
0d32d8cf | 77 | log_err(" ** %s read error - block\n", __func__); |
5994e8b6 MB |
78 | return 0; |
79 | } | |
80 | block_len = byte_len & ~(blk->blksz - 1); | |
81 | buf += block_len; | |
82 | byte_len -= block_len; | |
83 | sector += block_len / blk->blksz; | |
84 | ||
85 | if (byte_len != 0) { | |
86 | /* read rest of data which are not in whole sector */ | |
87 | if (blk_dread(blk, partition->start + sector, 1, | |
88 | (void *)sec_buf) != 1) { | |
0d32d8cf | 89 | log_err("* %s read error - last part\n", __func__); |
5994e8b6 MB |
90 | return 0; |
91 | } | |
92 | memcpy(buf, sec_buf, byte_len); | |
93 | } | |
94 | return 1; | |
95 | } |