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; 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) static void ubi_dump_vol_info(const struct ubi_volume *vol)
{ {
ubi_msg("volume information dump:"); 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) if (argc < 3)
return cmd_usage(cmdtp); 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... */ /* todo: get dev number for NAND... */
ubi_dev.nr = 0; ubi_dev.nr = 0;

View File

@ -33,12 +33,17 @@
#include <config.h> #include <config.h>
#include <command.h> #include <command.h>
#include "../fs/ubifs/ubifs.h"
static int ubifs_initialized; static int ubifs_initialized;
static int ubifs_mounted; static int ubifs_mounted;
extern struct super_block *ubifs_sb;
/* Prototypes */ /* Prototypes */
int ubifs_init(void); int ubifs_init(void);
int ubifs_mount(char *vol_name); int ubifs_mount(char *vol_name);
void ubifs_umount(struct ubifs_info *c);
int ubifs_ls(char *dir_name); int ubifs_ls(char *dir_name);
int ubifs_load(char *filename, u32 addr, u32 size); 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; 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[]) int do_ubifs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{ {
char *filename = "/"; char *filename = "/";
int ret; int ret;
if (!ubifs_mounted) { 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; return -1;
} }
@ -131,6 +170,12 @@ U_BOOT_CMD(
" - mount 'volume-name' volume" " - mount 'volume-name' volume"
); );
U_BOOT_CMD(
ubifsumount, 1, 0, do_ubifs_umount,
"unmount UBIFS volume",
" - unmount current volume"
);
U_BOOT_CMD( U_BOOT_CMD(
ubifsls, 2, 0, do_ubifs_ls, ubifsls, 2, 0, do_ubifs_ls,
"list files in a directory", "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 * through mounting (error path cleanup function). So it has to make sure the
* resource was actually allocated before freeing it. * 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, dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num,
c->vi.vol_id); c->vi.vol_id);

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2006-2008 Nokia Corporation. * Copyright (C) 2006-2008 Nokia Corporation.
* *
* (C) Copyright 2008-2009 * (C) Copyright 2008-2010
* Stefan Roese, DENX Software Engineering, sr@denx.de. * Stefan Roese, DENX Software Engineering, sr@denx.de.
* *
* This program is free software; you can redistribute it and/or modify it * 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 root_inum = 1;
unsigned long inum; unsigned long inum;
int symlink_count = 0; /* Don't allow symlink recursion */ int symlink_count = 0; /* Don't allow symlink recursion */
char link_name[64];
strcpy(fpath, filename); strcpy(fpath, filename);
@ -420,7 +421,6 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
ui = ubifs_inode(inode); ui = ubifs_inode(inode);
if ((inode->i_mode & S_IFMT) == S_IFLNK) { if ((inode->i_mode & S_IFMT) == S_IFLNK) {
char link_name[64];
char buf[128]; char buf[128];
/* We have some sort of symlink recursion, bail out */ /* We have some sort of symlink recursion, bail out */
@ -567,7 +567,8 @@ dump:
return -EINVAL; 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; void *addr;
int err = 0, i; int err = 0, i;
@ -601,17 +602,54 @@ static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *p
err = -ENOENT; err = -ENOENT;
memset(addr, 0, UBIFS_BLOCK_SIZE); memset(addr, 0, UBIFS_BLOCK_SIZE);
} else { } else {
ret = read_block(inode, addr, block, dn); /*
if (ret) { * Reading last block? Make sure to not write beyond
err = ret; * the requested size in the destination buffer.
if (err != -ENOENT) */
break; if (((block + 1) == beyond) || last_block_size) {
} else if (block + 1 == beyond) { void *buff;
int dlen = le32_to_cpu(dn->size); int dlen;
int ilen = i_size & (UBIFS_BLOCK_SIZE - 1);
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) if (++i >= UBIFS_BLOCKS_PER_PAGE)
@ -649,6 +687,7 @@ int ubifs_load(char *filename, u32 addr, u32 size)
int err = 0; int err = 0;
int i; int i;
int count; int count;
int last_block_size = 0;
c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); 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 /* 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.index = 0;
page.inode = inode; page.inode = inode;
for (i = 0; i < count; i++) { 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) if (err)
break; break;