Merge branch 'master' of git://git.denx.de/u-boot-ubi

This commit is contained in:
Wolfgang Denk 2010-12-06 23:44:06 +01:00
commit f61f59da0f
4 changed files with 121 additions and 16 deletions

View File

@ -42,6 +42,11 @@ struct selected_dev {
static struct selected_dev ubi_dev;
#ifdef CONFIG_CMD_UBIFS
int ubifs_is_mounted(void);
void cmd_ubifs_umount(void);
#endif
static void ubi_dump_vol_info(const struct ubi_volume *vol)
{
ubi_msg("volume information dump:");
@ -472,6 +477,16 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
if (argc < 3)
return cmd_usage(cmdtp);
#ifdef CONFIG_CMD_UBIFS
/*
* Automatically unmount UBIFS partition when user
* changes the UBI device. Otherwise the following
* UBIFS commands will crash.
*/
if (ubifs_is_mounted())
cmd_ubifs_umount();
#endif
/* todo: get dev number for NAND... */
ubi_dev.nr = 0;

View File

@ -33,12 +33,17 @@
#include <config.h>
#include <command.h>
#include "../fs/ubifs/ubifs.h"
static int ubifs_initialized;
static int ubifs_mounted;
extern struct super_block *ubifs_sb;
/* Prototypes */
int ubifs_init(void);
int ubifs_mount(char *vol_name);
void ubifs_umount(struct ubifs_info *c);
int ubifs_ls(char *dir_name);
int ubifs_load(char *filename, u32 addr, u32 size);
@ -67,13 +72,47 @@ int do_ubifs_mount(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 0;
}
int ubifs_is_mounted(void)
{
return ubifs_mounted;
}
void cmd_ubifs_umount(void)
{
if (ubifs_sb) {
printf("Unmounting UBIFS volume %s!\n",
((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name);
ubifs_umount(ubifs_sb->s_fs_info);
}
ubifs_sb = NULL;
ubifs_mounted = 0;
ubifs_initialized = 0;
}
int do_ubifs_umount(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
if (argc != 1)
return cmd_usage(cmdtp);
if (ubifs_initialized == 0) {
printf("No UBIFS volume mounted!\n");
return -1;
}
cmd_ubifs_umount();
return 0;
}
int do_ubifs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
char *filename = "/";
int ret;
if (!ubifs_mounted) {
printf("UBIFS not mounted, use ubifs mount to mount volume first!\n");
printf("UBIFS not mounted, use ubifsmount to mount volume first!\n");
return -1;
}
@ -131,6 +170,12 @@ U_BOOT_CMD(
" - mount 'volume-name' volume"
);
U_BOOT_CMD(
ubifsumount, 1, 0, do_ubifs_umount,
"unmount UBIFS volume",
" - unmount current volume"
);
U_BOOT_CMD(
ubifsls, 2, 0, do_ubifs_ls,
"list files in a directory",

View File

@ -824,7 +824,7 @@ out_free:
* through mounting (error path cleanup function). So it has to make sure the
* resource was actually allocated before freeing it.
*/
static void ubifs_umount(struct ubifs_info *c)
void ubifs_umount(struct ubifs_info *c)
{
dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num,
c->vi.vol_id);

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2006-2008 Nokia Corporation.
*
* (C) Copyright 2008-2009
* (C) Copyright 2008-2010
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* This program is free software; you can redistribute it and/or modify it
@ -384,6 +384,7 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
unsigned long root_inum = 1;
unsigned long inum;
int symlink_count = 0; /* Don't allow symlink recursion */
char link_name[64];
strcpy(fpath, filename);
@ -420,7 +421,6 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
ui = ubifs_inode(inode);
if ((inode->i_mode & S_IFMT) == S_IFLNK) {
char link_name[64];
char buf[128];
/* We have some sort of symlink recursion, bail out */
@ -567,7 +567,8 @@ dump:
return -EINVAL;
}
static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *page)
static int do_readpage(struct ubifs_info *c, struct inode *inode,
struct page *page, int last_block_size)
{
void *addr;
int err = 0, i;
@ -601,17 +602,54 @@ static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *p
err = -ENOENT;
memset(addr, 0, UBIFS_BLOCK_SIZE);
} else {
ret = read_block(inode, addr, block, dn);
if (ret) {
err = ret;
if (err != -ENOENT)
break;
} else if (block + 1 == beyond) {
int dlen = le32_to_cpu(dn->size);
int ilen = i_size & (UBIFS_BLOCK_SIZE - 1);
/*
* Reading last block? Make sure to not write beyond
* the requested size in the destination buffer.
*/
if (((block + 1) == beyond) || last_block_size) {
void *buff;
int dlen;
if (ilen && ilen < dlen)
memset(addr + ilen, 0, dlen - ilen);
/*
* We need to buffer the data locally for the
* last block. This is to not pad the
* destination area to a multiple of
* UBIFS_BLOCK_SIZE.
*/
buff = malloc(UBIFS_BLOCK_SIZE);
if (!buff) {
printf("%s: Error, malloc fails!\n",
__func__);
err = -ENOMEM;
break;
}
/* Read block-size into temp buffer */
ret = read_block(inode, buff, block, dn);
if (ret) {
err = ret;
if (err != -ENOENT) {
free(buff);
break;
}
}
if (last_block_size)
dlen = last_block_size;
else
dlen = le32_to_cpu(dn->size);
/* Now copy required size back to dest */
memcpy(addr, buff, dlen);
free(buff);
} else {
ret = read_block(inode, addr, block, dn);
if (ret) {
err = ret;
if (err != -ENOENT)
break;
}
}
}
if (++i >= UBIFS_BLOCKS_PER_PAGE)
@ -649,6 +687,7 @@ int ubifs_load(char *filename, u32 addr, u32 size)
int err = 0;
int i;
int count;
int last_block_size = 0;
c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
/* ubifs_findfile will resolve symlinks, so we know that we get
@ -684,7 +723,13 @@ int ubifs_load(char *filename, u32 addr, u32 size)
page.index = 0;
page.inode = inode;
for (i = 0; i < count; i++) {
err = do_readpage(c, inode, &page);
/*
* Make sure to not read beyond the requested size
*/
if (((i + 1) == count) && (size < inode->i_size))
last_block_size = size - (i * PAGE_SIZE);
err = do_readpage(c, inode, &page, last_block_size);
if (err)
break;