]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
5994e8b6 MB |
2 | /* |
3 | * 2017 by Marek Behun <[email protected]> | |
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) { | |
0d32d8cf HS |
32 | log_err("%s read outside partition " LBAFU "\n", __func__, |
33 | sector); | |
5994e8b6 MB |
34 | return 0; |
35 | } | |
36 | ||
37 | /* Get the read to the beginning of a partition */ | |
38 | sector += byte_offset >> log2blksz; | |
39 | byte_offset &= blk->blksz - 1; | |
40 | ||
0d32d8cf | 41 | log_debug(" <" LBAFU ", %d, %d>\n", sector, byte_offset, byte_len); |
5994e8b6 MB |
42 | |
43 | if (byte_offset != 0) { | |
44 | int readlen; | |
45 | /* read first part which isn't aligned with start of sector */ | |
46 | if (blk_dread(blk, partition->start + sector, 1, | |
47 | (void *)sec_buf) != 1) { | |
0d32d8cf | 48 | log_err(" ** %s read error **\n", __func__); |
5994e8b6 MB |
49 | return 0; |
50 | } | |
51 | readlen = min((int)blk->blksz - byte_offset, | |
52 | byte_len); | |
53 | memcpy(buf, sec_buf + byte_offset, readlen); | |
54 | buf += readlen; | |
55 | byte_len -= readlen; | |
56 | sector++; | |
57 | } | |
58 | ||
59 | if (byte_len == 0) | |
60 | return 1; | |
61 | ||
62 | /* read sector aligned part */ | |
63 | block_len = byte_len & ~(blk->blksz - 1); | |
64 | ||
65 | if (block_len == 0) { | |
66 | ALLOC_CACHE_ALIGN_BUFFER(u8, p, blk->blksz); | |
67 | ||
68 | block_len = blk->blksz; | |
69 | blk_dread(blk, partition->start + sector, 1, | |
70 | (void *)p); | |
71 | memcpy(buf, p, byte_len); | |
72 | return 1; | |
73 | } | |
74 | ||
75 | if (blk_dread(blk, partition->start + sector, | |
76 | block_len >> log2blksz, (void *)buf) != | |
77 | block_len >> log2blksz) { | |
0d32d8cf | 78 | log_err(" ** %s read error - block\n", __func__); |
5994e8b6 MB |
79 | return 0; |
80 | } | |
81 | block_len = byte_len & ~(blk->blksz - 1); | |
82 | buf += block_len; | |
83 | byte_len -= block_len; | |
84 | sector += block_len / blk->blksz; | |
85 | ||
86 | if (byte_len != 0) { | |
87 | /* read rest of data which are not in whole sector */ | |
88 | if (blk_dread(blk, partition->start + sector, 1, | |
89 | (void *)sec_buf) != 1) { | |
0d32d8cf | 90 | log_err("* %s read error - last part\n", __func__); |
5994e8b6 MB |
91 | return 0; |
92 | } | |
93 | memcpy(buf, sec_buf, byte_len); | |
94 | } | |
95 | return 1; | |
96 | } |