2012-05-25 15:51:44 +00:00
|
|
|
/*
|
|
|
|
* (C) Copyright 2011 - 2012 Samsung Electronics
|
|
|
|
* EXT4 filesystem implementation in Uboot by
|
|
|
|
* Uma Shankar <uma.shankar@samsung.com>
|
|
|
|
* Manjunatha C Achar <a.manjunatha@samsung.com>
|
|
|
|
*
|
|
|
|
* made from existing ext2/dev.c file of Uboot
|
|
|
|
* (C) Copyright 2004
|
|
|
|
* esd gmbh <www.esd-electronics.com>
|
|
|
|
* Reinhard Arlt <reinhard.arlt@esd-electronics.com>
|
|
|
|
*
|
|
|
|
* based on code of fs/reiserfs/dev.c by
|
|
|
|
*
|
|
|
|
* (C) Copyright 2003 - 2004
|
|
|
|
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
|
|
|
|
*
|
2013-07-08 07:37:19 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0+
|
2012-05-25 15:51:44 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Changelog:
|
|
|
|
* 0.1 - Newly created file for ext4fs support. Taken from
|
|
|
|
* fs/ext2/dev.c file in uboot.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
#include <config.h>
|
2012-08-23 11:31:46 +00:00
|
|
|
#include <ext4fs.h>
|
2012-05-25 15:51:44 +00:00
|
|
|
#include <ext_common.h>
|
2013-05-01 01:13:19 +00:00
|
|
|
#include "ext4_common.h"
|
2012-05-25 15:51:44 +00:00
|
|
|
|
2013-06-26 16:11:25 +00:00
|
|
|
lbaint_t part_offset;
|
2012-08-23 11:31:46 +00:00
|
|
|
|
2012-05-25 15:51:44 +00:00
|
|
|
static block_dev_desc_t *ext4fs_block_dev_desc;
|
2012-08-23 11:31:46 +00:00
|
|
|
static disk_partition_t *part_info;
|
2012-05-25 15:51:44 +00:00
|
|
|
|
2012-08-23 11:31:46 +00:00
|
|
|
void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info)
|
2012-05-25 15:51:44 +00:00
|
|
|
{
|
2013-05-01 01:13:19 +00:00
|
|
|
assert(rbdd->blksz == (1 << rbdd->log2blksz));
|
2012-05-25 15:51:44 +00:00
|
|
|
ext4fs_block_dev_desc = rbdd;
|
2013-05-23 10:22:10 +00:00
|
|
|
get_fs()->dev_desc = rbdd;
|
2012-08-23 11:31:46 +00:00
|
|
|
part_info = info;
|
|
|
|
part_offset = info->start;
|
2014-01-07 22:49:43 +00:00
|
|
|
get_fs()->total_sect = ((uint64_t)info->size * info->blksz) >>
|
2013-05-01 01:13:19 +00:00
|
|
|
get_fs()->dev_desc->log2blksz;
|
2012-05-25 15:51:44 +00:00
|
|
|
}
|
|
|
|
|
2013-06-26 16:11:25 +00:00
|
|
|
int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len, char *buf)
|
2012-05-25 15:51:44 +00:00
|
|
|
{
|
|
|
|
unsigned block_len;
|
2013-05-01 01:13:19 +00:00
|
|
|
int log2blksz = ext4fs_block_dev_desc->log2blksz;
|
|
|
|
ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, (ext4fs_block_dev_desc ?
|
|
|
|
ext4fs_block_dev_desc->blksz :
|
|
|
|
0));
|
|
|
|
if (ext4fs_block_dev_desc == NULL) {
|
|
|
|
printf("** Invalid Block Device Descriptor (NULL)\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2012-05-25 15:51:44 +00:00
|
|
|
|
|
|
|
/* Check partition boundaries */
|
2013-05-01 01:13:19 +00:00
|
|
|
if ((sector < 0) ||
|
|
|
|
((sector + ((byte_offset + byte_len - 1) >> log2blksz))
|
|
|
|
>= part_info->size)) {
|
2013-06-26 16:11:25 +00:00
|
|
|
printf("%s read outside partition " LBAFU "\n", __func__,
|
|
|
|
sector);
|
2012-05-25 15:51:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the read to the beginning of a partition */
|
2013-05-01 01:13:19 +00:00
|
|
|
sector += byte_offset >> log2blksz;
|
|
|
|
byte_offset &= ext4fs_block_dev_desc->blksz - 1;
|
2012-05-25 15:51:44 +00:00
|
|
|
|
2013-06-26 16:11:25 +00:00
|
|
|
debug(" <" LBAFU ", %d, %d>\n", sector, byte_offset, byte_len);
|
2012-05-25 15:51:44 +00:00
|
|
|
|
|
|
|
if (byte_offset != 0) {
|
linux/kernel.h: sync min, max, min3, max3 macros with Linux
U-Boot has never cared about the type when we get max/min of two
values, but Linux Kernel does. This commit gets min, max, min3, max3
macros synced with the kernel introducing type checks.
Many of references of those macros must be fixed to suppress warnings.
We have two options:
- Use min, max, min3, max3 only when the arguments have the same type
(or add casts to the arguments)
- Use min_t/max_t instead with the appropriate type for the first
argument
Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
Acked-by: Pavel Machek <pavel@denx.de>
Acked-by: Lukasz Majewski <l.majewski@samsung.com>
Tested-by: Lukasz Majewski <l.majewski@samsung.com>
[trini: Fixup arch/blackfin/lib/string.c]
Signed-off-by: Tom Rini <trini@ti.com>
2014-11-06 18:03:31 +00:00
|
|
|
int readlen;
|
2012-05-25 15:51:44 +00:00
|
|
|
/* read first part which isn't aligned with start of sector */
|
|
|
|
if (ext4fs_block_dev_desc->
|
|
|
|
block_read(ext4fs_block_dev_desc->dev,
|
2012-08-23 11:31:46 +00:00
|
|
|
part_info->start + sector, 1,
|
2012-05-25 15:51:44 +00:00
|
|
|
(unsigned long *) sec_buf) != 1) {
|
|
|
|
printf(" ** ext2fs_devread() read error **\n");
|
|
|
|
return 0;
|
|
|
|
}
|
linux/kernel.h: sync min, max, min3, max3 macros with Linux
U-Boot has never cared about the type when we get max/min of two
values, but Linux Kernel does. This commit gets min, max, min3, max3
macros synced with the kernel introducing type checks.
Many of references of those macros must be fixed to suppress warnings.
We have two options:
- Use min, max, min3, max3 only when the arguments have the same type
(or add casts to the arguments)
- Use min_t/max_t instead with the appropriate type for the first
argument
Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
Acked-by: Pavel Machek <pavel@denx.de>
Acked-by: Lukasz Majewski <l.majewski@samsung.com>
Tested-by: Lukasz Majewski <l.majewski@samsung.com>
[trini: Fixup arch/blackfin/lib/string.c]
Signed-off-by: Tom Rini <trini@ti.com>
2014-11-06 18:03:31 +00:00
|
|
|
readlen = min((int)ext4fs_block_dev_desc->blksz - byte_offset,
|
|
|
|
byte_len);
|
|
|
|
memcpy(buf, sec_buf + byte_offset, readlen);
|
|
|
|
buf += readlen;
|
|
|
|
byte_len -= readlen;
|
2012-05-25 15:51:44 +00:00
|
|
|
sector++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (byte_len == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* read sector aligned part */
|
2013-05-01 01:13:19 +00:00
|
|
|
block_len = byte_len & ~(ext4fs_block_dev_desc->blksz - 1);
|
2012-05-25 15:51:44 +00:00
|
|
|
|
|
|
|
if (block_len == 0) {
|
2013-05-01 01:13:19 +00:00
|
|
|
ALLOC_CACHE_ALIGN_BUFFER(u8, p, ext4fs_block_dev_desc->blksz);
|
2012-05-25 15:51:44 +00:00
|
|
|
|
2013-05-01 01:13:19 +00:00
|
|
|
block_len = ext4fs_block_dev_desc->blksz;
|
2012-05-25 15:51:44 +00:00
|
|
|
ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev,
|
2012-08-23 11:31:46 +00:00
|
|
|
part_info->start + sector,
|
2012-05-25 15:51:44 +00:00
|
|
|
1, (unsigned long *)p);
|
|
|
|
memcpy(buf, p, byte_len);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev,
|
2012-08-23 11:31:46 +00:00
|
|
|
part_info->start + sector,
|
2013-05-01 01:13:19 +00:00
|
|
|
block_len >> log2blksz,
|
2012-05-25 15:51:44 +00:00
|
|
|
(unsigned long *) buf) !=
|
2013-05-01 01:13:19 +00:00
|
|
|
block_len >> log2blksz) {
|
2012-05-25 15:51:44 +00:00
|
|
|
printf(" ** %s read error - block\n", __func__);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-05-01 01:13:19 +00:00
|
|
|
block_len = byte_len & ~(ext4fs_block_dev_desc->blksz - 1);
|
2012-05-25 15:51:44 +00:00
|
|
|
buf += block_len;
|
|
|
|
byte_len -= block_len;
|
2013-05-01 01:13:19 +00:00
|
|
|
sector += block_len / ext4fs_block_dev_desc->blksz;
|
2012-05-25 15:51:44 +00:00
|
|
|
|
|
|
|
if (byte_len != 0) {
|
|
|
|
/* read rest of data which are not in whole sector */
|
|
|
|
if (ext4fs_block_dev_desc->
|
|
|
|
block_read(ext4fs_block_dev_desc->dev,
|
2012-08-23 11:31:46 +00:00
|
|
|
part_info->start + sector, 1,
|
2012-05-25 15:51:44 +00:00
|
|
|
(unsigned long *) sec_buf) != 1) {
|
|
|
|
printf("* %s read error - last part\n", __func__);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
memcpy(buf, sec_buf, byte_len);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2013-05-01 01:13:19 +00:00
|
|
|
|
|
|
|
int ext4_read_superblock(char *buffer)
|
|
|
|
{
|
|
|
|
struct ext_filesystem *fs = get_fs();
|
|
|
|
int sect = SUPERBLOCK_START >> fs->dev_desc->log2blksz;
|
|
|
|
int off = SUPERBLOCK_START % fs->dev_desc->blksz;
|
|
|
|
|
|
|
|
return ext4fs_devread(sect, off, SUPERBLOCK_SIZE,
|
|
|
|
buffer);
|
|
|
|
}
|