183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
29eefe2a2SStefan Roese /*
39eefe2a2SStefan Roese * This file is part of UBIFS.
49eefe2a2SStefan Roese *
59eefe2a2SStefan Roese * Copyright (C) 2006-2008 Nokia Corporation.
69eefe2a2SStefan Roese *
7b1a14f8aSStefan Roese * (C) Copyright 2008-2010
89eefe2a2SStefan Roese * Stefan Roese, DENX Software Engineering, sr@denx.de.
99eefe2a2SStefan Roese *
109eefe2a2SStefan Roese * Authors: Artem Bityutskiy (Битюцкий Артём)
119eefe2a2SStefan Roese * Adrian Hunter
129eefe2a2SStefan Roese */
139eefe2a2SStefan Roese
146e295186SSimon Glass #include <common.h>
156e295186SSimon Glass #include <memalign.h>
169eefe2a2SStefan Roese #include "ubifs.h"
17c1a0fd5fSRicardo Ribalda Delgado #include <u-boot/zlib.h>
189eefe2a2SStefan Roese
19ff94bc40SHeiko Schocher #include <linux/err.h>
20ff94bc40SHeiko Schocher #include <linux/lzo.h>
21ff94bc40SHeiko Schocher
229eefe2a2SStefan Roese DECLARE_GLOBAL_DATA_PTR;
239eefe2a2SStefan Roese
249eefe2a2SStefan Roese /* compress.c */
259eefe2a2SStefan Roese
269eefe2a2SStefan Roese /*
27c1a0fd5fSRicardo Ribalda Delgado * We need a wrapper for zunzip() because the parameters are
289eefe2a2SStefan Roese * incompatible with the lzo decompressor.
299eefe2a2SStefan Roese */
gzip_decompress(const unsigned char * in,size_t in_len,unsigned char * out,size_t * out_len)309eefe2a2SStefan Roese static int gzip_decompress(const unsigned char *in, size_t in_len,
319eefe2a2SStefan Roese unsigned char *out, size_t *out_len)
329eefe2a2SStefan Roese {
338044c138SVeli-Pekka Peltola return zunzip(out, *out_len, (unsigned char *)in,
348044c138SVeli-Pekka Peltola (unsigned long *)out_len, 0, 0);
359eefe2a2SStefan Roese }
369eefe2a2SStefan Roese
379eefe2a2SStefan Roese /* Fake description object for the "none" compressor */
389eefe2a2SStefan Roese static struct ubifs_compressor none_compr = {
399eefe2a2SStefan Roese .compr_type = UBIFS_COMPR_NONE,
40ff94bc40SHeiko Schocher .name = "none",
419eefe2a2SStefan Roese .capi_name = "",
429eefe2a2SStefan Roese .decompress = NULL,
439eefe2a2SStefan Roese };
449eefe2a2SStefan Roese
459eefe2a2SStefan Roese static struct ubifs_compressor lzo_compr = {
469eefe2a2SStefan Roese .compr_type = UBIFS_COMPR_LZO,
47ff94bc40SHeiko Schocher #ifndef __UBOOT__
48ff94bc40SHeiko Schocher .comp_mutex = &lzo_mutex,
49ff94bc40SHeiko Schocher #endif
50ff94bc40SHeiko Schocher .name = "lzo",
519eefe2a2SStefan Roese .capi_name = "lzo",
529eefe2a2SStefan Roese .decompress = lzo1x_decompress_safe,
539eefe2a2SStefan Roese };
549eefe2a2SStefan Roese
559eefe2a2SStefan Roese static struct ubifs_compressor zlib_compr = {
569eefe2a2SStefan Roese .compr_type = UBIFS_COMPR_ZLIB,
57ff94bc40SHeiko Schocher #ifndef __UBOOT__
58ff94bc40SHeiko Schocher .comp_mutex = &deflate_mutex,
59ff94bc40SHeiko Schocher .decomp_mutex = &inflate_mutex,
60ff94bc40SHeiko Schocher #endif
619eefe2a2SStefan Roese .name = "zlib",
629eefe2a2SStefan Roese .capi_name = "deflate",
639eefe2a2SStefan Roese .decompress = gzip_decompress,
649eefe2a2SStefan Roese };
659eefe2a2SStefan Roese
669eefe2a2SStefan Roese /* All UBIFS compressors */
679eefe2a2SStefan Roese struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
689eefe2a2SStefan Roese
69ff94bc40SHeiko Schocher
70ff94bc40SHeiko Schocher #ifdef __UBOOT__
71ff94bc40SHeiko Schocher /* from mm/util.c */
72ff94bc40SHeiko Schocher
73ff94bc40SHeiko Schocher /**
74ff94bc40SHeiko Schocher * kmemdup - duplicate region of memory
75ff94bc40SHeiko Schocher *
76ff94bc40SHeiko Schocher * @src: memory region to duplicate
77ff94bc40SHeiko Schocher * @len: memory region length
78ff94bc40SHeiko Schocher * @gfp: GFP mask to use
79ff94bc40SHeiko Schocher */
kmemdup(const void * src,size_t len,gfp_t gfp)80ff94bc40SHeiko Schocher void *kmemdup(const void *src, size_t len, gfp_t gfp)
81ff94bc40SHeiko Schocher {
82ff94bc40SHeiko Schocher void *p;
83ff94bc40SHeiko Schocher
84ff94bc40SHeiko Schocher p = kmalloc(len, gfp);
85ff94bc40SHeiko Schocher if (p)
86ff94bc40SHeiko Schocher memcpy(p, src, len);
87ff94bc40SHeiko Schocher return p;
88ff94bc40SHeiko Schocher }
89ff94bc40SHeiko Schocher
90ff94bc40SHeiko Schocher struct crypto_comp {
91ff94bc40SHeiko Schocher int compressor;
92ff94bc40SHeiko Schocher };
93ff94bc40SHeiko Schocher
940195a7bbSHeiko Schocher static inline struct crypto_comp
crypto_alloc_comp(const char * alg_name,u32 type,u32 mask)950195a7bbSHeiko Schocher *crypto_alloc_comp(const char *alg_name, u32 type, u32 mask)
96ff94bc40SHeiko Schocher {
97ff94bc40SHeiko Schocher struct ubifs_compressor *comp;
98ff94bc40SHeiko Schocher struct crypto_comp *ptr;
99ff94bc40SHeiko Schocher int i = 0;
100ff94bc40SHeiko Schocher
1014519668bSMarcel Ziswiler ptr = malloc_cache_aligned(sizeof(struct crypto_comp));
102ff94bc40SHeiko Schocher while (i < UBIFS_COMPR_TYPES_CNT) {
103ff94bc40SHeiko Schocher comp = ubifs_compressors[i];
104ff94bc40SHeiko Schocher if (!comp) {
105ff94bc40SHeiko Schocher i++;
106ff94bc40SHeiko Schocher continue;
107ff94bc40SHeiko Schocher }
108ff94bc40SHeiko Schocher if (strncmp(alg_name, comp->capi_name, strlen(alg_name)) == 0) {
109ff94bc40SHeiko Schocher ptr->compressor = i;
110ff94bc40SHeiko Schocher return ptr;
111ff94bc40SHeiko Schocher }
112ff94bc40SHeiko Schocher i++;
113ff94bc40SHeiko Schocher }
114ff94bc40SHeiko Schocher if (i >= UBIFS_COMPR_TYPES_CNT) {
1150195a7bbSHeiko Schocher dbg_gen("invalid compression type %s", alg_name);
116ff94bc40SHeiko Schocher free (ptr);
117ff94bc40SHeiko Schocher return NULL;
118ff94bc40SHeiko Schocher }
119ff94bc40SHeiko Schocher return ptr;
120ff94bc40SHeiko Schocher }
1210195a7bbSHeiko Schocher static inline int
crypto_comp_decompress(const struct ubifs_info * c,struct crypto_comp * tfm,const u8 * src,unsigned int slen,u8 * dst,unsigned int * dlen)1220195a7bbSHeiko Schocher crypto_comp_decompress(const struct ubifs_info *c, struct crypto_comp *tfm,
1230195a7bbSHeiko Schocher const u8 *src, unsigned int slen, u8 *dst,
1240195a7bbSHeiko Schocher unsigned int *dlen)
125ff94bc40SHeiko Schocher {
126ff94bc40SHeiko Schocher struct ubifs_compressor *compr = ubifs_compressors[tfm->compressor];
127ff94bc40SHeiko Schocher int err;
128*e4aa10baSPaul Davey size_t tmp_len = *dlen;
129ff94bc40SHeiko Schocher
130ff94bc40SHeiko Schocher if (compr->compr_type == UBIFS_COMPR_NONE) {
131ff94bc40SHeiko Schocher memcpy(dst, src, slen);
132ff94bc40SHeiko Schocher *dlen = slen;
133ff94bc40SHeiko Schocher return 0;
134ff94bc40SHeiko Schocher }
135ff94bc40SHeiko Schocher
136*e4aa10baSPaul Davey err = compr->decompress(src, slen, dst, &tmp_len);
137ff94bc40SHeiko Schocher if (err)
1380195a7bbSHeiko Schocher ubifs_err(c, "cannot decompress %d bytes, compressor %s, "
139ff94bc40SHeiko Schocher "error %d", slen, compr->name, err);
140ff94bc40SHeiko Schocher
141*e4aa10baSPaul Davey *dlen = tmp_len;
142ff94bc40SHeiko Schocher return err;
143ff94bc40SHeiko Schocher
144ff94bc40SHeiko Schocher return 0;
145ff94bc40SHeiko Schocher }
146dc288431SAnton Habegger
147dc288431SAnton Habegger /* from shrinker.c */
148dc288431SAnton Habegger
149dc288431SAnton Habegger /* Global clean znode counter (for all mounted UBIFS instances) */
150dc288431SAnton Habegger atomic_long_t ubifs_clean_zn_cnt;
151dc288431SAnton Habegger
152ff94bc40SHeiko Schocher #endif
153ff94bc40SHeiko Schocher
1549eefe2a2SStefan Roese /**
1559eefe2a2SStefan Roese * ubifs_decompress - decompress data.
1569eefe2a2SStefan Roese * @in_buf: data to decompress
1579eefe2a2SStefan Roese * @in_len: length of the data to decompress
1589eefe2a2SStefan Roese * @out_buf: output buffer where decompressed data should
1599eefe2a2SStefan Roese * @out_len: output length is returned here
1609eefe2a2SStefan Roese * @compr_type: type of compression
1619eefe2a2SStefan Roese *
1629eefe2a2SStefan Roese * This function decompresses data from buffer @in_buf into buffer @out_buf.
1639eefe2a2SStefan Roese * The length of the uncompressed data is returned in @out_len. This functions
1649eefe2a2SStefan Roese * returns %0 on success or a negative error code on failure.
1659eefe2a2SStefan Roese */
ubifs_decompress(const struct ubifs_info * c,const void * in_buf,int in_len,void * out_buf,int * out_len,int compr_type)1660195a7bbSHeiko Schocher int ubifs_decompress(const struct ubifs_info *c, const void *in_buf,
1670195a7bbSHeiko Schocher int in_len, void *out_buf, int *out_len, int compr_type)
1689eefe2a2SStefan Roese {
1699eefe2a2SStefan Roese int err;
1709eefe2a2SStefan Roese struct ubifs_compressor *compr;
1719eefe2a2SStefan Roese
1729eefe2a2SStefan Roese if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
1730195a7bbSHeiko Schocher ubifs_err(c, "invalid compression type %d", compr_type);
1749eefe2a2SStefan Roese return -EINVAL;
1759eefe2a2SStefan Roese }
1769eefe2a2SStefan Roese
1779eefe2a2SStefan Roese compr = ubifs_compressors[compr_type];
1789eefe2a2SStefan Roese
1799eefe2a2SStefan Roese if (unlikely(!compr->capi_name)) {
1800195a7bbSHeiko Schocher ubifs_err(c, "%s compression is not compiled in", compr->name);
1819eefe2a2SStefan Roese return -EINVAL;
1829eefe2a2SStefan Roese }
1839eefe2a2SStefan Roese
1849eefe2a2SStefan Roese if (compr_type == UBIFS_COMPR_NONE) {
1859eefe2a2SStefan Roese memcpy(out_buf, in_buf, in_len);
1869eefe2a2SStefan Roese *out_len = in_len;
1879eefe2a2SStefan Roese return 0;
1889eefe2a2SStefan Roese }
1899eefe2a2SStefan Roese
190ff94bc40SHeiko Schocher if (compr->decomp_mutex)
191ff94bc40SHeiko Schocher mutex_lock(compr->decomp_mutex);
1920195a7bbSHeiko Schocher err = crypto_comp_decompress(c, compr->cc, in_buf, in_len, out_buf,
193ff94bc40SHeiko Schocher (unsigned int *)out_len);
194ff94bc40SHeiko Schocher if (compr->decomp_mutex)
195ff94bc40SHeiko Schocher mutex_unlock(compr->decomp_mutex);
1969eefe2a2SStefan Roese if (err)
1970195a7bbSHeiko Schocher ubifs_err(c, "cannot decompress %d bytes, compressor %s,"
1980195a7bbSHeiko Schocher " error %d", in_len, compr->name, err);
1999eefe2a2SStefan Roese
2009eefe2a2SStefan Roese return err;
2019eefe2a2SStefan Roese }
2029eefe2a2SStefan Roese
2039eefe2a2SStefan Roese /**
2049eefe2a2SStefan Roese * compr_init - initialize a compressor.
2059eefe2a2SStefan Roese * @compr: compressor description object
2069eefe2a2SStefan Roese *
2079eefe2a2SStefan Roese * This function initializes the requested compressor and returns zero in case
2089eefe2a2SStefan Roese * of success or a negative error code in case of failure.
2099eefe2a2SStefan Roese */
compr_init(struct ubifs_compressor * compr)2109eefe2a2SStefan Roese static int __init compr_init(struct ubifs_compressor *compr)
2119eefe2a2SStefan Roese {
2129eefe2a2SStefan Roese ubifs_compressors[compr->compr_type] = compr;
213521af04dSPeter Tyser
2142e5167ccSWolfgang Denk #ifdef CONFIG_NEEDS_MANUAL_RELOC
2159eefe2a2SStefan Roese ubifs_compressors[compr->compr_type]->name += gd->reloc_off;
2169eefe2a2SStefan Roese ubifs_compressors[compr->compr_type]->capi_name += gd->reloc_off;
2179eefe2a2SStefan Roese ubifs_compressors[compr->compr_type]->decompress += gd->reloc_off;
218521af04dSPeter Tyser #endif
219521af04dSPeter Tyser
220ff94bc40SHeiko Schocher if (compr->capi_name) {
221ff94bc40SHeiko Schocher compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
222ff94bc40SHeiko Schocher if (IS_ERR(compr->cc)) {
2230195a7bbSHeiko Schocher dbg_gen("cannot initialize compressor %s,"
2240195a7bbSHeiko Schocher " error %ld", compr->name,
2250195a7bbSHeiko Schocher PTR_ERR(compr->cc));
226ff94bc40SHeiko Schocher return PTR_ERR(compr->cc);
227ff94bc40SHeiko Schocher }
228ff94bc40SHeiko Schocher }
229ff94bc40SHeiko Schocher
2309eefe2a2SStefan Roese return 0;
2319eefe2a2SStefan Roese }
2329eefe2a2SStefan Roese
2339eefe2a2SStefan Roese /**
2349eefe2a2SStefan Roese * ubifs_compressors_init - initialize UBIFS compressors.
2359eefe2a2SStefan Roese *
2369eefe2a2SStefan Roese * This function initializes the compressor which were compiled in. Returns
2379eefe2a2SStefan Roese * zero in case of success and a negative error code in case of failure.
2389eefe2a2SStefan Roese */
ubifs_compressors_init(void)2399eefe2a2SStefan Roese int __init ubifs_compressors_init(void)
2409eefe2a2SStefan Roese {
2419eefe2a2SStefan Roese int err;
2429eefe2a2SStefan Roese
2439eefe2a2SStefan Roese err = compr_init(&lzo_compr);
2449eefe2a2SStefan Roese if (err)
2459eefe2a2SStefan Roese return err;
2469eefe2a2SStefan Roese
2479eefe2a2SStefan Roese err = compr_init(&zlib_compr);
2489eefe2a2SStefan Roese if (err)
2499eefe2a2SStefan Roese return err;
2509eefe2a2SStefan Roese
251faac4fd8SMichael Lawnick err = compr_init(&none_compr);
252faac4fd8SMichael Lawnick if (err)
253faac4fd8SMichael Lawnick return err;
254faac4fd8SMichael Lawnick
2559eefe2a2SStefan Roese return 0;
2569eefe2a2SStefan Roese }
2579eefe2a2SStefan Roese
2589eefe2a2SStefan Roese /*
2599eefe2a2SStefan Roese * ubifsls...
2609eefe2a2SStefan Roese */
2619eefe2a2SStefan Roese
filldir(struct ubifs_info * c,const char * name,int namlen,u64 ino,unsigned int d_type)2629eefe2a2SStefan Roese static int filldir(struct ubifs_info *c, const char *name, int namlen,
2639eefe2a2SStefan Roese u64 ino, unsigned int d_type)
2649eefe2a2SStefan Roese {
2659eefe2a2SStefan Roese struct inode *inode;
2669eefe2a2SStefan Roese char filetime[32];
2679eefe2a2SStefan Roese
2689eefe2a2SStefan Roese switch (d_type) {
2699eefe2a2SStefan Roese case UBIFS_ITYPE_REG:
2709eefe2a2SStefan Roese printf("\t");
2719eefe2a2SStefan Roese break;
2729eefe2a2SStefan Roese case UBIFS_ITYPE_DIR:
2739eefe2a2SStefan Roese printf("<DIR>\t");
2749eefe2a2SStefan Roese break;
2759eefe2a2SStefan Roese case UBIFS_ITYPE_LNK:
2769eefe2a2SStefan Roese printf("<LNK>\t");
2779eefe2a2SStefan Roese break;
2789eefe2a2SStefan Roese default:
2799eefe2a2SStefan Roese printf("other\t");
2809eefe2a2SStefan Roese break;
2819eefe2a2SStefan Roese }
2829eefe2a2SStefan Roese
2839eefe2a2SStefan Roese inode = ubifs_iget(c->vfs_sb, ino);
2849eefe2a2SStefan Roese if (IS_ERR(inode)) {
2859eefe2a2SStefan Roese printf("%s: Error in ubifs_iget(), ino=%lld ret=%p!\n",
2869eefe2a2SStefan Roese __func__, ino, inode);
2879eefe2a2SStefan Roese return -1;
2889eefe2a2SStefan Roese }
2899eefe2a2SStefan Roese ctime_r((time_t *)&inode->i_mtime, filetime);
2909eefe2a2SStefan Roese printf("%9lld %24.24s ", inode->i_size, filetime);
291ff94bc40SHeiko Schocher #ifndef __UBOOT__
2929eefe2a2SStefan Roese ubifs_iput(inode);
293ff94bc40SHeiko Schocher #endif
2949eefe2a2SStefan Roese
2959eefe2a2SStefan Roese printf("%s\n", name);
2969eefe2a2SStefan Roese
2979eefe2a2SStefan Roese return 0;
2989eefe2a2SStefan Roese }
2999eefe2a2SStefan Roese
ubifs_printdir(struct file * file,void * dirent)3009eefe2a2SStefan Roese static int ubifs_printdir(struct file *file, void *dirent)
3019eefe2a2SStefan Roese {
3029eefe2a2SStefan Roese int err, over = 0;
3039eefe2a2SStefan Roese struct qstr nm;
3049eefe2a2SStefan Roese union ubifs_key key;
3059eefe2a2SStefan Roese struct ubifs_dent_node *dent;
3069eefe2a2SStefan Roese struct inode *dir = file->f_path.dentry->d_inode;
3079eefe2a2SStefan Roese struct ubifs_info *c = dir->i_sb->s_fs_info;
3089eefe2a2SStefan Roese
3099eefe2a2SStefan Roese dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
3109eefe2a2SStefan Roese
3119eefe2a2SStefan Roese if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
3129eefe2a2SStefan Roese /*
3139eefe2a2SStefan Roese * The directory was seek'ed to a senseless position or there
3149eefe2a2SStefan Roese * are no more entries.
3159eefe2a2SStefan Roese */
3169eefe2a2SStefan Roese return 0;
3179eefe2a2SStefan Roese
3189eefe2a2SStefan Roese if (file->f_pos == 1) {
3199eefe2a2SStefan Roese /* Find the first entry in TNC and save it */
3209eefe2a2SStefan Roese lowest_dent_key(c, &key, dir->i_ino);
3219eefe2a2SStefan Roese nm.name = NULL;
3229eefe2a2SStefan Roese dent = ubifs_tnc_next_ent(c, &key, &nm);
3239eefe2a2SStefan Roese if (IS_ERR(dent)) {
3249eefe2a2SStefan Roese err = PTR_ERR(dent);
3259eefe2a2SStefan Roese goto out;
3269eefe2a2SStefan Roese }
3279eefe2a2SStefan Roese
3289eefe2a2SStefan Roese file->f_pos = key_hash_flash(c, &dent->key);
3299eefe2a2SStefan Roese file->private_data = dent;
3309eefe2a2SStefan Roese }
3319eefe2a2SStefan Roese
3329eefe2a2SStefan Roese dent = file->private_data;
3339eefe2a2SStefan Roese if (!dent) {
3349eefe2a2SStefan Roese /*
3359eefe2a2SStefan Roese * The directory was seek'ed to and is now readdir'ed.
3369eefe2a2SStefan Roese * Find the entry corresponding to @file->f_pos or the
3379eefe2a2SStefan Roese * closest one.
3389eefe2a2SStefan Roese */
3399eefe2a2SStefan Roese dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
3409eefe2a2SStefan Roese nm.name = NULL;
3419eefe2a2SStefan Roese dent = ubifs_tnc_next_ent(c, &key, &nm);
3429eefe2a2SStefan Roese if (IS_ERR(dent)) {
3439eefe2a2SStefan Roese err = PTR_ERR(dent);
3449eefe2a2SStefan Roese goto out;
3459eefe2a2SStefan Roese }
3469eefe2a2SStefan Roese file->f_pos = key_hash_flash(c, &dent->key);
3479eefe2a2SStefan Roese file->private_data = dent;
3489eefe2a2SStefan Roese }
3499eefe2a2SStefan Roese
3509eefe2a2SStefan Roese while (1) {
3519eefe2a2SStefan Roese dbg_gen("feed '%s', ino %llu, new f_pos %#x",
3529eefe2a2SStefan Roese dent->name, (unsigned long long)le64_to_cpu(dent->inum),
3539eefe2a2SStefan Roese key_hash_flash(c, &dent->key));
35487deefecSPatrice Chotard #ifndef __UBOOT__
3559eefe2a2SStefan Roese ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
35687deefecSPatrice Chotard #endif
3579eefe2a2SStefan Roese
3589eefe2a2SStefan Roese nm.len = le16_to_cpu(dent->nlen);
3599eefe2a2SStefan Roese over = filldir(c, (char *)dent->name, nm.len,
3609eefe2a2SStefan Roese le64_to_cpu(dent->inum), dent->type);
3619eefe2a2SStefan Roese if (over)
3629eefe2a2SStefan Roese return 0;
3639eefe2a2SStefan Roese
3649eefe2a2SStefan Roese /* Switch to the next entry */
3659eefe2a2SStefan Roese key_read(c, &dent->key, &key);
3669eefe2a2SStefan Roese nm.name = (char *)dent->name;
3679eefe2a2SStefan Roese dent = ubifs_tnc_next_ent(c, &key, &nm);
3689eefe2a2SStefan Roese if (IS_ERR(dent)) {
3699eefe2a2SStefan Roese err = PTR_ERR(dent);
3709eefe2a2SStefan Roese goto out;
3719eefe2a2SStefan Roese }
3729eefe2a2SStefan Roese
3739eefe2a2SStefan Roese kfree(file->private_data);
3749eefe2a2SStefan Roese file->f_pos = key_hash_flash(c, &dent->key);
3759eefe2a2SStefan Roese file->private_data = dent;
3769eefe2a2SStefan Roese cond_resched();
3779eefe2a2SStefan Roese }
3789eefe2a2SStefan Roese
3799eefe2a2SStefan Roese out:
3809eefe2a2SStefan Roese if (err != -ENOENT) {
3810195a7bbSHeiko Schocher ubifs_err(c, "cannot find next direntry, error %d", err);
3829eefe2a2SStefan Roese return err;
3839eefe2a2SStefan Roese }
3849eefe2a2SStefan Roese
3859eefe2a2SStefan Roese kfree(file->private_data);
3869eefe2a2SStefan Roese file->private_data = NULL;
3879eefe2a2SStefan Roese file->f_pos = 2;
3889eefe2a2SStefan Roese return 0;
3899eefe2a2SStefan Roese }
3909eefe2a2SStefan Roese
ubifs_finddir(struct super_block * sb,char * dirname,unsigned long root_inum,unsigned long * inum)3919eefe2a2SStefan Roese static int ubifs_finddir(struct super_block *sb, char *dirname,
3929eefe2a2SStefan Roese unsigned long root_inum, unsigned long *inum)
3939eefe2a2SStefan Roese {
3949eefe2a2SStefan Roese int err;
3959eefe2a2SStefan Roese struct qstr nm;
3969eefe2a2SStefan Roese union ubifs_key key;
3979eefe2a2SStefan Roese struct ubifs_dent_node *dent;
3989eefe2a2SStefan Roese struct ubifs_info *c;
3999eefe2a2SStefan Roese struct file *file;
4009eefe2a2SStefan Roese struct dentry *dentry;
4019eefe2a2SStefan Roese struct inode *dir;
402be73913bSStefan Roese int ret = 0;
4039eefe2a2SStefan Roese
4049eefe2a2SStefan Roese file = kzalloc(sizeof(struct file), 0);
4059eefe2a2SStefan Roese dentry = kzalloc(sizeof(struct dentry), 0);
4069eefe2a2SStefan Roese dir = kzalloc(sizeof(struct inode), 0);
4079eefe2a2SStefan Roese if (!file || !dentry || !dir) {
4089eefe2a2SStefan Roese printf("%s: Error, no memory for malloc!\n", __func__);
4099eefe2a2SStefan Roese err = -ENOMEM;
4109eefe2a2SStefan Roese goto out;
4119eefe2a2SStefan Roese }
4129eefe2a2SStefan Roese
4139eefe2a2SStefan Roese dir->i_sb = sb;
4149eefe2a2SStefan Roese file->f_path.dentry = dentry;
4159eefe2a2SStefan Roese file->f_path.dentry->d_parent = dentry;
4169eefe2a2SStefan Roese file->f_path.dentry->d_inode = dir;
4179eefe2a2SStefan Roese file->f_path.dentry->d_inode->i_ino = root_inum;
4189eefe2a2SStefan Roese c = sb->s_fs_info;
4199eefe2a2SStefan Roese
4209eefe2a2SStefan Roese dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
4219eefe2a2SStefan Roese
4229eefe2a2SStefan Roese /* Find the first entry in TNC and save it */
4239eefe2a2SStefan Roese lowest_dent_key(c, &key, dir->i_ino);
4249eefe2a2SStefan Roese nm.name = NULL;
4259eefe2a2SStefan Roese dent = ubifs_tnc_next_ent(c, &key, &nm);
4269eefe2a2SStefan Roese if (IS_ERR(dent)) {
4279eefe2a2SStefan Roese err = PTR_ERR(dent);
4289eefe2a2SStefan Roese goto out;
4299eefe2a2SStefan Roese }
4309eefe2a2SStefan Roese
4319eefe2a2SStefan Roese file->f_pos = key_hash_flash(c, &dent->key);
4329eefe2a2SStefan Roese file->private_data = dent;
4339eefe2a2SStefan Roese
4349eefe2a2SStefan Roese while (1) {
4359eefe2a2SStefan Roese dbg_gen("feed '%s', ino %llu, new f_pos %#x",
4369eefe2a2SStefan Roese dent->name, (unsigned long long)le64_to_cpu(dent->inum),
4379eefe2a2SStefan Roese key_hash_flash(c, &dent->key));
43887deefecSPatrice Chotard #ifndef __UBOOT__
4399eefe2a2SStefan Roese ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
44087deefecSPatrice Chotard #endif
4419eefe2a2SStefan Roese
4429eefe2a2SStefan Roese nm.len = le16_to_cpu(dent->nlen);
4439eefe2a2SStefan Roese if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
4449eefe2a2SStefan Roese (strlen(dirname) == nm.len)) {
4459eefe2a2SStefan Roese *inum = le64_to_cpu(dent->inum);
446be73913bSStefan Roese ret = 1;
447be73913bSStefan Roese goto out_free;
4489eefe2a2SStefan Roese }
4499eefe2a2SStefan Roese
4509eefe2a2SStefan Roese /* Switch to the next entry */
4519eefe2a2SStefan Roese key_read(c, &dent->key, &key);
4529eefe2a2SStefan Roese nm.name = (char *)dent->name;
4539eefe2a2SStefan Roese dent = ubifs_tnc_next_ent(c, &key, &nm);
4549eefe2a2SStefan Roese if (IS_ERR(dent)) {
4559eefe2a2SStefan Roese err = PTR_ERR(dent);
4569eefe2a2SStefan Roese goto out;
4579eefe2a2SStefan Roese }
4589eefe2a2SStefan Roese
4599eefe2a2SStefan Roese kfree(file->private_data);
4609eefe2a2SStefan Roese file->f_pos = key_hash_flash(c, &dent->key);
4619eefe2a2SStefan Roese file->private_data = dent;
4629eefe2a2SStefan Roese cond_resched();
4639eefe2a2SStefan Roese }
4649eefe2a2SStefan Roese
4659eefe2a2SStefan Roese out:
466be73913bSStefan Roese if (err != -ENOENT)
4670195a7bbSHeiko Schocher dbg_gen("cannot find next direntry, error %d", err);
4689eefe2a2SStefan Roese
469be73913bSStefan Roese out_free:
4703267bc1bSWolfgang Denk kfree(file->private_data);
4719eefe2a2SStefan Roese free(file);
4729eefe2a2SStefan Roese free(dentry);
4739eefe2a2SStefan Roese free(dir);
4749eefe2a2SStefan Roese
475be73913bSStefan Roese return ret;
4769eefe2a2SStefan Roese }
4779eefe2a2SStefan Roese
ubifs_findfile(struct super_block * sb,char * filename)4789eefe2a2SStefan Roese static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
4799eefe2a2SStefan Roese {
4809eefe2a2SStefan Roese int ret;
4819eefe2a2SStefan Roese char *next;
4829eefe2a2SStefan Roese char fpath[128];
4839d7952e4SSimon Kagstrom char symlinkpath[128];
4849eefe2a2SStefan Roese char *name = fpath;
4859eefe2a2SStefan Roese unsigned long root_inum = 1;
4869eefe2a2SStefan Roese unsigned long inum;
4879d7952e4SSimon Kagstrom int symlink_count = 0; /* Don't allow symlink recursion */
48864b68178SRicardo Ribalda Delgado char link_name[64];
4899eefe2a2SStefan Roese
4909eefe2a2SStefan Roese strcpy(fpath, filename);
4919eefe2a2SStefan Roese
4929eefe2a2SStefan Roese /* Remove all leading slashes */
4939eefe2a2SStefan Roese while (*name == '/')
4949eefe2a2SStefan Roese name++;
4959eefe2a2SStefan Roese
4969eefe2a2SStefan Roese /*
4979eefe2a2SStefan Roese * Handle root-direcoty ('/')
4989eefe2a2SStefan Roese */
4999eefe2a2SStefan Roese inum = root_inum;
5009eefe2a2SStefan Roese if (!name || *name == '\0')
5019eefe2a2SStefan Roese return inum;
5029eefe2a2SStefan Roese
5039eefe2a2SStefan Roese for (;;) {
5049d7952e4SSimon Kagstrom struct inode *inode;
5059d7952e4SSimon Kagstrom struct ubifs_inode *ui;
5069d7952e4SSimon Kagstrom
5079eefe2a2SStefan Roese /* Extract the actual part from the pathname. */
5089eefe2a2SStefan Roese next = strchr(name, '/');
5099eefe2a2SStefan Roese if (next) {
5109eefe2a2SStefan Roese /* Remove all leading slashes. */
5119eefe2a2SStefan Roese while (*next == '/')
5129eefe2a2SStefan Roese *(next++) = '\0';
5139eefe2a2SStefan Roese }
5149eefe2a2SStefan Roese
5159eefe2a2SStefan Roese ret = ubifs_finddir(sb, name, root_inum, &inum);
5169d7952e4SSimon Kagstrom if (!ret)
5179d7952e4SSimon Kagstrom return 0;
5189d7952e4SSimon Kagstrom inode = ubifs_iget(sb, inum);
5199d7952e4SSimon Kagstrom
5209d7952e4SSimon Kagstrom if (!inode)
5219d7952e4SSimon Kagstrom return 0;
5229d7952e4SSimon Kagstrom ui = ubifs_inode(inode);
5239d7952e4SSimon Kagstrom
5249d7952e4SSimon Kagstrom if ((inode->i_mode & S_IFMT) == S_IFLNK) {
5259d7952e4SSimon Kagstrom char buf[128];
5269d7952e4SSimon Kagstrom
5279d7952e4SSimon Kagstrom /* We have some sort of symlink recursion, bail out */
5289d7952e4SSimon Kagstrom if (symlink_count++ > 8) {
5299d7952e4SSimon Kagstrom printf("Symlink recursion, aborting\n");
5309d7952e4SSimon Kagstrom return 0;
5319d7952e4SSimon Kagstrom }
5329d7952e4SSimon Kagstrom memcpy(link_name, ui->data, ui->data_len);
5339d7952e4SSimon Kagstrom link_name[ui->data_len] = '\0';
5349d7952e4SSimon Kagstrom
5359d7952e4SSimon Kagstrom if (link_name[0] == '/') {
5369d7952e4SSimon Kagstrom /* Absolute path, redo everything without
5379d7952e4SSimon Kagstrom * the leading slash */
5389d7952e4SSimon Kagstrom next = name = link_name + 1;
5399d7952e4SSimon Kagstrom root_inum = 1;
5409d7952e4SSimon Kagstrom continue;
5419d7952e4SSimon Kagstrom }
5429d7952e4SSimon Kagstrom /* Relative to cur dir */
543ef37c683SSimon Kagstrom sprintf(buf, "%s/%s",
5449d7952e4SSimon Kagstrom link_name, next == NULL ? "" : next);
5459d7952e4SSimon Kagstrom memcpy(symlinkpath, buf, sizeof(buf));
5469d7952e4SSimon Kagstrom next = name = symlinkpath;
5479d7952e4SSimon Kagstrom continue;
5489d7952e4SSimon Kagstrom }
5499eefe2a2SStefan Roese
5509eefe2a2SStefan Roese /*
5519eefe2a2SStefan Roese * Check if directory with this name exists
5529eefe2a2SStefan Roese */
5539eefe2a2SStefan Roese
5549eefe2a2SStefan Roese /* Found the node! */
5559d7952e4SSimon Kagstrom if (!next || *next == '\0')
5569eefe2a2SStefan Roese return inum;
5579eefe2a2SStefan Roese
5589eefe2a2SStefan Roese root_inum = inum;
5599eefe2a2SStefan Roese name = next;
5609eefe2a2SStefan Roese }
5619eefe2a2SStefan Roese
5629eefe2a2SStefan Roese return 0;
5639eefe2a2SStefan Roese }
5649eefe2a2SStefan Roese
ubifs_set_blk_dev(struct blk_desc * rbdd,disk_partition_t * info)5654101f687SSimon Glass int ubifs_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info)
56629cc5bcaSHans de Goede {
56729cc5bcaSHans de Goede if (rbdd) {
56829cc5bcaSHans de Goede debug("UBIFS cannot be used with normal block devices\n");
56929cc5bcaSHans de Goede return -1;
57029cc5bcaSHans de Goede }
57129cc5bcaSHans de Goede
57229cc5bcaSHans de Goede /*
573e35929e4SSimon Glass * Should never happen since blk_get_device_part_str() already checks
57429cc5bcaSHans de Goede * this, but better safe then sorry.
57529cc5bcaSHans de Goede */
57629cc5bcaSHans de Goede if (!ubifs_is_mounted()) {
57729cc5bcaSHans de Goede debug("UBIFS not mounted, use ubifsmount to mount volume first!\n");
57829cc5bcaSHans de Goede return -1;
57929cc5bcaSHans de Goede }
58029cc5bcaSHans de Goede
58129cc5bcaSHans de Goede return 0;
58229cc5bcaSHans de Goede }
58329cc5bcaSHans de Goede
ubifs_ls(const char * filename)584ad15749bSHans de Goede int ubifs_ls(const char *filename)
5859eefe2a2SStefan Roese {
5869eefe2a2SStefan Roese struct ubifs_info *c = ubifs_sb->s_fs_info;
5879eefe2a2SStefan Roese struct file *file;
5889eefe2a2SStefan Roese struct dentry *dentry;
5899eefe2a2SStefan Roese struct inode *dir;
5909eefe2a2SStefan Roese void *dirent = NULL;
5919eefe2a2SStefan Roese unsigned long inum;
5929eefe2a2SStefan Roese int ret = 0;
5939eefe2a2SStefan Roese
5949eefe2a2SStefan Roese c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
595ad15749bSHans de Goede inum = ubifs_findfile(ubifs_sb, (char *)filename);
5969eefe2a2SStefan Roese if (!inum) {
5979eefe2a2SStefan Roese ret = -1;
5989eefe2a2SStefan Roese goto out;
5999eefe2a2SStefan Roese }
6009eefe2a2SStefan Roese
6019eefe2a2SStefan Roese file = kzalloc(sizeof(struct file), 0);
6029eefe2a2SStefan Roese dentry = kzalloc(sizeof(struct dentry), 0);
6039eefe2a2SStefan Roese dir = kzalloc(sizeof(struct inode), 0);
6049eefe2a2SStefan Roese if (!file || !dentry || !dir) {
6059eefe2a2SStefan Roese printf("%s: Error, no memory for malloc!\n", __func__);
6069eefe2a2SStefan Roese ret = -ENOMEM;
6079eefe2a2SStefan Roese goto out_mem;
6089eefe2a2SStefan Roese }
6099eefe2a2SStefan Roese
6109eefe2a2SStefan Roese dir->i_sb = ubifs_sb;
6119eefe2a2SStefan Roese file->f_path.dentry = dentry;
6129eefe2a2SStefan Roese file->f_path.dentry->d_parent = dentry;
6139eefe2a2SStefan Roese file->f_path.dentry->d_inode = dir;
6149eefe2a2SStefan Roese file->f_path.dentry->d_inode->i_ino = inum;
6159eefe2a2SStefan Roese file->f_pos = 1;
6169eefe2a2SStefan Roese file->private_data = NULL;
6179eefe2a2SStefan Roese ubifs_printdir(file, dirent);
6189eefe2a2SStefan Roese
6199eefe2a2SStefan Roese out_mem:
6209eefe2a2SStefan Roese if (file)
6219eefe2a2SStefan Roese free(file);
6229eefe2a2SStefan Roese if (dentry)
6239eefe2a2SStefan Roese free(dentry);
6249eefe2a2SStefan Roese if (dir)
6259eefe2a2SStefan Roese free(dir);
6269eefe2a2SStefan Roese
6279eefe2a2SStefan Roese out:
6289eefe2a2SStefan Roese ubi_close_volume(c->ubi);
6299eefe2a2SStefan Roese return ret;
6309eefe2a2SStefan Roese }
6319eefe2a2SStefan Roese
ubifs_exists(const char * filename)63229cc5bcaSHans de Goede int ubifs_exists(const char *filename)
63329cc5bcaSHans de Goede {
63429cc5bcaSHans de Goede struct ubifs_info *c = ubifs_sb->s_fs_info;
63529cc5bcaSHans de Goede unsigned long inum;
63629cc5bcaSHans de Goede
63729cc5bcaSHans de Goede c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
63829cc5bcaSHans de Goede inum = ubifs_findfile(ubifs_sb, (char *)filename);
63929cc5bcaSHans de Goede ubi_close_volume(c->ubi);
64029cc5bcaSHans de Goede
64129cc5bcaSHans de Goede return inum != 0;
64229cc5bcaSHans de Goede }
64329cc5bcaSHans de Goede
ubifs_size(const char * filename,loff_t * size)64429cc5bcaSHans de Goede int ubifs_size(const char *filename, loff_t *size)
64529cc5bcaSHans de Goede {
64629cc5bcaSHans de Goede struct ubifs_info *c = ubifs_sb->s_fs_info;
64729cc5bcaSHans de Goede unsigned long inum;
64829cc5bcaSHans de Goede struct inode *inode;
64929cc5bcaSHans de Goede int err = 0;
65029cc5bcaSHans de Goede
65129cc5bcaSHans de Goede c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
65229cc5bcaSHans de Goede
65329cc5bcaSHans de Goede inum = ubifs_findfile(ubifs_sb, (char *)filename);
65429cc5bcaSHans de Goede if (!inum) {
65529cc5bcaSHans de Goede err = -1;
65629cc5bcaSHans de Goede goto out;
65729cc5bcaSHans de Goede }
65829cc5bcaSHans de Goede
65929cc5bcaSHans de Goede inode = ubifs_iget(ubifs_sb, inum);
66029cc5bcaSHans de Goede if (IS_ERR(inode)) {
66129cc5bcaSHans de Goede printf("%s: Error reading inode %ld!\n", __func__, inum);
66229cc5bcaSHans de Goede err = PTR_ERR(inode);
66329cc5bcaSHans de Goede goto out;
66429cc5bcaSHans de Goede }
66529cc5bcaSHans de Goede
66629cc5bcaSHans de Goede *size = inode->i_size;
66729cc5bcaSHans de Goede
66829cc5bcaSHans de Goede ubifs_iput(inode);
66929cc5bcaSHans de Goede out:
67029cc5bcaSHans de Goede ubi_close_volume(c->ubi);
67129cc5bcaSHans de Goede return err;
67229cc5bcaSHans de Goede }
67329cc5bcaSHans de Goede
6749eefe2a2SStefan Roese /*
6759eefe2a2SStefan Roese * ubifsload...
6769eefe2a2SStefan Roese */
6779eefe2a2SStefan Roese
6789eefe2a2SStefan Roese /* file.c */
6799eefe2a2SStefan Roese
kmap(struct page * page)6809eefe2a2SStefan Roese static inline void *kmap(struct page *page)
6819eefe2a2SStefan Roese {
6829eefe2a2SStefan Roese return page->addr;
6839eefe2a2SStefan Roese }
6849eefe2a2SStefan Roese
read_block(struct inode * inode,void * addr,unsigned int block,struct ubifs_data_node * dn)6859eefe2a2SStefan Roese static int read_block(struct inode *inode, void *addr, unsigned int block,
6869eefe2a2SStefan Roese struct ubifs_data_node *dn)
6879eefe2a2SStefan Roese {
6889eefe2a2SStefan Roese struct ubifs_info *c = inode->i_sb->s_fs_info;
6899eefe2a2SStefan Roese int err, len, out_len;
6909eefe2a2SStefan Roese union ubifs_key key;
6919eefe2a2SStefan Roese unsigned int dlen;
6929eefe2a2SStefan Roese
6939eefe2a2SStefan Roese data_key_init(c, &key, inode->i_ino, block);
6949eefe2a2SStefan Roese err = ubifs_tnc_lookup(c, &key, dn);
6959eefe2a2SStefan Roese if (err) {
6969eefe2a2SStefan Roese if (err == -ENOENT)
6979eefe2a2SStefan Roese /* Not found, so it must be a hole */
6989eefe2a2SStefan Roese memset(addr, 0, UBIFS_BLOCK_SIZE);
6999eefe2a2SStefan Roese return err;
7009eefe2a2SStefan Roese }
7019eefe2a2SStefan Roese
7029eefe2a2SStefan Roese ubifs_assert(le64_to_cpu(dn->ch.sqnum) > ubifs_inode(inode)->creat_sqnum);
7039eefe2a2SStefan Roese
7049eefe2a2SStefan Roese len = le32_to_cpu(dn->size);
7059eefe2a2SStefan Roese if (len <= 0 || len > UBIFS_BLOCK_SIZE)
7069eefe2a2SStefan Roese goto dump;
7079eefe2a2SStefan Roese
7089eefe2a2SStefan Roese dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
7099eefe2a2SStefan Roese out_len = UBIFS_BLOCK_SIZE;
7100195a7bbSHeiko Schocher err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
7119eefe2a2SStefan Roese le16_to_cpu(dn->compr_type));
7129eefe2a2SStefan Roese if (err || len != out_len)
7139eefe2a2SStefan Roese goto dump;
7149eefe2a2SStefan Roese
7159eefe2a2SStefan Roese /*
7169eefe2a2SStefan Roese * Data length can be less than a full block, even for blocks that are
7179eefe2a2SStefan Roese * not the last in the file (e.g., as a result of making a hole and
7189eefe2a2SStefan Roese * appending data). Ensure that the remainder is zeroed out.
7199eefe2a2SStefan Roese */
7209eefe2a2SStefan Roese if (len < UBIFS_BLOCK_SIZE)
7219eefe2a2SStefan Roese memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
7229eefe2a2SStefan Roese
7239eefe2a2SStefan Roese return 0;
7249eefe2a2SStefan Roese
7259eefe2a2SStefan Roese dump:
7260195a7bbSHeiko Schocher ubifs_err(c, "bad data node (block %u, inode %lu)",
7279eefe2a2SStefan Roese block, inode->i_ino);
728ff94bc40SHeiko Schocher ubifs_dump_node(c, dn);
7299eefe2a2SStefan Roese return -EINVAL;
7309eefe2a2SStefan Roese }
7319eefe2a2SStefan Roese
do_readpage(struct ubifs_info * c,struct inode * inode,struct page * page,int last_block_size)732b1a14f8aSStefan Roese static int do_readpage(struct ubifs_info *c, struct inode *inode,
733b1a14f8aSStefan Roese struct page *page, int last_block_size)
7349eefe2a2SStefan Roese {
7359eefe2a2SStefan Roese void *addr;
7369eefe2a2SStefan Roese int err = 0, i;
7379eefe2a2SStefan Roese unsigned int block, beyond;
7389eefe2a2SStefan Roese struct ubifs_data_node *dn;
7399eefe2a2SStefan Roese loff_t i_size = inode->i_size;
7409eefe2a2SStefan Roese
7419eefe2a2SStefan Roese dbg_gen("ino %lu, pg %lu, i_size %lld",
7429eefe2a2SStefan Roese inode->i_ino, page->index, i_size);
7439eefe2a2SStefan Roese
7449eefe2a2SStefan Roese addr = kmap(page);
7459eefe2a2SStefan Roese
7469eefe2a2SStefan Roese block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
7479eefe2a2SStefan Roese beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
7489eefe2a2SStefan Roese if (block >= beyond) {
7499eefe2a2SStefan Roese /* Reading beyond inode */
7509eefe2a2SStefan Roese memset(addr, 0, PAGE_CACHE_SIZE);
7519eefe2a2SStefan Roese goto out;
7529eefe2a2SStefan Roese }
7539eefe2a2SStefan Roese
7549eefe2a2SStefan Roese dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
755165f9859SDaniel Mack if (!dn)
756165f9859SDaniel Mack return -ENOMEM;
7579eefe2a2SStefan Roese
7589eefe2a2SStefan Roese i = 0;
7599eefe2a2SStefan Roese while (1) {
7609eefe2a2SStefan Roese int ret;
7619eefe2a2SStefan Roese
7629eefe2a2SStefan Roese if (block >= beyond) {
7639eefe2a2SStefan Roese /* Reading beyond inode */
7649eefe2a2SStefan Roese err = -ENOENT;
7659eefe2a2SStefan Roese memset(addr, 0, UBIFS_BLOCK_SIZE);
7669eefe2a2SStefan Roese } else {
767b1a14f8aSStefan Roese /*
768b1a14f8aSStefan Roese * Reading last block? Make sure to not write beyond
769b1a14f8aSStefan Roese * the requested size in the destination buffer.
770b1a14f8aSStefan Roese */
771b1a14f8aSStefan Roese if (((block + 1) == beyond) || last_block_size) {
772b1a14f8aSStefan Roese void *buff;
773b1a14f8aSStefan Roese int dlen;
774b1a14f8aSStefan Roese
775b1a14f8aSStefan Roese /*
776b1a14f8aSStefan Roese * We need to buffer the data locally for the
777b1a14f8aSStefan Roese * last block. This is to not pad the
778b1a14f8aSStefan Roese * destination area to a multiple of
779b1a14f8aSStefan Roese * UBIFS_BLOCK_SIZE.
780b1a14f8aSStefan Roese */
7814519668bSMarcel Ziswiler buff = malloc_cache_aligned(UBIFS_BLOCK_SIZE);
782b1a14f8aSStefan Roese if (!buff) {
783b1a14f8aSStefan Roese printf("%s: Error, malloc fails!\n",
784b1a14f8aSStefan Roese __func__);
785b1a14f8aSStefan Roese err = -ENOMEM;
786b1a14f8aSStefan Roese break;
787b1a14f8aSStefan Roese }
788b1a14f8aSStefan Roese
789b1a14f8aSStefan Roese /* Read block-size into temp buffer */
790b1a14f8aSStefan Roese ret = read_block(inode, buff, block, dn);
791b1a14f8aSStefan Roese if (ret) {
792b1a14f8aSStefan Roese err = ret;
793b1a14f8aSStefan Roese if (err != -ENOENT) {
794b1a14f8aSStefan Roese free(buff);
795b1a14f8aSStefan Roese break;
796b1a14f8aSStefan Roese }
797b1a14f8aSStefan Roese }
798b1a14f8aSStefan Roese
799b1a14f8aSStefan Roese if (last_block_size)
800b1a14f8aSStefan Roese dlen = last_block_size;
801b1a14f8aSStefan Roese else
802b1a14f8aSStefan Roese dlen = le32_to_cpu(dn->size);
803b1a14f8aSStefan Roese
804b1a14f8aSStefan Roese /* Now copy required size back to dest */
805b1a14f8aSStefan Roese memcpy(addr, buff, dlen);
806b1a14f8aSStefan Roese
807b1a14f8aSStefan Roese free(buff);
808b1a14f8aSStefan Roese } else {
8099eefe2a2SStefan Roese ret = read_block(inode, addr, block, dn);
8109eefe2a2SStefan Roese if (ret) {
8119eefe2a2SStefan Roese err = ret;
8129eefe2a2SStefan Roese if (err != -ENOENT)
8139eefe2a2SStefan Roese break;
814b1a14f8aSStefan Roese }
8159eefe2a2SStefan Roese }
8169eefe2a2SStefan Roese }
8179eefe2a2SStefan Roese if (++i >= UBIFS_BLOCKS_PER_PAGE)
8189eefe2a2SStefan Roese break;
8199eefe2a2SStefan Roese block += 1;
8209eefe2a2SStefan Roese addr += UBIFS_BLOCK_SIZE;
8219eefe2a2SStefan Roese }
8229eefe2a2SStefan Roese if (err) {
8239eefe2a2SStefan Roese if (err == -ENOENT) {
8249eefe2a2SStefan Roese /* Not found, so it must be a hole */
8259eefe2a2SStefan Roese dbg_gen("hole");
8269eefe2a2SStefan Roese goto out_free;
8279eefe2a2SStefan Roese }
8280195a7bbSHeiko Schocher ubifs_err(c, "cannot read page %lu of inode %lu, error %d",
8299eefe2a2SStefan Roese page->index, inode->i_ino, err);
8309eefe2a2SStefan Roese goto error;
8319eefe2a2SStefan Roese }
8329eefe2a2SStefan Roese
8339eefe2a2SStefan Roese out_free:
8349eefe2a2SStefan Roese kfree(dn);
8359eefe2a2SStefan Roese out:
8369eefe2a2SStefan Roese return 0;
8379eefe2a2SStefan Roese
8389eefe2a2SStefan Roese error:
8399eefe2a2SStefan Roese kfree(dn);
8409eefe2a2SStefan Roese return err;
8419eefe2a2SStefan Roese }
8429eefe2a2SStefan Roese
ubifs_read(const char * filename,void * buf,loff_t offset,loff_t size,loff_t * actread)843ad15749bSHans de Goede int ubifs_read(const char *filename, void *buf, loff_t offset,
844ad15749bSHans de Goede loff_t size, loff_t *actread)
8459eefe2a2SStefan Roese {
8469eefe2a2SStefan Roese struct ubifs_info *c = ubifs_sb->s_fs_info;
8479eefe2a2SStefan Roese unsigned long inum;
8489eefe2a2SStefan Roese struct inode *inode;
8499eefe2a2SStefan Roese struct page page;
8509eefe2a2SStefan Roese int err = 0;
8519eefe2a2SStefan Roese int i;
8529eefe2a2SStefan Roese int count;
853b1a14f8aSStefan Roese int last_block_size = 0;
8549eefe2a2SStefan Roese
855ad15749bSHans de Goede *actread = 0;
856ad15749bSHans de Goede
857ad15749bSHans de Goede if (offset & (PAGE_SIZE - 1)) {
8581381901eSVagrant Cascadian printf("ubifs: Error offset must be a multiple of %d\n",
859ad15749bSHans de Goede PAGE_SIZE);
860ad15749bSHans de Goede return -1;
861ad15749bSHans de Goede }
862ad15749bSHans de Goede
8639eefe2a2SStefan Roese c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
8649d7952e4SSimon Kagstrom /* ubifs_findfile will resolve symlinks, so we know that we get
8659d7952e4SSimon Kagstrom * the real file here */
866ad15749bSHans de Goede inum = ubifs_findfile(ubifs_sb, (char *)filename);
8679eefe2a2SStefan Roese if (!inum) {
8689eefe2a2SStefan Roese err = -1;
8699eefe2a2SStefan Roese goto out;
8709eefe2a2SStefan Roese }
8719eefe2a2SStefan Roese
8729eefe2a2SStefan Roese /*
8739eefe2a2SStefan Roese * Read file inode
8749eefe2a2SStefan Roese */
8759eefe2a2SStefan Roese inode = ubifs_iget(ubifs_sb, inum);
8769eefe2a2SStefan Roese if (IS_ERR(inode)) {
8779eefe2a2SStefan Roese printf("%s: Error reading inode %ld!\n", __func__, inum);
8789eefe2a2SStefan Roese err = PTR_ERR(inode);
8799eefe2a2SStefan Roese goto out;
8809eefe2a2SStefan Roese }
8819eefe2a2SStefan Roese
882ad15749bSHans de Goede if (offset > inode->i_size) {
883ad15749bSHans de Goede printf("ubifs: Error offset (%lld) > file-size (%lld)\n",
884ad15749bSHans de Goede offset, size);
885ad15749bSHans de Goede err = -1;
886ad15749bSHans de Goede goto put_inode;
887ad15749bSHans de Goede }
888ad15749bSHans de Goede
8899eefe2a2SStefan Roese /*
8909eefe2a2SStefan Roese * If no size was specified or if size bigger than filesize
8919eefe2a2SStefan Roese * set size to filesize
8929eefe2a2SStefan Roese */
893ad15749bSHans de Goede if ((size == 0) || (size > (inode->i_size - offset)))
894ad15749bSHans de Goede size = inode->i_size - offset;
8959eefe2a2SStefan Roese
8969eefe2a2SStefan Roese count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
8979eefe2a2SStefan Roese
898ad15749bSHans de Goede page.addr = buf;
899ad15749bSHans de Goede page.index = offset / PAGE_SIZE;
9009eefe2a2SStefan Roese page.inode = inode;
9019eefe2a2SStefan Roese for (i = 0; i < count; i++) {
902b1a14f8aSStefan Roese /*
903b1a14f8aSStefan Roese * Make sure to not read beyond the requested size
904b1a14f8aSStefan Roese */
905b1a14f8aSStefan Roese if (((i + 1) == count) && (size < inode->i_size))
906b1a14f8aSStefan Roese last_block_size = size - (i * PAGE_SIZE);
907b1a14f8aSStefan Roese
908b1a14f8aSStefan Roese err = do_readpage(c, inode, &page, last_block_size);
9099eefe2a2SStefan Roese if (err)
9109eefe2a2SStefan Roese break;
9119eefe2a2SStefan Roese
9129eefe2a2SStefan Roese page.addr += PAGE_SIZE;
9139eefe2a2SStefan Roese page.index++;
9149eefe2a2SStefan Roese }
9159eefe2a2SStefan Roese
916ad15749bSHans de Goede if (err) {
9179eefe2a2SStefan Roese printf("Error reading file '%s'\n", filename);
918ad15749bSHans de Goede *actread = i * PAGE_SIZE;
919ad15749bSHans de Goede } else {
920ad15749bSHans de Goede *actread = size;
92146d7274cSBastian Ruppert }
9229eefe2a2SStefan Roese
923ad15749bSHans de Goede put_inode:
9249eefe2a2SStefan Roese ubifs_iput(inode);
9259eefe2a2SStefan Roese
9269eefe2a2SStefan Roese out:
9279eefe2a2SStefan Roese ubi_close_volume(c->ubi);
9289eefe2a2SStefan Roese return err;
9299eefe2a2SStefan Roese }
930ad15749bSHans de Goede
ubifs_close(void)93129cc5bcaSHans de Goede void ubifs_close(void)
93229cc5bcaSHans de Goede {
93329cc5bcaSHans de Goede }
93429cc5bcaSHans de Goede
935ad15749bSHans de Goede /* Compat wrappers for common/cmd_ubifs.c */
ubifs_load(char * filename,u32 addr,u32 size)936ad15749bSHans de Goede int ubifs_load(char *filename, u32 addr, u32 size)
937ad15749bSHans de Goede {
938ad15749bSHans de Goede loff_t actread;
939ad15749bSHans de Goede int err;
940ad15749bSHans de Goede
941ad15749bSHans de Goede printf("Loading file '%s' to addr 0x%08x...\n", filename, addr);
942ad15749bSHans de Goede
94334cc30afSSiva Durga Prasad Paladugu err = ubifs_read(filename, (void *)(uintptr_t)addr, 0, size, &actread);
944ad15749bSHans de Goede if (err == 0) {
945018f5303SSimon Glass env_set_hex("filesize", actread);
946ad15749bSHans de Goede printf("Done\n");
947ad15749bSHans de Goede }
948ad15749bSHans de Goede
949ad15749bSHans de Goede return err;
950ad15749bSHans de Goede }
951ad15749bSHans de Goede
uboot_ubifs_umount(void)952ad15749bSHans de Goede void uboot_ubifs_umount(void)
953ad15749bSHans de Goede {
954ad15749bSHans de Goede if (ubifs_sb) {
955ad15749bSHans de Goede printf("Unmounting UBIFS volume %s!\n",
956ad15749bSHans de Goede ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name);
957ad15749bSHans de Goede ubifs_umount(ubifs_sb->s_fs_info);
958ad15749bSHans de Goede ubifs_sb = NULL;
959ad15749bSHans de Goede }
960ad15749bSHans de Goede }
961