blob: 388451512a3d2a67dd854534afef7616dc696b6b [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 Glass313112a2019-08-01 09:46:46 -060015#include <env.h>
Simon Glass1a974af2019-08-01 09:46:36 -060016#include <gzip.h>
Simon Glassa87fc0a2015-09-02 17:24:57 -060017#include <memalign.h>
Stefan Roese2fc10f62009-03-19 15:35:05 +010018#include "ubifs.h"
Simon Glassd66c5f72020-02-03 07:36:15 -070019#include <dm/devres.h>
Ricardo Ribalda Delgadoa7a743e2009-04-27 18:33:33 +020020#include <u-boot/zlib.h>
Stefan Roese2fc10f62009-03-19 15:35:05 +010021
AKASHI Takahiro1d8d34d2019-11-13 09:44:47 +090022#include <linux/compat.h>
Heiko Schocherf5895d12014-06-24 10:10:04 +020023#include <linux/err.h>
24#include <linux/lzo.h>
25
Stefan Roese2fc10f62009-03-19 15:35:05 +010026DECLARE_GLOBAL_DATA_PTR;
27
28/* compress.c */
29
30/*
Ricardo Ribalda Delgadoa7a743e2009-04-27 18:33:33 +020031 * We need a wrapper for zunzip() because the parameters are
Stefan Roese2fc10f62009-03-19 15:35:05 +010032 * incompatible with the lzo decompressor.
33 */
34static int gzip_decompress(const unsigned char *in, size_t in_len,
35 unsigned char *out, size_t *out_len)
36{
Veli-Pekka Peltola7b7e1552012-09-05 18:05:14 +030037 return zunzip(out, *out_len, (unsigned char *)in,
38 (unsigned long *)out_len, 0, 0);
Stefan Roese2fc10f62009-03-19 15:35:05 +010039}
40
41/* Fake description object for the "none" compressor */
42static struct ubifs_compressor none_compr = {
43 .compr_type = UBIFS_COMPR_NONE,
Heiko Schocherf5895d12014-06-24 10:10:04 +020044 .name = "none",
Stefan Roese2fc10f62009-03-19 15:35:05 +010045 .capi_name = "",
46 .decompress = NULL,
47};
48
49static struct ubifs_compressor lzo_compr = {
50 .compr_type = UBIFS_COMPR_LZO,
Heiko Schocherf5895d12014-06-24 10:10:04 +020051#ifndef __UBOOT__
52 .comp_mutex = &lzo_mutex,
53#endif
54 .name = "lzo",
Stefan Roese2fc10f62009-03-19 15:35:05 +010055 .capi_name = "lzo",
56 .decompress = lzo1x_decompress_safe,
57};
58
59static struct ubifs_compressor zlib_compr = {
60 .compr_type = UBIFS_COMPR_ZLIB,
Heiko Schocherf5895d12014-06-24 10:10:04 +020061#ifndef __UBOOT__
62 .comp_mutex = &deflate_mutex,
63 .decomp_mutex = &inflate_mutex,
64#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +010065 .name = "zlib",
66 .capi_name = "deflate",
67 .decompress = gzip_decompress,
68};
69
70/* All UBIFS compressors */
71struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
72
Heiko Schocherf5895d12014-06-24 10:10:04 +020073
74#ifdef __UBOOT__
Heiko Schocherf5895d12014-06-24 10:10:04 +020075
76struct crypto_comp {
77 int compressor;
78};
79
Heiko Schocher94b66de2015-10-22 06:19:21 +020080static inline struct crypto_comp
81*crypto_alloc_comp(const char *alg_name, u32 type, u32 mask)
Heiko Schocherf5895d12014-06-24 10:10:04 +020082{
83 struct ubifs_compressor *comp;
84 struct crypto_comp *ptr;
85 int i = 0;
86
Marcel Ziswilerabc574b2015-08-18 13:06:37 +020087 ptr = malloc_cache_aligned(sizeof(struct crypto_comp));
Heiko Schocherf5895d12014-06-24 10:10:04 +020088 while (i < UBIFS_COMPR_TYPES_CNT) {
89 comp = ubifs_compressors[i];
90 if (!comp) {
91 i++;
92 continue;
93 }
94 if (strncmp(alg_name, comp->capi_name, strlen(alg_name)) == 0) {
95 ptr->compressor = i;
96 return ptr;
97 }
98 i++;
99 }
100 if (i >= UBIFS_COMPR_TYPES_CNT) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200101 dbg_gen("invalid compression type %s", alg_name);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200102 free (ptr);
103 return NULL;
104 }
105 return ptr;
106}
Heiko Schocher94b66de2015-10-22 06:19:21 +0200107static inline int
108crypto_comp_decompress(const struct ubifs_info *c, struct crypto_comp *tfm,
109 const u8 *src, unsigned int slen, u8 *dst,
110 unsigned int *dlen)
Heiko Schocherf5895d12014-06-24 10:10:04 +0200111{
112 struct ubifs_compressor *compr = ubifs_compressors[tfm->compressor];
113 int err;
Paul Davey7f918382018-11-05 18:09:29 +1300114 size_t tmp_len = *dlen;
Heiko Schocherf5895d12014-06-24 10:10:04 +0200115
116 if (compr->compr_type == UBIFS_COMPR_NONE) {
117 memcpy(dst, src, slen);
118 *dlen = slen;
119 return 0;
120 }
121
Paul Davey7f918382018-11-05 18:09:29 +1300122 err = compr->decompress(src, slen, dst, &tmp_len);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200123 if (err)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200124 ubifs_err(c, "cannot decompress %d bytes, compressor %s, "
Heiko Schocherf5895d12014-06-24 10:10:04 +0200125 "error %d", slen, compr->name, err);
126
Paul Davey7f918382018-11-05 18:09:29 +1300127 *dlen = tmp_len;
Heiko Schocherf5895d12014-06-24 10:10:04 +0200128 return err;
129
130 return 0;
131}
Anton Habegger62e79dd2015-01-22 22:29:10 +0100132
133/* from shrinker.c */
134
135/* Global clean znode counter (for all mounted UBIFS instances) */
136atomic_long_t ubifs_clean_zn_cnt;
137
Heiko Schocherf5895d12014-06-24 10:10:04 +0200138#endif
139
Stefan Roese2fc10f62009-03-19 15:35:05 +0100140/**
141 * ubifs_decompress - decompress data.
142 * @in_buf: data to decompress
143 * @in_len: length of the data to decompress
144 * @out_buf: output buffer where decompressed data should
145 * @out_len: output length is returned here
146 * @compr_type: type of compression
147 *
148 * This function decompresses data from buffer @in_buf into buffer @out_buf.
149 * The length of the uncompressed data is returned in @out_len. This functions
150 * returns %0 on success or a negative error code on failure.
151 */
Heiko Schocher94b66de2015-10-22 06:19:21 +0200152int ubifs_decompress(const struct ubifs_info *c, const void *in_buf,
153 int in_len, void *out_buf, int *out_len, int compr_type)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100154{
155 int err;
156 struct ubifs_compressor *compr;
157
158 if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200159 ubifs_err(c, "invalid compression type %d", compr_type);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100160 return -EINVAL;
161 }
162
163 compr = ubifs_compressors[compr_type];
164
165 if (unlikely(!compr->capi_name)) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200166 ubifs_err(c, "%s compression is not compiled in", compr->name);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100167 return -EINVAL;
168 }
169
170 if (compr_type == UBIFS_COMPR_NONE) {
171 memcpy(out_buf, in_buf, in_len);
172 *out_len = in_len;
173 return 0;
174 }
175
Heiko Schocherf5895d12014-06-24 10:10:04 +0200176 if (compr->decomp_mutex)
177 mutex_lock(compr->decomp_mutex);
Heiko Schocher94b66de2015-10-22 06:19:21 +0200178 err = crypto_comp_decompress(c, compr->cc, in_buf, in_len, out_buf,
Heiko Schocherf5895d12014-06-24 10:10:04 +0200179 (unsigned int *)out_len);
180 if (compr->decomp_mutex)
181 mutex_unlock(compr->decomp_mutex);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100182 if (err)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200183 ubifs_err(c, "cannot decompress %d bytes, compressor %s,"
184 " error %d", in_len, compr->name, err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100185
186 return err;
187}
188
189/**
190 * compr_init - initialize a compressor.
191 * @compr: compressor description object
192 *
193 * This function initializes the requested compressor and returns zero in case
194 * of success or a negative error code in case of failure.
195 */
196static int __init compr_init(struct ubifs_compressor *compr)
197{
198 ubifs_compressors[compr->compr_type] = compr;
Peter Tyser9057cbf2009-09-21 11:20:36 -0500199
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200200#ifdef CONFIG_NEEDS_MANUAL_RELOC
Stefan Roese2fc10f62009-03-19 15:35:05 +0100201 ubifs_compressors[compr->compr_type]->name += gd->reloc_off;
202 ubifs_compressors[compr->compr_type]->capi_name += gd->reloc_off;
203 ubifs_compressors[compr->compr_type]->decompress += gd->reloc_off;
Peter Tyser9057cbf2009-09-21 11:20:36 -0500204#endif
205
Heiko Schocherf5895d12014-06-24 10:10:04 +0200206 if (compr->capi_name) {
207 compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
208 if (IS_ERR(compr->cc)) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200209 dbg_gen("cannot initialize compressor %s,"
210 " error %ld", compr->name,
211 PTR_ERR(compr->cc));
Heiko Schocherf5895d12014-06-24 10:10:04 +0200212 return PTR_ERR(compr->cc);
213 }
214 }
215
Stefan Roese2fc10f62009-03-19 15:35:05 +0100216 return 0;
217}
218
219/**
220 * ubifs_compressors_init - initialize UBIFS compressors.
221 *
222 * This function initializes the compressor which were compiled in. Returns
223 * zero in case of success and a negative error code in case of failure.
224 */
225int __init ubifs_compressors_init(void)
226{
227 int err;
228
229 err = compr_init(&lzo_compr);
230 if (err)
231 return err;
232
233 err = compr_init(&zlib_compr);
234 if (err)
235 return err;
236
Michael Lawnickb0617012009-03-19 10:06:41 +0100237 err = compr_init(&none_compr);
238 if (err)
239 return err;
240
Stefan Roese2fc10f62009-03-19 15:35:05 +0100241 return 0;
242}
243
244/*
245 * ubifsls...
246 */
247
248static int filldir(struct ubifs_info *c, const char *name, int namlen,
249 u64 ino, unsigned int d_type)
250{
251 struct inode *inode;
252 char filetime[32];
253
254 switch (d_type) {
255 case UBIFS_ITYPE_REG:
256 printf("\t");
257 break;
258 case UBIFS_ITYPE_DIR:
259 printf("<DIR>\t");
260 break;
261 case UBIFS_ITYPE_LNK:
262 printf("<LNK>\t");
263 break;
264 default:
265 printf("other\t");
266 break;
267 }
268
269 inode = ubifs_iget(c->vfs_sb, ino);
270 if (IS_ERR(inode)) {
271 printf("%s: Error in ubifs_iget(), ino=%lld ret=%p!\n",
272 __func__, ino, inode);
273 return -1;
274 }
275 ctime_r((time_t *)&inode->i_mtime, filetime);
276 printf("%9lld %24.24s ", inode->i_size, filetime);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200277#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100278 ubifs_iput(inode);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200279#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100280
281 printf("%s\n", name);
282
283 return 0;
284}
285
286static int ubifs_printdir(struct file *file, void *dirent)
287{
288 int err, over = 0;
289 struct qstr nm;
290 union ubifs_key key;
291 struct ubifs_dent_node *dent;
292 struct inode *dir = file->f_path.dentry->d_inode;
293 struct ubifs_info *c = dir->i_sb->s_fs_info;
294
295 dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
296
297 if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
298 /*
299 * The directory was seek'ed to a senseless position or there
300 * are no more entries.
301 */
302 return 0;
303
304 if (file->f_pos == 1) {
305 /* Find the first entry in TNC and save it */
306 lowest_dent_key(c, &key, dir->i_ino);
307 nm.name = NULL;
308 dent = ubifs_tnc_next_ent(c, &key, &nm);
309 if (IS_ERR(dent)) {
310 err = PTR_ERR(dent);
311 goto out;
312 }
313
314 file->f_pos = key_hash_flash(c, &dent->key);
315 file->private_data = dent;
316 }
317
318 dent = file->private_data;
319 if (!dent) {
320 /*
321 * The directory was seek'ed to and is now readdir'ed.
322 * Find the entry corresponding to @file->f_pos or the
323 * closest one.
324 */
325 dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
326 nm.name = NULL;
327 dent = ubifs_tnc_next_ent(c, &key, &nm);
328 if (IS_ERR(dent)) {
329 err = PTR_ERR(dent);
330 goto out;
331 }
332 file->f_pos = key_hash_flash(c, &dent->key);
333 file->private_data = dent;
334 }
335
336 while (1) {
337 dbg_gen("feed '%s', ino %llu, new f_pos %#x",
338 dent->name, (unsigned long long)le64_to_cpu(dent->inum),
339 key_hash_flash(c, &dent->key));
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200340#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100341 ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200342#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100343
344 nm.len = le16_to_cpu(dent->nlen);
345 over = filldir(c, (char *)dent->name, nm.len,
346 le64_to_cpu(dent->inum), dent->type);
347 if (over)
348 return 0;
349
350 /* Switch to the next entry */
351 key_read(c, &dent->key, &key);
352 nm.name = (char *)dent->name;
353 dent = ubifs_tnc_next_ent(c, &key, &nm);
354 if (IS_ERR(dent)) {
355 err = PTR_ERR(dent);
356 goto out;
357 }
358
359 kfree(file->private_data);
360 file->f_pos = key_hash_flash(c, &dent->key);
361 file->private_data = dent;
362 cond_resched();
363 }
364
365out:
366 if (err != -ENOENT) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200367 ubifs_err(c, "cannot find next direntry, error %d", err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100368 return err;
369 }
370
371 kfree(file->private_data);
372 file->private_data = NULL;
373 file->f_pos = 2;
374 return 0;
375}
376
377static int ubifs_finddir(struct super_block *sb, char *dirname,
378 unsigned long root_inum, unsigned long *inum)
379{
380 int err;
381 struct qstr nm;
382 union ubifs_key key;
383 struct ubifs_dent_node *dent;
384 struct ubifs_info *c;
385 struct file *file;
386 struct dentry *dentry;
387 struct inode *dir;
Stefan Roeseac3244a2012-08-28 14:00:24 +0200388 int ret = 0;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100389
390 file = kzalloc(sizeof(struct file), 0);
391 dentry = kzalloc(sizeof(struct dentry), 0);
392 dir = kzalloc(sizeof(struct inode), 0);
393 if (!file || !dentry || !dir) {
394 printf("%s: Error, no memory for malloc!\n", __func__);
395 err = -ENOMEM;
396 goto out;
397 }
398
399 dir->i_sb = sb;
400 file->f_path.dentry = dentry;
401 file->f_path.dentry->d_parent = dentry;
402 file->f_path.dentry->d_inode = dir;
403 file->f_path.dentry->d_inode->i_ino = root_inum;
404 c = sb->s_fs_info;
405
406 dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
407
408 /* Find the first entry in TNC and save it */
409 lowest_dent_key(c, &key, dir->i_ino);
410 nm.name = NULL;
411 dent = ubifs_tnc_next_ent(c, &key, &nm);
412 if (IS_ERR(dent)) {
413 err = PTR_ERR(dent);
414 goto out;
415 }
416
417 file->f_pos = key_hash_flash(c, &dent->key);
418 file->private_data = dent;
419
420 while (1) {
421 dbg_gen("feed '%s', ino %llu, new f_pos %#x",
422 dent->name, (unsigned long long)le64_to_cpu(dent->inum),
423 key_hash_flash(c, &dent->key));
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200424#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100425 ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200426#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100427
428 nm.len = le16_to_cpu(dent->nlen);
429 if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
430 (strlen(dirname) == nm.len)) {
431 *inum = le64_to_cpu(dent->inum);
Stefan Roeseac3244a2012-08-28 14:00:24 +0200432 ret = 1;
433 goto out_free;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100434 }
435
436 /* Switch to the next entry */
437 key_read(c, &dent->key, &key);
438 nm.name = (char *)dent->name;
439 dent = ubifs_tnc_next_ent(c, &key, &nm);
440 if (IS_ERR(dent)) {
441 err = PTR_ERR(dent);
442 goto out;
443 }
444
445 kfree(file->private_data);
446 file->f_pos = key_hash_flash(c, &dent->key);
447 file->private_data = dent;
448 cond_resched();
449 }
450
451out:
Stefan Roeseac3244a2012-08-28 14:00:24 +0200452 if (err != -ENOENT)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200453 dbg_gen("cannot find next direntry, error %d", err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100454
Stefan Roeseac3244a2012-08-28 14:00:24 +0200455out_free:
Heinrich Schuchardte9892792017-11-08 22:28:47 +0100456 kfree(file->private_data);
457 free(file);
458 free(dentry);
459 free(dir);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100460
Stefan Roeseac3244a2012-08-28 14:00:24 +0200461 return ret;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100462}
463
464static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
465{
466 int ret;
467 char *next;
468 char fpath[128];
Simon Kagstrom877501a2009-09-15 09:53:29 +0200469 char symlinkpath[128];
Stefan Roese2fc10f62009-03-19 15:35:05 +0100470 char *name = fpath;
471 unsigned long root_inum = 1;
472 unsigned long inum;
Simon Kagstrom877501a2009-09-15 09:53:29 +0200473 int symlink_count = 0; /* Don't allow symlink recursion */
Ricardo Ribalda Delgado4a2e69c2010-12-02 15:02:35 +0100474 char link_name[64];
Stefan Roese2fc10f62009-03-19 15:35:05 +0100475
476 strcpy(fpath, filename);
477
478 /* Remove all leading slashes */
479 while (*name == '/')
480 name++;
481
482 /*
483 * Handle root-direcoty ('/')
484 */
485 inum = root_inum;
486 if (!name || *name == '\0')
487 return inum;
488
489 for (;;) {
Simon Kagstrom877501a2009-09-15 09:53:29 +0200490 struct inode *inode;
491 struct ubifs_inode *ui;
492
Stefan Roese2fc10f62009-03-19 15:35:05 +0100493 /* Extract the actual part from the pathname. */
494 next = strchr(name, '/');
495 if (next) {
496 /* Remove all leading slashes. */
497 while (*next == '/')
498 *(next++) = '\0';
499 }
500
501 ret = ubifs_finddir(sb, name, root_inum, &inum);
Simon Kagstrom877501a2009-09-15 09:53:29 +0200502 if (!ret)
503 return 0;
504 inode = ubifs_iget(sb, inum);
505
506 if (!inode)
507 return 0;
508 ui = ubifs_inode(inode);
509
510 if ((inode->i_mode & S_IFMT) == S_IFLNK) {
Simon Kagstrom877501a2009-09-15 09:53:29 +0200511 char buf[128];
512
513 /* We have some sort of symlink recursion, bail out */
514 if (symlink_count++ > 8) {
515 printf("Symlink recursion, aborting\n");
516 return 0;
517 }
518 memcpy(link_name, ui->data, ui->data_len);
519 link_name[ui->data_len] = '\0';
520
521 if (link_name[0] == '/') {
522 /* Absolute path, redo everything without
523 * the leading slash */
524 next = name = link_name + 1;
525 root_inum = 1;
526 continue;
527 }
528 /* Relative to cur dir */
Simon Kagstrom84167362009-09-25 14:05:57 +0200529 sprintf(buf, "%s/%s",
Simon Kagstrom877501a2009-09-15 09:53:29 +0200530 link_name, next == NULL ? "" : next);
531 memcpy(symlinkpath, buf, sizeof(buf));
532 next = name = symlinkpath;
533 continue;
534 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100535
536 /*
537 * Check if directory with this name exists
538 */
539
540 /* Found the node! */
Simon Kagstrom877501a2009-09-15 09:53:29 +0200541 if (!next || *next == '\0')
542 return inum;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100543
544 root_inum = inum;
545 name = next;
546 }
547
548 return 0;
549}
550
Simon Glasse3394752016-02-29 15:25:34 -0700551int ubifs_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info)
Hans de Goedeb5030b22015-09-17 18:46:57 -0400552{
553 if (rbdd) {
554 debug("UBIFS cannot be used with normal block devices\n");
555 return -1;
556 }
557
558 /*
Simon Glasse76ee972016-02-29 15:25:44 -0700559 * Should never happen since blk_get_device_part_str() already checks
Hans de Goedeb5030b22015-09-17 18:46:57 -0400560 * this, but better safe then sorry.
561 */
562 if (!ubifs_is_mounted()) {
563 debug("UBIFS not mounted, use ubifsmount to mount volume first!\n");
564 return -1;
565 }
566
567 return 0;
568}
569
Hans de Goedea1644772015-09-17 18:46:56 -0400570int ubifs_ls(const char *filename)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100571{
572 struct ubifs_info *c = ubifs_sb->s_fs_info;
573 struct file *file;
574 struct dentry *dentry;
575 struct inode *dir;
576 void *dirent = NULL;
577 unsigned long inum;
578 int ret = 0;
579
580 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
Hans de Goedea1644772015-09-17 18:46:56 -0400581 inum = ubifs_findfile(ubifs_sb, (char *)filename);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100582 if (!inum) {
583 ret = -1;
584 goto out;
585 }
586
587 file = kzalloc(sizeof(struct file), 0);
588 dentry = kzalloc(sizeof(struct dentry), 0);
589 dir = kzalloc(sizeof(struct inode), 0);
590 if (!file || !dentry || !dir) {
591 printf("%s: Error, no memory for malloc!\n", __func__);
592 ret = -ENOMEM;
593 goto out_mem;
594 }
595
596 dir->i_sb = ubifs_sb;
597 file->f_path.dentry = dentry;
598 file->f_path.dentry->d_parent = dentry;
599 file->f_path.dentry->d_inode = dir;
600 file->f_path.dentry->d_inode->i_ino = inum;
601 file->f_pos = 1;
602 file->private_data = NULL;
603 ubifs_printdir(file, dirent);
604
605out_mem:
606 if (file)
607 free(file);
608 if (dentry)
609 free(dentry);
610 if (dir)
611 free(dir);
612
613out:
614 ubi_close_volume(c->ubi);
615 return ret;
616}
617
Hans de Goedeb5030b22015-09-17 18:46:57 -0400618int ubifs_exists(const char *filename)
619{
620 struct ubifs_info *c = ubifs_sb->s_fs_info;
621 unsigned long inum;
622
623 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
624 inum = ubifs_findfile(ubifs_sb, (char *)filename);
625 ubi_close_volume(c->ubi);
626
627 return inum != 0;
628}
629
630int ubifs_size(const char *filename, loff_t *size)
631{
632 struct ubifs_info *c = ubifs_sb->s_fs_info;
633 unsigned long inum;
634 struct inode *inode;
635 int err = 0;
636
637 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
638
639 inum = ubifs_findfile(ubifs_sb, (char *)filename);
640 if (!inum) {
641 err = -1;
642 goto out;
643 }
644
645 inode = ubifs_iget(ubifs_sb, inum);
646 if (IS_ERR(inode)) {
647 printf("%s: Error reading inode %ld!\n", __func__, inum);
648 err = PTR_ERR(inode);
649 goto out;
650 }
651
652 *size = inode->i_size;
653
654 ubifs_iput(inode);
655out:
656 ubi_close_volume(c->ubi);
657 return err;
658}
659
Stefan Roese2fc10f62009-03-19 15:35:05 +0100660/*
661 * ubifsload...
662 */
663
664/* file.c */
665
666static inline void *kmap(struct page *page)
667{
668 return page->addr;
669}
670
671static int read_block(struct inode *inode, void *addr, unsigned int block,
672 struct ubifs_data_node *dn)
673{
674 struct ubifs_info *c = inode->i_sb->s_fs_info;
675 int err, len, out_len;
676 union ubifs_key key;
677 unsigned int dlen;
678
679 data_key_init(c, &key, inode->i_ino, block);
680 err = ubifs_tnc_lookup(c, &key, dn);
681 if (err) {
682 if (err == -ENOENT)
683 /* Not found, so it must be a hole */
684 memset(addr, 0, UBIFS_BLOCK_SIZE);
685 return err;
686 }
687
688 ubifs_assert(le64_to_cpu(dn->ch.sqnum) > ubifs_inode(inode)->creat_sqnum);
689
690 len = le32_to_cpu(dn->size);
691 if (len <= 0 || len > UBIFS_BLOCK_SIZE)
692 goto dump;
693
694 dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
695 out_len = UBIFS_BLOCK_SIZE;
Heiko Schocher94b66de2015-10-22 06:19:21 +0200696 err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
Stefan Roese2fc10f62009-03-19 15:35:05 +0100697 le16_to_cpu(dn->compr_type));
698 if (err || len != out_len)
699 goto dump;
700
701 /*
702 * Data length can be less than a full block, even for blocks that are
703 * not the last in the file (e.g., as a result of making a hole and
704 * appending data). Ensure that the remainder is zeroed out.
705 */
706 if (len < UBIFS_BLOCK_SIZE)
707 memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
708
709 return 0;
710
711dump:
Heiko Schocher94b66de2015-10-22 06:19:21 +0200712 ubifs_err(c, "bad data node (block %u, inode %lu)",
Stefan Roese2fc10f62009-03-19 15:35:05 +0100713 block, inode->i_ino);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200714 ubifs_dump_node(c, dn);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100715 return -EINVAL;
716}
717
Stefan Roese28ea29f2010-11-01 17:28:00 +0100718static int do_readpage(struct ubifs_info *c, struct inode *inode,
719 struct page *page, int last_block_size)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100720{
721 void *addr;
722 int err = 0, i;
723 unsigned int block, beyond;
724 struct ubifs_data_node *dn;
725 loff_t i_size = inode->i_size;
726
727 dbg_gen("ino %lu, pg %lu, i_size %lld",
728 inode->i_ino, page->index, i_size);
729
730 addr = kmap(page);
731
732 block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
733 beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
734 if (block >= beyond) {
735 /* Reading beyond inode */
736 memset(addr, 0, PAGE_CACHE_SIZE);
737 goto out;
738 }
739
740 dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
Daniel Mackb5775802009-06-04 19:44:12 +0200741 if (!dn)
742 return -ENOMEM;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100743
744 i = 0;
745 while (1) {
746 int ret;
747
748 if (block >= beyond) {
749 /* Reading beyond inode */
750 err = -ENOENT;
751 memset(addr, 0, UBIFS_BLOCK_SIZE);
752 } else {
Stefan Roese28ea29f2010-11-01 17:28:00 +0100753 /*
754 * Reading last block? Make sure to not write beyond
755 * the requested size in the destination buffer.
756 */
757 if (((block + 1) == beyond) || last_block_size) {
758 void *buff;
759 int dlen;
760
761 /*
762 * We need to buffer the data locally for the
763 * last block. This is to not pad the
764 * destination area to a multiple of
765 * UBIFS_BLOCK_SIZE.
766 */
Marcel Ziswilerabc574b2015-08-18 13:06:37 +0200767 buff = malloc_cache_aligned(UBIFS_BLOCK_SIZE);
Stefan Roese28ea29f2010-11-01 17:28:00 +0100768 if (!buff) {
769 printf("%s: Error, malloc fails!\n",
770 __func__);
771 err = -ENOMEM;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100772 break;
Stefan Roese28ea29f2010-11-01 17:28:00 +0100773 }
774
775 /* Read block-size into temp buffer */
776 ret = read_block(inode, buff, block, dn);
777 if (ret) {
778 err = ret;
779 if (err != -ENOENT) {
780 free(buff);
781 break;
782 }
783 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100784
Stefan Roese28ea29f2010-11-01 17:28:00 +0100785 if (last_block_size)
786 dlen = last_block_size;
787 else
788 dlen = le32_to_cpu(dn->size);
789
790 /* Now copy required size back to dest */
791 memcpy(addr, buff, dlen);
792
793 free(buff);
794 } else {
795 ret = read_block(inode, addr, block, dn);
796 if (ret) {
797 err = ret;
798 if (err != -ENOENT)
799 break;
800 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100801 }
802 }
803 if (++i >= UBIFS_BLOCKS_PER_PAGE)
804 break;
805 block += 1;
806 addr += UBIFS_BLOCK_SIZE;
807 }
808 if (err) {
809 if (err == -ENOENT) {
810 /* Not found, so it must be a hole */
811 dbg_gen("hole");
812 goto out_free;
813 }
Heiko Schocher94b66de2015-10-22 06:19:21 +0200814 ubifs_err(c, "cannot read page %lu of inode %lu, error %d",
Stefan Roese2fc10f62009-03-19 15:35:05 +0100815 page->index, inode->i_ino, err);
816 goto error;
817 }
818
819out_free:
820 kfree(dn);
821out:
822 return 0;
823
824error:
825 kfree(dn);
826 return err;
827}
828
Hans de Goedea1644772015-09-17 18:46:56 -0400829int ubifs_read(const char *filename, void *buf, loff_t offset,
830 loff_t size, loff_t *actread)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100831{
832 struct ubifs_info *c = ubifs_sb->s_fs_info;
833 unsigned long inum;
834 struct inode *inode;
835 struct page page;
836 int err = 0;
837 int i;
838 int count;
Stefan Roese28ea29f2010-11-01 17:28:00 +0100839 int last_block_size = 0;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100840
Hans de Goedea1644772015-09-17 18:46:56 -0400841 *actread = 0;
842
843 if (offset & (PAGE_SIZE - 1)) {
Vagrant Cascadianbfdfd102016-10-23 20:45:16 -0700844 printf("ubifs: Error offset must be a multiple of %d\n",
Hans de Goedea1644772015-09-17 18:46:56 -0400845 PAGE_SIZE);
846 return -1;
847 }
848
Stefan Roese2fc10f62009-03-19 15:35:05 +0100849 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
Simon Kagstrom877501a2009-09-15 09:53:29 +0200850 /* ubifs_findfile will resolve symlinks, so we know that we get
851 * the real file here */
Hans de Goedea1644772015-09-17 18:46:56 -0400852 inum = ubifs_findfile(ubifs_sb, (char *)filename);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100853 if (!inum) {
854 err = -1;
855 goto out;
856 }
857
858 /*
859 * Read file inode
860 */
861 inode = ubifs_iget(ubifs_sb, inum);
862 if (IS_ERR(inode)) {
863 printf("%s: Error reading inode %ld!\n", __func__, inum);
864 err = PTR_ERR(inode);
865 goto out;
866 }
867
Hans de Goedea1644772015-09-17 18:46:56 -0400868 if (offset > inode->i_size) {
869 printf("ubifs: Error offset (%lld) > file-size (%lld)\n",
870 offset, size);
871 err = -1;
872 goto put_inode;
873 }
874
Stefan Roese2fc10f62009-03-19 15:35:05 +0100875 /*
Stefan Roese2fc10f62009-03-19 15:35:05 +0100876 * If no size was specified or if size bigger than filesize
877 * set size to filesize
878 */
Hans de Goedea1644772015-09-17 18:46:56 -0400879 if ((size == 0) || (size > (inode->i_size - offset)))
880 size = inode->i_size - offset;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100881
882 count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100883
Hans de Goedea1644772015-09-17 18:46:56 -0400884 page.addr = buf;
885 page.index = offset / PAGE_SIZE;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100886 page.inode = inode;
887 for (i = 0; i < count; i++) {
Stefan Roese28ea29f2010-11-01 17:28:00 +0100888 /*
889 * Make sure to not read beyond the requested size
890 */
891 if (((i + 1) == count) && (size < inode->i_size))
892 last_block_size = size - (i * PAGE_SIZE);
893
894 err = do_readpage(c, inode, &page, last_block_size);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100895 if (err)
896 break;
897
898 page.addr += PAGE_SIZE;
899 page.index++;
900 }
901
Hans de Goedea1644772015-09-17 18:46:56 -0400902 if (err) {
Stefan Roese2fc10f62009-03-19 15:35:05 +0100903 printf("Error reading file '%s'\n", filename);
Hans de Goedea1644772015-09-17 18:46:56 -0400904 *actread = i * PAGE_SIZE;
905 } else {
906 *actread = size;
Bastian Ruppertfd43edd2011-09-05 03:03:57 +0000907 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100908
Hans de Goedea1644772015-09-17 18:46:56 -0400909put_inode:
Stefan Roese2fc10f62009-03-19 15:35:05 +0100910 ubifs_iput(inode);
911
912out:
913 ubi_close_volume(c->ubi);
914 return err;
915}
Hans de Goedea1644772015-09-17 18:46:56 -0400916
Hans de Goedeb5030b22015-09-17 18:46:57 -0400917void ubifs_close(void)
918{
919}
920
Hans de Goedea1644772015-09-17 18:46:56 -0400921/* Compat wrappers for common/cmd_ubifs.c */
922int ubifs_load(char *filename, u32 addr, u32 size)
923{
924 loff_t actread;
925 int err;
926
927 printf("Loading file '%s' to addr 0x%08x...\n", filename, addr);
928
Siva Durga Prasad Paladugu67eccfb2017-05-30 14:29:06 +0200929 err = ubifs_read(filename, (void *)(uintptr_t)addr, 0, size, &actread);
Hans de Goedea1644772015-09-17 18:46:56 -0400930 if (err == 0) {
Simon Glass4d949a22017-08-03 12:22:10 -0600931 env_set_hex("filesize", actread);
Hans de Goedea1644772015-09-17 18:46:56 -0400932 printf("Done\n");
933 }
934
935 return err;
936}
937
938void uboot_ubifs_umount(void)
939{
940 if (ubifs_sb) {
941 printf("Unmounting UBIFS volume %s!\n",
942 ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name);
943 ubifs_umount(ubifs_sb->s_fs_info);
944 ubifs_sb = NULL;
945 }
946}