blob: 72e8a24d3b9aef161c0bc6ea758cf54536cc62ec [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Stefan Roese2fc10f62009-03-19 15:35:05 +01002/*
3 * This file is part of UBIFS.
4 *
5 * Copyright (C) 2006-2008 Nokia Corporation.
6 *
Stefan Roese28ea29f2010-11-01 17:28:00 +01007 * (C) Copyright 2008-2010
Stefan Roese2fc10f62009-03-19 15:35:05 +01008 * Stefan Roese, DENX Software Engineering, sr@denx.de.
9 *
Stefan Roese2fc10f62009-03-19 15:35:05 +010010 * Authors: Artem Bityutskiy (Битюцкий Артём)
11 * Adrian Hunter
12 */
13
Simon Glassa87fc0a2015-09-02 17:24:57 -060014#include <common.h>
Simon Glass1a974af2019-08-01 09:46:36 -060015#include <gzip.h>
Simon Glassa87fc0a2015-09-02 17:24:57 -060016#include <memalign.h>
Stefan Roese2fc10f62009-03-19 15:35:05 +010017#include "ubifs.h"
Ricardo Ribalda Delgadoa7a743e2009-04-27 18:33:33 +020018#include <u-boot/zlib.h>
Stefan Roese2fc10f62009-03-19 15:35:05 +010019
Heiko Schocherf5895d12014-06-24 10:10:04 +020020#include <linux/err.h>
21#include <linux/lzo.h>
22
Stefan Roese2fc10f62009-03-19 15:35:05 +010023DECLARE_GLOBAL_DATA_PTR;
24
25/* compress.c */
26
27/*
Ricardo Ribalda Delgadoa7a743e2009-04-27 18:33:33 +020028 * We need a wrapper for zunzip() because the parameters are
Stefan Roese2fc10f62009-03-19 15:35:05 +010029 * incompatible with the lzo decompressor.
30 */
31static int gzip_decompress(const unsigned char *in, size_t in_len,
32 unsigned char *out, size_t *out_len)
33{
Veli-Pekka Peltola7b7e1552012-09-05 18:05:14 +030034 return zunzip(out, *out_len, (unsigned char *)in,
35 (unsigned long *)out_len, 0, 0);
Stefan Roese2fc10f62009-03-19 15:35:05 +010036}
37
38/* Fake description object for the "none" compressor */
39static struct ubifs_compressor none_compr = {
40 .compr_type = UBIFS_COMPR_NONE,
Heiko Schocherf5895d12014-06-24 10:10:04 +020041 .name = "none",
Stefan Roese2fc10f62009-03-19 15:35:05 +010042 .capi_name = "",
43 .decompress = NULL,
44};
45
46static struct ubifs_compressor lzo_compr = {
47 .compr_type = UBIFS_COMPR_LZO,
Heiko Schocherf5895d12014-06-24 10:10:04 +020048#ifndef __UBOOT__
49 .comp_mutex = &lzo_mutex,
50#endif
51 .name = "lzo",
Stefan Roese2fc10f62009-03-19 15:35:05 +010052 .capi_name = "lzo",
53 .decompress = lzo1x_decompress_safe,
54};
55
56static struct ubifs_compressor zlib_compr = {
57 .compr_type = UBIFS_COMPR_ZLIB,
Heiko Schocherf5895d12014-06-24 10:10:04 +020058#ifndef __UBOOT__
59 .comp_mutex = &deflate_mutex,
60 .decomp_mutex = &inflate_mutex,
61#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +010062 .name = "zlib",
63 .capi_name = "deflate",
64 .decompress = gzip_decompress,
65};
66
67/* All UBIFS compressors */
68struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
69
Heiko Schocherf5895d12014-06-24 10:10:04 +020070
71#ifdef __UBOOT__
72/* from mm/util.c */
73
74/**
75 * kmemdup - duplicate region of memory
76 *
77 * @src: memory region to duplicate
78 * @len: memory region length
79 * @gfp: GFP mask to use
80 */
81void *kmemdup(const void *src, size_t len, gfp_t gfp)
82{
83 void *p;
84
85 p = kmalloc(len, gfp);
86 if (p)
87 memcpy(p, src, len);
88 return p;
89}
90
91struct crypto_comp {
92 int compressor;
93};
94
Heiko Schocher94b66de2015-10-22 06:19:21 +020095static inline struct crypto_comp
96*crypto_alloc_comp(const char *alg_name, u32 type, u32 mask)
Heiko Schocherf5895d12014-06-24 10:10:04 +020097{
98 struct ubifs_compressor *comp;
99 struct crypto_comp *ptr;
100 int i = 0;
101
Marcel Ziswilerabc574b2015-08-18 13:06:37 +0200102 ptr = malloc_cache_aligned(sizeof(struct crypto_comp));
Heiko Schocherf5895d12014-06-24 10:10:04 +0200103 while (i < UBIFS_COMPR_TYPES_CNT) {
104 comp = ubifs_compressors[i];
105 if (!comp) {
106 i++;
107 continue;
108 }
109 if (strncmp(alg_name, comp->capi_name, strlen(alg_name)) == 0) {
110 ptr->compressor = i;
111 return ptr;
112 }
113 i++;
114 }
115 if (i >= UBIFS_COMPR_TYPES_CNT) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200116 dbg_gen("invalid compression type %s", alg_name);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200117 free (ptr);
118 return NULL;
119 }
120 return ptr;
121}
Heiko Schocher94b66de2015-10-22 06:19:21 +0200122static inline int
123crypto_comp_decompress(const struct ubifs_info *c, struct crypto_comp *tfm,
124 const u8 *src, unsigned int slen, u8 *dst,
125 unsigned int *dlen)
Heiko Schocherf5895d12014-06-24 10:10:04 +0200126{
127 struct ubifs_compressor *compr = ubifs_compressors[tfm->compressor];
128 int err;
Paul Davey7f918382018-11-05 18:09:29 +1300129 size_t tmp_len = *dlen;
Heiko Schocherf5895d12014-06-24 10:10:04 +0200130
131 if (compr->compr_type == UBIFS_COMPR_NONE) {
132 memcpy(dst, src, slen);
133 *dlen = slen;
134 return 0;
135 }
136
Paul Davey7f918382018-11-05 18:09:29 +1300137 err = compr->decompress(src, slen, dst, &tmp_len);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200138 if (err)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200139 ubifs_err(c, "cannot decompress %d bytes, compressor %s, "
Heiko Schocherf5895d12014-06-24 10:10:04 +0200140 "error %d", slen, compr->name, err);
141
Paul Davey7f918382018-11-05 18:09:29 +1300142 *dlen = tmp_len;
Heiko Schocherf5895d12014-06-24 10:10:04 +0200143 return err;
144
145 return 0;
146}
Anton Habegger62e79dd2015-01-22 22:29:10 +0100147
148/* from shrinker.c */
149
150/* Global clean znode counter (for all mounted UBIFS instances) */
151atomic_long_t ubifs_clean_zn_cnt;
152
Heiko Schocherf5895d12014-06-24 10:10:04 +0200153#endif
154
Stefan Roese2fc10f62009-03-19 15:35:05 +0100155/**
156 * ubifs_decompress - decompress data.
157 * @in_buf: data to decompress
158 * @in_len: length of the data to decompress
159 * @out_buf: output buffer where decompressed data should
160 * @out_len: output length is returned here
161 * @compr_type: type of compression
162 *
163 * This function decompresses data from buffer @in_buf into buffer @out_buf.
164 * The length of the uncompressed data is returned in @out_len. This functions
165 * returns %0 on success or a negative error code on failure.
166 */
Heiko Schocher94b66de2015-10-22 06:19:21 +0200167int ubifs_decompress(const struct ubifs_info *c, const void *in_buf,
168 int in_len, void *out_buf, int *out_len, int compr_type)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100169{
170 int err;
171 struct ubifs_compressor *compr;
172
173 if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200174 ubifs_err(c, "invalid compression type %d", compr_type);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100175 return -EINVAL;
176 }
177
178 compr = ubifs_compressors[compr_type];
179
180 if (unlikely(!compr->capi_name)) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200181 ubifs_err(c, "%s compression is not compiled in", compr->name);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100182 return -EINVAL;
183 }
184
185 if (compr_type == UBIFS_COMPR_NONE) {
186 memcpy(out_buf, in_buf, in_len);
187 *out_len = in_len;
188 return 0;
189 }
190
Heiko Schocherf5895d12014-06-24 10:10:04 +0200191 if (compr->decomp_mutex)
192 mutex_lock(compr->decomp_mutex);
Heiko Schocher94b66de2015-10-22 06:19:21 +0200193 err = crypto_comp_decompress(c, compr->cc, in_buf, in_len, out_buf,
Heiko Schocherf5895d12014-06-24 10:10:04 +0200194 (unsigned int *)out_len);
195 if (compr->decomp_mutex)
196 mutex_unlock(compr->decomp_mutex);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100197 if (err)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200198 ubifs_err(c, "cannot decompress %d bytes, compressor %s,"
199 " error %d", in_len, compr->name, err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100200
201 return err;
202}
203
204/**
205 * compr_init - initialize a compressor.
206 * @compr: compressor description object
207 *
208 * This function initializes the requested compressor and returns zero in case
209 * of success or a negative error code in case of failure.
210 */
211static int __init compr_init(struct ubifs_compressor *compr)
212{
213 ubifs_compressors[compr->compr_type] = compr;
Peter Tyser9057cbf2009-09-21 11:20:36 -0500214
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200215#ifdef CONFIG_NEEDS_MANUAL_RELOC
Stefan Roese2fc10f62009-03-19 15:35:05 +0100216 ubifs_compressors[compr->compr_type]->name += gd->reloc_off;
217 ubifs_compressors[compr->compr_type]->capi_name += gd->reloc_off;
218 ubifs_compressors[compr->compr_type]->decompress += gd->reloc_off;
Peter Tyser9057cbf2009-09-21 11:20:36 -0500219#endif
220
Heiko Schocherf5895d12014-06-24 10:10:04 +0200221 if (compr->capi_name) {
222 compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
223 if (IS_ERR(compr->cc)) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200224 dbg_gen("cannot initialize compressor %s,"
225 " error %ld", compr->name,
226 PTR_ERR(compr->cc));
Heiko Schocherf5895d12014-06-24 10:10:04 +0200227 return PTR_ERR(compr->cc);
228 }
229 }
230
Stefan Roese2fc10f62009-03-19 15:35:05 +0100231 return 0;
232}
233
234/**
235 * ubifs_compressors_init - initialize UBIFS compressors.
236 *
237 * This function initializes the compressor which were compiled in. Returns
238 * zero in case of success and a negative error code in case of failure.
239 */
240int __init ubifs_compressors_init(void)
241{
242 int err;
243
244 err = compr_init(&lzo_compr);
245 if (err)
246 return err;
247
248 err = compr_init(&zlib_compr);
249 if (err)
250 return err;
251
Michael Lawnickb0617012009-03-19 10:06:41 +0100252 err = compr_init(&none_compr);
253 if (err)
254 return err;
255
Stefan Roese2fc10f62009-03-19 15:35:05 +0100256 return 0;
257}
258
259/*
260 * ubifsls...
261 */
262
263static int filldir(struct ubifs_info *c, const char *name, int namlen,
264 u64 ino, unsigned int d_type)
265{
266 struct inode *inode;
267 char filetime[32];
268
269 switch (d_type) {
270 case UBIFS_ITYPE_REG:
271 printf("\t");
272 break;
273 case UBIFS_ITYPE_DIR:
274 printf("<DIR>\t");
275 break;
276 case UBIFS_ITYPE_LNK:
277 printf("<LNK>\t");
278 break;
279 default:
280 printf("other\t");
281 break;
282 }
283
284 inode = ubifs_iget(c->vfs_sb, ino);
285 if (IS_ERR(inode)) {
286 printf("%s: Error in ubifs_iget(), ino=%lld ret=%p!\n",
287 __func__, ino, inode);
288 return -1;
289 }
290 ctime_r((time_t *)&inode->i_mtime, filetime);
291 printf("%9lld %24.24s ", inode->i_size, filetime);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200292#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100293 ubifs_iput(inode);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200294#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100295
296 printf("%s\n", name);
297
298 return 0;
299}
300
301static int ubifs_printdir(struct file *file, void *dirent)
302{
303 int err, over = 0;
304 struct qstr nm;
305 union ubifs_key key;
306 struct ubifs_dent_node *dent;
307 struct inode *dir = file->f_path.dentry->d_inode;
308 struct ubifs_info *c = dir->i_sb->s_fs_info;
309
310 dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
311
312 if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
313 /*
314 * The directory was seek'ed to a senseless position or there
315 * are no more entries.
316 */
317 return 0;
318
319 if (file->f_pos == 1) {
320 /* Find the first entry in TNC and save it */
321 lowest_dent_key(c, &key, dir->i_ino);
322 nm.name = NULL;
323 dent = ubifs_tnc_next_ent(c, &key, &nm);
324 if (IS_ERR(dent)) {
325 err = PTR_ERR(dent);
326 goto out;
327 }
328
329 file->f_pos = key_hash_flash(c, &dent->key);
330 file->private_data = dent;
331 }
332
333 dent = file->private_data;
334 if (!dent) {
335 /*
336 * The directory was seek'ed to and is now readdir'ed.
337 * Find the entry corresponding to @file->f_pos or the
338 * closest one.
339 */
340 dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
341 nm.name = NULL;
342 dent = ubifs_tnc_next_ent(c, &key, &nm);
343 if (IS_ERR(dent)) {
344 err = PTR_ERR(dent);
345 goto out;
346 }
347 file->f_pos = key_hash_flash(c, &dent->key);
348 file->private_data = dent;
349 }
350
351 while (1) {
352 dbg_gen("feed '%s', ino %llu, new f_pos %#x",
353 dent->name, (unsigned long long)le64_to_cpu(dent->inum),
354 key_hash_flash(c, &dent->key));
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200355#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100356 ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200357#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100358
359 nm.len = le16_to_cpu(dent->nlen);
360 over = filldir(c, (char *)dent->name, nm.len,
361 le64_to_cpu(dent->inum), dent->type);
362 if (over)
363 return 0;
364
365 /* Switch to the next entry */
366 key_read(c, &dent->key, &key);
367 nm.name = (char *)dent->name;
368 dent = ubifs_tnc_next_ent(c, &key, &nm);
369 if (IS_ERR(dent)) {
370 err = PTR_ERR(dent);
371 goto out;
372 }
373
374 kfree(file->private_data);
375 file->f_pos = key_hash_flash(c, &dent->key);
376 file->private_data = dent;
377 cond_resched();
378 }
379
380out:
381 if (err != -ENOENT) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200382 ubifs_err(c, "cannot find next direntry, error %d", err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100383 return err;
384 }
385
386 kfree(file->private_data);
387 file->private_data = NULL;
388 file->f_pos = 2;
389 return 0;
390}
391
392static int ubifs_finddir(struct super_block *sb, char *dirname,
393 unsigned long root_inum, unsigned long *inum)
394{
395 int err;
396 struct qstr nm;
397 union ubifs_key key;
398 struct ubifs_dent_node *dent;
399 struct ubifs_info *c;
400 struct file *file;
401 struct dentry *dentry;
402 struct inode *dir;
Stefan Roeseac3244a2012-08-28 14:00:24 +0200403 int ret = 0;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100404
405 file = kzalloc(sizeof(struct file), 0);
406 dentry = kzalloc(sizeof(struct dentry), 0);
407 dir = kzalloc(sizeof(struct inode), 0);
408 if (!file || !dentry || !dir) {
409 printf("%s: Error, no memory for malloc!\n", __func__);
410 err = -ENOMEM;
411 goto out;
412 }
413
414 dir->i_sb = sb;
415 file->f_path.dentry = dentry;
416 file->f_path.dentry->d_parent = dentry;
417 file->f_path.dentry->d_inode = dir;
418 file->f_path.dentry->d_inode->i_ino = root_inum;
419 c = sb->s_fs_info;
420
421 dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
422
423 /* Find the first entry in TNC and save it */
424 lowest_dent_key(c, &key, dir->i_ino);
425 nm.name = NULL;
426 dent = ubifs_tnc_next_ent(c, &key, &nm);
427 if (IS_ERR(dent)) {
428 err = PTR_ERR(dent);
429 goto out;
430 }
431
432 file->f_pos = key_hash_flash(c, &dent->key);
433 file->private_data = dent;
434
435 while (1) {
436 dbg_gen("feed '%s', ino %llu, new f_pos %#x",
437 dent->name, (unsigned long long)le64_to_cpu(dent->inum),
438 key_hash_flash(c, &dent->key));
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200439#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100440 ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200441#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100442
443 nm.len = le16_to_cpu(dent->nlen);
444 if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
445 (strlen(dirname) == nm.len)) {
446 *inum = le64_to_cpu(dent->inum);
Stefan Roeseac3244a2012-08-28 14:00:24 +0200447 ret = 1;
448 goto out_free;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100449 }
450
451 /* Switch to the next entry */
452 key_read(c, &dent->key, &key);
453 nm.name = (char *)dent->name;
454 dent = ubifs_tnc_next_ent(c, &key, &nm);
455 if (IS_ERR(dent)) {
456 err = PTR_ERR(dent);
457 goto out;
458 }
459
460 kfree(file->private_data);
461 file->f_pos = key_hash_flash(c, &dent->key);
462 file->private_data = dent;
463 cond_resched();
464 }
465
466out:
Stefan Roeseac3244a2012-08-28 14:00:24 +0200467 if (err != -ENOENT)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200468 dbg_gen("cannot find next direntry, error %d", err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100469
Stefan Roeseac3244a2012-08-28 14:00:24 +0200470out_free:
Heinrich Schuchardte9892792017-11-08 22:28:47 +0100471 kfree(file->private_data);
472 free(file);
473 free(dentry);
474 free(dir);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100475
Stefan Roeseac3244a2012-08-28 14:00:24 +0200476 return ret;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100477}
478
479static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
480{
481 int ret;
482 char *next;
483 char fpath[128];
Simon Kagstrom877501a2009-09-15 09:53:29 +0200484 char symlinkpath[128];
Stefan Roese2fc10f62009-03-19 15:35:05 +0100485 char *name = fpath;
486 unsigned long root_inum = 1;
487 unsigned long inum;
Simon Kagstrom877501a2009-09-15 09:53:29 +0200488 int symlink_count = 0; /* Don't allow symlink recursion */
Ricardo Ribalda Delgado4a2e69c2010-12-02 15:02:35 +0100489 char link_name[64];
Stefan Roese2fc10f62009-03-19 15:35:05 +0100490
491 strcpy(fpath, filename);
492
493 /* Remove all leading slashes */
494 while (*name == '/')
495 name++;
496
497 /*
498 * Handle root-direcoty ('/')
499 */
500 inum = root_inum;
501 if (!name || *name == '\0')
502 return inum;
503
504 for (;;) {
Simon Kagstrom877501a2009-09-15 09:53:29 +0200505 struct inode *inode;
506 struct ubifs_inode *ui;
507
Stefan Roese2fc10f62009-03-19 15:35:05 +0100508 /* Extract the actual part from the pathname. */
509 next = strchr(name, '/');
510 if (next) {
511 /* Remove all leading slashes. */
512 while (*next == '/')
513 *(next++) = '\0';
514 }
515
516 ret = ubifs_finddir(sb, name, root_inum, &inum);
Simon Kagstrom877501a2009-09-15 09:53:29 +0200517 if (!ret)
518 return 0;
519 inode = ubifs_iget(sb, inum);
520
521 if (!inode)
522 return 0;
523 ui = ubifs_inode(inode);
524
525 if ((inode->i_mode & S_IFMT) == S_IFLNK) {
Simon Kagstrom877501a2009-09-15 09:53:29 +0200526 char buf[128];
527
528 /* We have some sort of symlink recursion, bail out */
529 if (symlink_count++ > 8) {
530 printf("Symlink recursion, aborting\n");
531 return 0;
532 }
533 memcpy(link_name, ui->data, ui->data_len);
534 link_name[ui->data_len] = '\0';
535
536 if (link_name[0] == '/') {
537 /* Absolute path, redo everything without
538 * the leading slash */
539 next = name = link_name + 1;
540 root_inum = 1;
541 continue;
542 }
543 /* Relative to cur dir */
Simon Kagstrom84167362009-09-25 14:05:57 +0200544 sprintf(buf, "%s/%s",
Simon Kagstrom877501a2009-09-15 09:53:29 +0200545 link_name, next == NULL ? "" : next);
546 memcpy(symlinkpath, buf, sizeof(buf));
547 next = name = symlinkpath;
548 continue;
549 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100550
551 /*
552 * Check if directory with this name exists
553 */
554
555 /* Found the node! */
Simon Kagstrom877501a2009-09-15 09:53:29 +0200556 if (!next || *next == '\0')
557 return inum;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100558
559 root_inum = inum;
560 name = next;
561 }
562
563 return 0;
564}
565
Simon Glasse3394752016-02-29 15:25:34 -0700566int ubifs_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info)
Hans de Goedeb5030b22015-09-17 18:46:57 -0400567{
568 if (rbdd) {
569 debug("UBIFS cannot be used with normal block devices\n");
570 return -1;
571 }
572
573 /*
Simon Glasse76ee972016-02-29 15:25:44 -0700574 * Should never happen since blk_get_device_part_str() already checks
Hans de Goedeb5030b22015-09-17 18:46:57 -0400575 * this, but better safe then sorry.
576 */
577 if (!ubifs_is_mounted()) {
578 debug("UBIFS not mounted, use ubifsmount to mount volume first!\n");
579 return -1;
580 }
581
582 return 0;
583}
584
Hans de Goedea1644772015-09-17 18:46:56 -0400585int ubifs_ls(const char *filename)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100586{
587 struct ubifs_info *c = ubifs_sb->s_fs_info;
588 struct file *file;
589 struct dentry *dentry;
590 struct inode *dir;
591 void *dirent = NULL;
592 unsigned long inum;
593 int ret = 0;
594
595 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
Hans de Goedea1644772015-09-17 18:46:56 -0400596 inum = ubifs_findfile(ubifs_sb, (char *)filename);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100597 if (!inum) {
598 ret = -1;
599 goto out;
600 }
601
602 file = kzalloc(sizeof(struct file), 0);
603 dentry = kzalloc(sizeof(struct dentry), 0);
604 dir = kzalloc(sizeof(struct inode), 0);
605 if (!file || !dentry || !dir) {
606 printf("%s: Error, no memory for malloc!\n", __func__);
607 ret = -ENOMEM;
608 goto out_mem;
609 }
610
611 dir->i_sb = ubifs_sb;
612 file->f_path.dentry = dentry;
613 file->f_path.dentry->d_parent = dentry;
614 file->f_path.dentry->d_inode = dir;
615 file->f_path.dentry->d_inode->i_ino = inum;
616 file->f_pos = 1;
617 file->private_data = NULL;
618 ubifs_printdir(file, dirent);
619
620out_mem:
621 if (file)
622 free(file);
623 if (dentry)
624 free(dentry);
625 if (dir)
626 free(dir);
627
628out:
629 ubi_close_volume(c->ubi);
630 return ret;
631}
632
Hans de Goedeb5030b22015-09-17 18:46:57 -0400633int ubifs_exists(const char *filename)
634{
635 struct ubifs_info *c = ubifs_sb->s_fs_info;
636 unsigned long inum;
637
638 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
639 inum = ubifs_findfile(ubifs_sb, (char *)filename);
640 ubi_close_volume(c->ubi);
641
642 return inum != 0;
643}
644
645int ubifs_size(const char *filename, loff_t *size)
646{
647 struct ubifs_info *c = ubifs_sb->s_fs_info;
648 unsigned long inum;
649 struct inode *inode;
650 int err = 0;
651
652 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
653
654 inum = ubifs_findfile(ubifs_sb, (char *)filename);
655 if (!inum) {
656 err = -1;
657 goto out;
658 }
659
660 inode = ubifs_iget(ubifs_sb, inum);
661 if (IS_ERR(inode)) {
662 printf("%s: Error reading inode %ld!\n", __func__, inum);
663 err = PTR_ERR(inode);
664 goto out;
665 }
666
667 *size = inode->i_size;
668
669 ubifs_iput(inode);
670out:
671 ubi_close_volume(c->ubi);
672 return err;
673}
674
Stefan Roese2fc10f62009-03-19 15:35:05 +0100675/*
676 * ubifsload...
677 */
678
679/* file.c */
680
681static inline void *kmap(struct page *page)
682{
683 return page->addr;
684}
685
686static int read_block(struct inode *inode, void *addr, unsigned int block,
687 struct ubifs_data_node *dn)
688{
689 struct ubifs_info *c = inode->i_sb->s_fs_info;
690 int err, len, out_len;
691 union ubifs_key key;
692 unsigned int dlen;
693
694 data_key_init(c, &key, inode->i_ino, block);
695 err = ubifs_tnc_lookup(c, &key, dn);
696 if (err) {
697 if (err == -ENOENT)
698 /* Not found, so it must be a hole */
699 memset(addr, 0, UBIFS_BLOCK_SIZE);
700 return err;
701 }
702
703 ubifs_assert(le64_to_cpu(dn->ch.sqnum) > ubifs_inode(inode)->creat_sqnum);
704
705 len = le32_to_cpu(dn->size);
706 if (len <= 0 || len > UBIFS_BLOCK_SIZE)
707 goto dump;
708
709 dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
710 out_len = UBIFS_BLOCK_SIZE;
Heiko Schocher94b66de2015-10-22 06:19:21 +0200711 err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
Stefan Roese2fc10f62009-03-19 15:35:05 +0100712 le16_to_cpu(dn->compr_type));
713 if (err || len != out_len)
714 goto dump;
715
716 /*
717 * Data length can be less than a full block, even for blocks that are
718 * not the last in the file (e.g., as a result of making a hole and
719 * appending data). Ensure that the remainder is zeroed out.
720 */
721 if (len < UBIFS_BLOCK_SIZE)
722 memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
723
724 return 0;
725
726dump:
Heiko Schocher94b66de2015-10-22 06:19:21 +0200727 ubifs_err(c, "bad data node (block %u, inode %lu)",
Stefan Roese2fc10f62009-03-19 15:35:05 +0100728 block, inode->i_ino);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200729 ubifs_dump_node(c, dn);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100730 return -EINVAL;
731}
732
Stefan Roese28ea29f2010-11-01 17:28:00 +0100733static int do_readpage(struct ubifs_info *c, struct inode *inode,
734 struct page *page, int last_block_size)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100735{
736 void *addr;
737 int err = 0, i;
738 unsigned int block, beyond;
739 struct ubifs_data_node *dn;
740 loff_t i_size = inode->i_size;
741
742 dbg_gen("ino %lu, pg %lu, i_size %lld",
743 inode->i_ino, page->index, i_size);
744
745 addr = kmap(page);
746
747 block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
748 beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
749 if (block >= beyond) {
750 /* Reading beyond inode */
751 memset(addr, 0, PAGE_CACHE_SIZE);
752 goto out;
753 }
754
755 dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
Daniel Mackb5775802009-06-04 19:44:12 +0200756 if (!dn)
757 return -ENOMEM;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100758
759 i = 0;
760 while (1) {
761 int ret;
762
763 if (block >= beyond) {
764 /* Reading beyond inode */
765 err = -ENOENT;
766 memset(addr, 0, UBIFS_BLOCK_SIZE);
767 } else {
Stefan Roese28ea29f2010-11-01 17:28:00 +0100768 /*
769 * Reading last block? Make sure to not write beyond
770 * the requested size in the destination buffer.
771 */
772 if (((block + 1) == beyond) || last_block_size) {
773 void *buff;
774 int dlen;
775
776 /*
777 * We need to buffer the data locally for the
778 * last block. This is to not pad the
779 * destination area to a multiple of
780 * UBIFS_BLOCK_SIZE.
781 */
Marcel Ziswilerabc574b2015-08-18 13:06:37 +0200782 buff = malloc_cache_aligned(UBIFS_BLOCK_SIZE);
Stefan Roese28ea29f2010-11-01 17:28:00 +0100783 if (!buff) {
784 printf("%s: Error, malloc fails!\n",
785 __func__);
786 err = -ENOMEM;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100787 break;
Stefan Roese28ea29f2010-11-01 17:28:00 +0100788 }
789
790 /* Read block-size into temp buffer */
791 ret = read_block(inode, buff, block, dn);
792 if (ret) {
793 err = ret;
794 if (err != -ENOENT) {
795 free(buff);
796 break;
797 }
798 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100799
Stefan Roese28ea29f2010-11-01 17:28:00 +0100800 if (last_block_size)
801 dlen = last_block_size;
802 else
803 dlen = le32_to_cpu(dn->size);
804
805 /* Now copy required size back to dest */
806 memcpy(addr, buff, dlen);
807
808 free(buff);
809 } else {
810 ret = read_block(inode, addr, block, dn);
811 if (ret) {
812 err = ret;
813 if (err != -ENOENT)
814 break;
815 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100816 }
817 }
818 if (++i >= UBIFS_BLOCKS_PER_PAGE)
819 break;
820 block += 1;
821 addr += UBIFS_BLOCK_SIZE;
822 }
823 if (err) {
824 if (err == -ENOENT) {
825 /* Not found, so it must be a hole */
826 dbg_gen("hole");
827 goto out_free;
828 }
Heiko Schocher94b66de2015-10-22 06:19:21 +0200829 ubifs_err(c, "cannot read page %lu of inode %lu, error %d",
Stefan Roese2fc10f62009-03-19 15:35:05 +0100830 page->index, inode->i_ino, err);
831 goto error;
832 }
833
834out_free:
835 kfree(dn);
836out:
837 return 0;
838
839error:
840 kfree(dn);
841 return err;
842}
843
Hans de Goedea1644772015-09-17 18:46:56 -0400844int ubifs_read(const char *filename, void *buf, loff_t offset,
845 loff_t size, loff_t *actread)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100846{
847 struct ubifs_info *c = ubifs_sb->s_fs_info;
848 unsigned long inum;
849 struct inode *inode;
850 struct page page;
851 int err = 0;
852 int i;
853 int count;
Stefan Roese28ea29f2010-11-01 17:28:00 +0100854 int last_block_size = 0;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100855
Hans de Goedea1644772015-09-17 18:46:56 -0400856 *actread = 0;
857
858 if (offset & (PAGE_SIZE - 1)) {
Vagrant Cascadianbfdfd102016-10-23 20:45:16 -0700859 printf("ubifs: Error offset must be a multiple of %d\n",
Hans de Goedea1644772015-09-17 18:46:56 -0400860 PAGE_SIZE);
861 return -1;
862 }
863
Stefan Roese2fc10f62009-03-19 15:35:05 +0100864 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
Simon Kagstrom877501a2009-09-15 09:53:29 +0200865 /* ubifs_findfile will resolve symlinks, so we know that we get
866 * the real file here */
Hans de Goedea1644772015-09-17 18:46:56 -0400867 inum = ubifs_findfile(ubifs_sb, (char *)filename);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100868 if (!inum) {
869 err = -1;
870 goto out;
871 }
872
873 /*
874 * Read file inode
875 */
876 inode = ubifs_iget(ubifs_sb, inum);
877 if (IS_ERR(inode)) {
878 printf("%s: Error reading inode %ld!\n", __func__, inum);
879 err = PTR_ERR(inode);
880 goto out;
881 }
882
Hans de Goedea1644772015-09-17 18:46:56 -0400883 if (offset > inode->i_size) {
884 printf("ubifs: Error offset (%lld) > file-size (%lld)\n",
885 offset, size);
886 err = -1;
887 goto put_inode;
888 }
889
Stefan Roese2fc10f62009-03-19 15:35:05 +0100890 /*
Stefan Roese2fc10f62009-03-19 15:35:05 +0100891 * If no size was specified or if size bigger than filesize
892 * set size to filesize
893 */
Hans de Goedea1644772015-09-17 18:46:56 -0400894 if ((size == 0) || (size > (inode->i_size - offset)))
895 size = inode->i_size - offset;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100896
897 count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100898
Hans de Goedea1644772015-09-17 18:46:56 -0400899 page.addr = buf;
900 page.index = offset / PAGE_SIZE;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100901 page.inode = inode;
902 for (i = 0; i < count; i++) {
Stefan Roese28ea29f2010-11-01 17:28:00 +0100903 /*
904 * Make sure to not read beyond the requested size
905 */
906 if (((i + 1) == count) && (size < inode->i_size))
907 last_block_size = size - (i * PAGE_SIZE);
908
909 err = do_readpage(c, inode, &page, last_block_size);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100910 if (err)
911 break;
912
913 page.addr += PAGE_SIZE;
914 page.index++;
915 }
916
Hans de Goedea1644772015-09-17 18:46:56 -0400917 if (err) {
Stefan Roese2fc10f62009-03-19 15:35:05 +0100918 printf("Error reading file '%s'\n", filename);
Hans de Goedea1644772015-09-17 18:46:56 -0400919 *actread = i * PAGE_SIZE;
920 } else {
921 *actread = size;
Bastian Ruppertfd43edd2011-09-05 03:03:57 +0000922 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100923
Hans de Goedea1644772015-09-17 18:46:56 -0400924put_inode:
Stefan Roese2fc10f62009-03-19 15:35:05 +0100925 ubifs_iput(inode);
926
927out:
928 ubi_close_volume(c->ubi);
929 return err;
930}
Hans de Goedea1644772015-09-17 18:46:56 -0400931
Hans de Goedeb5030b22015-09-17 18:46:57 -0400932void ubifs_close(void)
933{
934}
935
Hans de Goedea1644772015-09-17 18:46:56 -0400936/* Compat wrappers for common/cmd_ubifs.c */
937int ubifs_load(char *filename, u32 addr, u32 size)
938{
939 loff_t actread;
940 int err;
941
942 printf("Loading file '%s' to addr 0x%08x...\n", filename, addr);
943
Siva Durga Prasad Paladugu67eccfb2017-05-30 14:29:06 +0200944 err = ubifs_read(filename, (void *)(uintptr_t)addr, 0, size, &actread);
Hans de Goedea1644772015-09-17 18:46:56 -0400945 if (err == 0) {
Simon Glass4d949a22017-08-03 12:22:10 -0600946 env_set_hex("filesize", actread);
Hans de Goedea1644772015-09-17 18:46:56 -0400947 printf("Done\n");
948 }
949
950 return err;
951}
952
953void uboot_ubifs_umount(void)
954{
955 if (ubifs_sb) {
956 printf("Unmounting UBIFS volume %s!\n",
957 ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name);
958 ubifs_umount(ubifs_sb->s_fs_info);
959 ubifs_sb = NULL;
960 }
961}