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