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