blob: f0ea7e5c1682d8a9866e7a38b4793e421e7f3f0d [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 Glass313112a2019-08-01 09:46:46 -060014#include <env.h>
Simon Glass1a974af2019-08-01 09:46:36 -060015#include <gzip.h>
Simon Glass0f2af882020-05-10 11:40:05 -060016#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070017#include <malloc.h>
Simon Glassa87fc0a2015-09-02 17:24:57 -060018#include <memalign.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060019#include <asm/global_data.h>
Stefan Roese2fc10f62009-03-19 15:35:05 +010020#include "ubifs.h"
Simon Glass655306c2020-05-10 11:39:58 -060021#include <part.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070022#include <dm/devres.h>
Ricardo Ribalda Delgadoa7a743e2009-04-27 18:33:33 +020023#include <u-boot/zlib.h>
Stefan Roese2fc10f62009-03-19 15:35:05 +010024
AKASHI Takahiro1d8d34d2019-11-13 09:44:47 +090025#include <linux/compat.h>
Heiko Schocherf5895d12014-06-24 10:10:04 +020026#include <linux/err.h>
27#include <linux/lzo.h>
28
Piotr Wojtaszczyke60ab9a2024-05-28 17:05:28 +020029#if IS_ENABLED(CONFIG_ZSTD)
30#include <linux/zstd.h>
31#include <abuf.h>
32#endif
33
Stefan Roese2fc10f62009-03-19 15:35:05 +010034DECLARE_GLOBAL_DATA_PTR;
35
36/* compress.c */
37
38/*
Ricardo Ribalda Delgadoa7a743e2009-04-27 18:33:33 +020039 * We need a wrapper for zunzip() because the parameters are
Stefan Roese2fc10f62009-03-19 15:35:05 +010040 * incompatible with the lzo decompressor.
41 */
42static int gzip_decompress(const unsigned char *in, size_t in_len,
43 unsigned char *out, size_t *out_len)
44{
Veli-Pekka Peltola7b7e1552012-09-05 18:05:14 +030045 return zunzip(out, *out_len, (unsigned char *)in,
46 (unsigned long *)out_len, 0, 0);
Stefan Roese2fc10f62009-03-19 15:35:05 +010047}
48
Piotr Wojtaszczyke60ab9a2024-05-28 17:05:28 +020049#if IS_ENABLED(CONFIG_ZSTD)
50static int zstd_decompress_wrapper(const unsigned char *in, size_t in_len,
51 unsigned char *out, size_t *out_len)
52{
53 struct abuf abuf_in, abuf_out;
54 int ret;
55
56 abuf_init_set(&abuf_in, (void *)in, in_len);
57 abuf_init_set(&abuf_out, (void *)out, *out_len);
58
59 ret = zstd_decompress(&abuf_in, &abuf_out);
60 if (ret < 0)
61 return ret;
62
63 *out_len = ret;
64 return 0;
65}
66#endif
67
Stefan Roese2fc10f62009-03-19 15:35:05 +010068/* Fake description object for the "none" compressor */
69static struct ubifs_compressor none_compr = {
70 .compr_type = UBIFS_COMPR_NONE,
Heiko Schocherf5895d12014-06-24 10:10:04 +020071 .name = "none",
Stefan Roese2fc10f62009-03-19 15:35:05 +010072 .capi_name = "",
73 .decompress = NULL,
74};
75
76static struct ubifs_compressor lzo_compr = {
77 .compr_type = UBIFS_COMPR_LZO,
Heiko Schocherf5895d12014-06-24 10:10:04 +020078#ifndef __UBOOT__
79 .comp_mutex = &lzo_mutex,
80#endif
81 .name = "lzo",
Stefan Roese2fc10f62009-03-19 15:35:05 +010082 .capi_name = "lzo",
83 .decompress = lzo1x_decompress_safe,
84};
85
86static struct ubifs_compressor zlib_compr = {
87 .compr_type = UBIFS_COMPR_ZLIB,
Heiko Schocherf5895d12014-06-24 10:10:04 +020088#ifndef __UBOOT__
89 .comp_mutex = &deflate_mutex,
90 .decomp_mutex = &inflate_mutex,
91#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +010092 .name = "zlib",
93 .capi_name = "deflate",
94 .decompress = gzip_decompress,
95};
Piotr Wojtaszczyke60ab9a2024-05-28 17:05:28 +020096
97#if IS_ENABLED(CONFIG_ZSTD)
98static struct ubifs_compressor zstd_compr = {
99 .compr_type = UBIFS_COMPR_ZSTD,
100#ifndef __UBOOT__
101 .comp_mutex = &zstd_enc_mutex,
102 .decomp_mutex = &zstd_dec_mutex,
103#endif
104 .name = "zstd",
105 .capi_name = "zstd",
106 .decompress = zstd_decompress_wrapper,
107};
108#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100109
110/* All UBIFS compressors */
Piotr Wojtaszczyke60ab9a2024-05-28 17:05:28 +0200111struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT] = {NULL};
Stefan Roese2fc10f62009-03-19 15:35:05 +0100112
Heiko Schocherf5895d12014-06-24 10:10:04 +0200113
114#ifdef __UBOOT__
Heiko Schocherf5895d12014-06-24 10:10:04 +0200115
116struct crypto_comp {
117 int compressor;
118};
119
Heiko Schocher94b66de2015-10-22 06:19:21 +0200120static inline struct crypto_comp
121*crypto_alloc_comp(const char *alg_name, u32 type, u32 mask)
Heiko Schocherf5895d12014-06-24 10:10:04 +0200122{
123 struct ubifs_compressor *comp;
124 struct crypto_comp *ptr;
125 int i = 0;
126
Marcel Ziswilerabc574b2015-08-18 13:06:37 +0200127 ptr = malloc_cache_aligned(sizeof(struct crypto_comp));
Heiko Schocherf5895d12014-06-24 10:10:04 +0200128 while (i < UBIFS_COMPR_TYPES_CNT) {
129 comp = ubifs_compressors[i];
130 if (!comp) {
131 i++;
132 continue;
133 }
134 if (strncmp(alg_name, comp->capi_name, strlen(alg_name)) == 0) {
135 ptr->compressor = i;
136 return ptr;
137 }
138 i++;
139 }
140 if (i >= UBIFS_COMPR_TYPES_CNT) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200141 dbg_gen("invalid compression type %s", alg_name);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200142 free (ptr);
143 return NULL;
144 }
145 return ptr;
146}
Heiko Schocher94b66de2015-10-22 06:19:21 +0200147static inline int
148crypto_comp_decompress(const struct ubifs_info *c, struct crypto_comp *tfm,
149 const u8 *src, unsigned int slen, u8 *dst,
150 unsigned int *dlen)
Heiko Schocherf5895d12014-06-24 10:10:04 +0200151{
152 struct ubifs_compressor *compr = ubifs_compressors[tfm->compressor];
153 int err;
Paul Davey7f918382018-11-05 18:09:29 +1300154 size_t tmp_len = *dlen;
Heiko Schocherf5895d12014-06-24 10:10:04 +0200155
156 if (compr->compr_type == UBIFS_COMPR_NONE) {
157 memcpy(dst, src, slen);
158 *dlen = slen;
159 return 0;
160 }
161
Paul Davey7f918382018-11-05 18:09:29 +1300162 err = compr->decompress(src, slen, dst, &tmp_len);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200163 if (err)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200164 ubifs_err(c, "cannot decompress %d bytes, compressor %s, "
Heiko Schocherf5895d12014-06-24 10:10:04 +0200165 "error %d", slen, compr->name, err);
166
Paul Davey7f918382018-11-05 18:09:29 +1300167 *dlen = tmp_len;
Heiko Schocherf5895d12014-06-24 10:10:04 +0200168 return err;
169
170 return 0;
171}
Anton Habegger62e79dd2015-01-22 22:29:10 +0100172
173/* from shrinker.c */
174
175/* Global clean znode counter (for all mounted UBIFS instances) */
176atomic_long_t ubifs_clean_zn_cnt;
177
Heiko Schocherf5895d12014-06-24 10:10:04 +0200178#endif
179
Stefan Roese2fc10f62009-03-19 15:35:05 +0100180/**
181 * ubifs_decompress - decompress data.
182 * @in_buf: data to decompress
183 * @in_len: length of the data to decompress
184 * @out_buf: output buffer where decompressed data should
185 * @out_len: output length is returned here
186 * @compr_type: type of compression
187 *
188 * This function decompresses data from buffer @in_buf into buffer @out_buf.
189 * The length of the uncompressed data is returned in @out_len. This functions
190 * returns %0 on success or a negative error code on failure.
191 */
Heiko Schocher94b66de2015-10-22 06:19:21 +0200192int ubifs_decompress(const struct ubifs_info *c, const void *in_buf,
193 int in_len, void *out_buf, int *out_len, int compr_type)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100194{
195 int err;
196 struct ubifs_compressor *compr;
197
198 if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200199 ubifs_err(c, "invalid compression type %d", compr_type);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100200 return -EINVAL;
201 }
202
203 compr = ubifs_compressors[compr_type];
204
Piotr Wojtaszczyke60ab9a2024-05-28 17:05:28 +0200205 if (unlikely(!compr)) {
206 ubifs_err(c, "compression type %d is not compiled in", compr_type);
207 return -EINVAL;
208 }
209
Stefan Roese2fc10f62009-03-19 15:35:05 +0100210 if (unlikely(!compr->capi_name)) {
Piotr Wojtaszczyke60ab9a2024-05-28 17:05:28 +0200211 ubifs_err(c, "%s compression is not compiled in",
212 compr->name ? compr->name : "unknown");
Stefan Roese2fc10f62009-03-19 15:35:05 +0100213 return -EINVAL;
214 }
215
216 if (compr_type == UBIFS_COMPR_NONE) {
217 memcpy(out_buf, in_buf, in_len);
218 *out_len = in_len;
219 return 0;
220 }
221
Heiko Schocherf5895d12014-06-24 10:10:04 +0200222 if (compr->decomp_mutex)
223 mutex_lock(compr->decomp_mutex);
Heiko Schocher94b66de2015-10-22 06:19:21 +0200224 err = crypto_comp_decompress(c, compr->cc, in_buf, in_len, out_buf,
Heiko Schocherf5895d12014-06-24 10:10:04 +0200225 (unsigned int *)out_len);
226 if (compr->decomp_mutex)
227 mutex_unlock(compr->decomp_mutex);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100228 if (err)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200229 ubifs_err(c, "cannot decompress %d bytes, compressor %s,"
230 " error %d", in_len, compr->name, err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100231
232 return err;
233}
234
235/**
236 * compr_init - initialize a compressor.
237 * @compr: compressor description object
238 *
239 * This function initializes the requested compressor and returns zero in case
240 * of success or a negative error code in case of failure.
241 */
242static int __init compr_init(struct ubifs_compressor *compr)
243{
244 ubifs_compressors[compr->compr_type] = compr;
Peter Tyser9057cbf2009-09-21 11:20:36 -0500245
Heiko Schocherf5895d12014-06-24 10:10:04 +0200246 if (compr->capi_name) {
247 compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
248 if (IS_ERR(compr->cc)) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200249 dbg_gen("cannot initialize compressor %s,"
250 " error %ld", compr->name,
251 PTR_ERR(compr->cc));
Heiko Schocherf5895d12014-06-24 10:10:04 +0200252 return PTR_ERR(compr->cc);
253 }
254 }
255
Stefan Roese2fc10f62009-03-19 15:35:05 +0100256 return 0;
257}
258
259/**
260 * ubifs_compressors_init - initialize UBIFS compressors.
261 *
262 * This function initializes the compressor which were compiled in. Returns
263 * zero in case of success and a negative error code in case of failure.
264 */
265int __init ubifs_compressors_init(void)
266{
267 int err;
268
269 err = compr_init(&lzo_compr);
270 if (err)
271 return err;
272
273 err = compr_init(&zlib_compr);
274 if (err)
275 return err;
276
Piotr Wojtaszczyke60ab9a2024-05-28 17:05:28 +0200277#if IS_ENABLED(CONFIG_ZSTD)
278 err = compr_init(&zstd_compr);
279 if (err)
280 return err;
281#endif
282
Michael Lawnickb0617012009-03-19 10:06:41 +0100283 err = compr_init(&none_compr);
284 if (err)
285 return err;
286
Stefan Roese2fc10f62009-03-19 15:35:05 +0100287 return 0;
288}
289
290/*
291 * ubifsls...
292 */
293
294static int filldir(struct ubifs_info *c, const char *name, int namlen,
295 u64 ino, unsigned int d_type)
296{
297 struct inode *inode;
298 char filetime[32];
299
300 switch (d_type) {
301 case UBIFS_ITYPE_REG:
302 printf("\t");
303 break;
304 case UBIFS_ITYPE_DIR:
305 printf("<DIR>\t");
306 break;
307 case UBIFS_ITYPE_LNK:
308 printf("<LNK>\t");
309 break;
310 default:
311 printf("other\t");
312 break;
313 }
314
315 inode = ubifs_iget(c->vfs_sb, ino);
316 if (IS_ERR(inode)) {
317 printf("%s: Error in ubifs_iget(), ino=%lld ret=%p!\n",
318 __func__, ino, inode);
319 return -1;
320 }
321 ctime_r((time_t *)&inode->i_mtime, filetime);
322 printf("%9lld %24.24s ", inode->i_size, filetime);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200323#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100324 ubifs_iput(inode);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200325#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100326
327 printf("%s\n", name);
328
329 return 0;
330}
331
332static int ubifs_printdir(struct file *file, void *dirent)
333{
334 int err, over = 0;
335 struct qstr nm;
336 union ubifs_key key;
337 struct ubifs_dent_node *dent;
338 struct inode *dir = file->f_path.dentry->d_inode;
339 struct ubifs_info *c = dir->i_sb->s_fs_info;
340
341 dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
342
343 if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
344 /*
345 * The directory was seek'ed to a senseless position or there
346 * are no more entries.
347 */
348 return 0;
349
350 if (file->f_pos == 1) {
351 /* Find the first entry in TNC and save it */
352 lowest_dent_key(c, &key, dir->i_ino);
353 nm.name = NULL;
354 dent = ubifs_tnc_next_ent(c, &key, &nm);
355 if (IS_ERR(dent)) {
356 err = PTR_ERR(dent);
357 goto out;
358 }
359
360 file->f_pos = key_hash_flash(c, &dent->key);
361 file->private_data = dent;
362 }
363
364 dent = file->private_data;
365 if (!dent) {
366 /*
367 * The directory was seek'ed to and is now readdir'ed.
368 * Find the entry corresponding to @file->f_pos or the
369 * closest one.
370 */
371 dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
372 nm.name = NULL;
373 dent = ubifs_tnc_next_ent(c, &key, &nm);
374 if (IS_ERR(dent)) {
375 err = PTR_ERR(dent);
376 goto out;
377 }
378 file->f_pos = key_hash_flash(c, &dent->key);
379 file->private_data = dent;
380 }
381
382 while (1) {
383 dbg_gen("feed '%s', ino %llu, new f_pos %#x",
384 dent->name, (unsigned long long)le64_to_cpu(dent->inum),
385 key_hash_flash(c, &dent->key));
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200386#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100387 ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200388#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100389
390 nm.len = le16_to_cpu(dent->nlen);
391 over = filldir(c, (char *)dent->name, nm.len,
392 le64_to_cpu(dent->inum), dent->type);
393 if (over)
394 return 0;
395
396 /* Switch to the next entry */
397 key_read(c, &dent->key, &key);
398 nm.name = (char *)dent->name;
399 dent = ubifs_tnc_next_ent(c, &key, &nm);
400 if (IS_ERR(dent)) {
401 err = PTR_ERR(dent);
402 goto out;
403 }
404
405 kfree(file->private_data);
406 file->f_pos = key_hash_flash(c, &dent->key);
407 file->private_data = dent;
408 cond_resched();
409 }
410
411out:
412 if (err != -ENOENT) {
Heiko Schocher94b66de2015-10-22 06:19:21 +0200413 ubifs_err(c, "cannot find next direntry, error %d", err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100414 return err;
415 }
416
417 kfree(file->private_data);
418 file->private_data = NULL;
419 file->f_pos = 2;
420 return 0;
421}
422
423static int ubifs_finddir(struct super_block *sb, char *dirname,
424 unsigned long root_inum, unsigned long *inum)
425{
426 int err;
427 struct qstr nm;
428 union ubifs_key key;
429 struct ubifs_dent_node *dent;
430 struct ubifs_info *c;
431 struct file *file;
432 struct dentry *dentry;
433 struct inode *dir;
Stefan Roeseac3244a2012-08-28 14:00:24 +0200434 int ret = 0;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100435
436 file = kzalloc(sizeof(struct file), 0);
437 dentry = kzalloc(sizeof(struct dentry), 0);
438 dir = kzalloc(sizeof(struct inode), 0);
439 if (!file || !dentry || !dir) {
440 printf("%s: Error, no memory for malloc!\n", __func__);
441 err = -ENOMEM;
442 goto out;
443 }
444
445 dir->i_sb = sb;
446 file->f_path.dentry = dentry;
447 file->f_path.dentry->d_parent = dentry;
448 file->f_path.dentry->d_inode = dir;
449 file->f_path.dentry->d_inode->i_ino = root_inum;
450 c = sb->s_fs_info;
451
452 dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
453
454 /* Find the first entry in TNC and save it */
455 lowest_dent_key(c, &key, dir->i_ino);
456 nm.name = NULL;
457 dent = ubifs_tnc_next_ent(c, &key, &nm);
458 if (IS_ERR(dent)) {
459 err = PTR_ERR(dent);
460 goto out;
461 }
462
463 file->f_pos = key_hash_flash(c, &dent->key);
464 file->private_data = dent;
465
466 while (1) {
467 dbg_gen("feed '%s', ino %llu, new f_pos %#x",
468 dent->name, (unsigned long long)le64_to_cpu(dent->inum),
469 key_hash_flash(c, &dent->key));
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200470#ifndef __UBOOT__
Stefan Roese2fc10f62009-03-19 15:35:05 +0100471 ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
Patrice Chotardec7c77e2018-04-27 15:51:23 +0200472#endif
Stefan Roese2fc10f62009-03-19 15:35:05 +0100473
474 nm.len = le16_to_cpu(dent->nlen);
475 if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
476 (strlen(dirname) == nm.len)) {
477 *inum = le64_to_cpu(dent->inum);
Stefan Roeseac3244a2012-08-28 14:00:24 +0200478 ret = 1;
479 goto out_free;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100480 }
481
482 /* Switch to the next entry */
483 key_read(c, &dent->key, &key);
484 nm.name = (char *)dent->name;
485 dent = ubifs_tnc_next_ent(c, &key, &nm);
486 if (IS_ERR(dent)) {
487 err = PTR_ERR(dent);
488 goto out;
489 }
490
491 kfree(file->private_data);
492 file->f_pos = key_hash_flash(c, &dent->key);
493 file->private_data = dent;
494 cond_resched();
495 }
496
497out:
Stefan Roeseac3244a2012-08-28 14:00:24 +0200498 if (err != -ENOENT)
Heiko Schocher94b66de2015-10-22 06:19:21 +0200499 dbg_gen("cannot find next direntry, error %d", err);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100500
Stefan Roeseac3244a2012-08-28 14:00:24 +0200501out_free:
Heinrich Schuchardte9892792017-11-08 22:28:47 +0100502 kfree(file->private_data);
503 free(file);
504 free(dentry);
505 free(dir);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100506
Stefan Roeseac3244a2012-08-28 14:00:24 +0200507 return ret;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100508}
509
510static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
511{
512 int ret;
513 char *next;
514 char fpath[128];
Simon Kagstrom877501a2009-09-15 09:53:29 +0200515 char symlinkpath[128];
Stefan Roese2fc10f62009-03-19 15:35:05 +0100516 char *name = fpath;
517 unsigned long root_inum = 1;
518 unsigned long inum;
Simon Kagstrom877501a2009-09-15 09:53:29 +0200519 int symlink_count = 0; /* Don't allow symlink recursion */
Ricardo Ribalda Delgado4a2e69c2010-12-02 15:02:35 +0100520 char link_name[64];
Stefan Roese2fc10f62009-03-19 15:35:05 +0100521
522 strcpy(fpath, filename);
523
524 /* Remove all leading slashes */
525 while (*name == '/')
526 name++;
527
528 /*
529 * Handle root-direcoty ('/')
530 */
531 inum = root_inum;
532 if (!name || *name == '\0')
533 return inum;
534
535 for (;;) {
Simon Kagstrom877501a2009-09-15 09:53:29 +0200536 struct inode *inode;
537 struct ubifs_inode *ui;
538
Stefan Roese2fc10f62009-03-19 15:35:05 +0100539 /* Extract the actual part from the pathname. */
540 next = strchr(name, '/');
541 if (next) {
542 /* Remove all leading slashes. */
543 while (*next == '/')
544 *(next++) = '\0';
545 }
546
547 ret = ubifs_finddir(sb, name, root_inum, &inum);
Simon Kagstrom877501a2009-09-15 09:53:29 +0200548 if (!ret)
549 return 0;
550 inode = ubifs_iget(sb, inum);
551
552 if (!inode)
553 return 0;
554 ui = ubifs_inode(inode);
555
556 if ((inode->i_mode & S_IFMT) == S_IFLNK) {
Simon Kagstrom877501a2009-09-15 09:53:29 +0200557 char buf[128];
558
559 /* We have some sort of symlink recursion, bail out */
560 if (symlink_count++ > 8) {
561 printf("Symlink recursion, aborting\n");
562 return 0;
563 }
564 memcpy(link_name, ui->data, ui->data_len);
565 link_name[ui->data_len] = '\0';
566
567 if (link_name[0] == '/') {
568 /* Absolute path, redo everything without
569 * the leading slash */
570 next = name = link_name + 1;
571 root_inum = 1;
572 continue;
573 }
574 /* Relative to cur dir */
Simon Kagstrom84167362009-09-25 14:05:57 +0200575 sprintf(buf, "%s/%s",
Simon Kagstrom877501a2009-09-15 09:53:29 +0200576 link_name, next == NULL ? "" : next);
577 memcpy(symlinkpath, buf, sizeof(buf));
578 next = name = symlinkpath;
579 continue;
580 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100581
582 /*
583 * Check if directory with this name exists
584 */
585
586 /* Found the node! */
Simon Kagstrom877501a2009-09-15 09:53:29 +0200587 if (!next || *next == '\0')
588 return inum;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100589
590 root_inum = inum;
591 name = next;
592 }
593
594 return 0;
595}
596
Simon Glassc1c4a8f2020-05-10 11:39:57 -0600597int ubifs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info)
Hans de Goedeb5030b22015-09-17 18:46:57 -0400598{
599 if (rbdd) {
600 debug("UBIFS cannot be used with normal block devices\n");
601 return -1;
602 }
603
604 /*
Simon Glasse76ee972016-02-29 15:25:44 -0700605 * Should never happen since blk_get_device_part_str() already checks
Hans de Goedeb5030b22015-09-17 18:46:57 -0400606 * this, but better safe then sorry.
607 */
608 if (!ubifs_is_mounted()) {
609 debug("UBIFS not mounted, use ubifsmount to mount volume first!\n");
610 return -1;
611 }
612
613 return 0;
614}
615
Hans de Goedea1644772015-09-17 18:46:56 -0400616int ubifs_ls(const char *filename)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100617{
618 struct ubifs_info *c = ubifs_sb->s_fs_info;
619 struct file *file;
620 struct dentry *dentry;
621 struct inode *dir;
622 void *dirent = NULL;
623 unsigned long inum;
624 int ret = 0;
625
626 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
Hans de Goedea1644772015-09-17 18:46:56 -0400627 inum = ubifs_findfile(ubifs_sb, (char *)filename);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100628 if (!inum) {
629 ret = -1;
630 goto out;
631 }
632
633 file = kzalloc(sizeof(struct file), 0);
634 dentry = kzalloc(sizeof(struct dentry), 0);
635 dir = kzalloc(sizeof(struct inode), 0);
636 if (!file || !dentry || !dir) {
637 printf("%s: Error, no memory for malloc!\n", __func__);
638 ret = -ENOMEM;
639 goto out_mem;
640 }
641
642 dir->i_sb = ubifs_sb;
643 file->f_path.dentry = dentry;
644 file->f_path.dentry->d_parent = dentry;
645 file->f_path.dentry->d_inode = dir;
646 file->f_path.dentry->d_inode->i_ino = inum;
647 file->f_pos = 1;
648 file->private_data = NULL;
649 ubifs_printdir(file, dirent);
650
651out_mem:
652 if (file)
653 free(file);
654 if (dentry)
655 free(dentry);
656 if (dir)
657 free(dir);
658
659out:
660 ubi_close_volume(c->ubi);
661 return ret;
662}
663
Hans de Goedeb5030b22015-09-17 18:46:57 -0400664int ubifs_exists(const char *filename)
665{
666 struct ubifs_info *c = ubifs_sb->s_fs_info;
667 unsigned long inum;
668
669 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
670 inum = ubifs_findfile(ubifs_sb, (char *)filename);
671 ubi_close_volume(c->ubi);
672
673 return inum != 0;
674}
675
676int ubifs_size(const char *filename, loff_t *size)
677{
678 struct ubifs_info *c = ubifs_sb->s_fs_info;
679 unsigned long inum;
680 struct inode *inode;
681 int err = 0;
682
683 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
684
685 inum = ubifs_findfile(ubifs_sb, (char *)filename);
686 if (!inum) {
687 err = -1;
688 goto out;
689 }
690
691 inode = ubifs_iget(ubifs_sb, inum);
692 if (IS_ERR(inode)) {
693 printf("%s: Error reading inode %ld!\n", __func__, inum);
694 err = PTR_ERR(inode);
695 goto out;
696 }
697
698 *size = inode->i_size;
699
700 ubifs_iput(inode);
701out:
702 ubi_close_volume(c->ubi);
703 return err;
704}
705
Stefan Roese2fc10f62009-03-19 15:35:05 +0100706/*
707 * ubifsload...
708 */
709
710/* file.c */
711
712static inline void *kmap(struct page *page)
713{
714 return page->addr;
715}
716
717static int read_block(struct inode *inode, void *addr, unsigned int block,
718 struct ubifs_data_node *dn)
719{
720 struct ubifs_info *c = inode->i_sb->s_fs_info;
721 int err, len, out_len;
722 union ubifs_key key;
723 unsigned int dlen;
724
725 data_key_init(c, &key, inode->i_ino, block);
726 err = ubifs_tnc_lookup(c, &key, dn);
727 if (err) {
728 if (err == -ENOENT)
729 /* Not found, so it must be a hole */
730 memset(addr, 0, UBIFS_BLOCK_SIZE);
731 return err;
732 }
733
734 ubifs_assert(le64_to_cpu(dn->ch.sqnum) > ubifs_inode(inode)->creat_sqnum);
735
736 len = le32_to_cpu(dn->size);
737 if (len <= 0 || len > UBIFS_BLOCK_SIZE)
738 goto dump;
739
740 dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
741 out_len = UBIFS_BLOCK_SIZE;
Heiko Schocher94b66de2015-10-22 06:19:21 +0200742 err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
Stefan Roese2fc10f62009-03-19 15:35:05 +0100743 le16_to_cpu(dn->compr_type));
744 if (err || len != out_len)
745 goto dump;
746
747 /*
748 * Data length can be less than a full block, even for blocks that are
749 * not the last in the file (e.g., as a result of making a hole and
750 * appending data). Ensure that the remainder is zeroed out.
751 */
752 if (len < UBIFS_BLOCK_SIZE)
753 memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
754
755 return 0;
756
757dump:
Heiko Schocher94b66de2015-10-22 06:19:21 +0200758 ubifs_err(c, "bad data node (block %u, inode %lu)",
Stefan Roese2fc10f62009-03-19 15:35:05 +0100759 block, inode->i_ino);
Heiko Schocherf5895d12014-06-24 10:10:04 +0200760 ubifs_dump_node(c, dn);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100761 return -EINVAL;
762}
763
Stefan Roese28ea29f2010-11-01 17:28:00 +0100764static int do_readpage(struct ubifs_info *c, struct inode *inode,
765 struct page *page, int last_block_size)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100766{
767 void *addr;
768 int err = 0, i;
769 unsigned int block, beyond;
770 struct ubifs_data_node *dn;
771 loff_t i_size = inode->i_size;
772
773 dbg_gen("ino %lu, pg %lu, i_size %lld",
774 inode->i_ino, page->index, i_size);
775
776 addr = kmap(page);
777
778 block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
779 beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
780 if (block >= beyond) {
781 /* Reading beyond inode */
782 memset(addr, 0, PAGE_CACHE_SIZE);
783 goto out;
784 }
785
786 dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
Daniel Mackb5775802009-06-04 19:44:12 +0200787 if (!dn)
788 return -ENOMEM;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100789
790 i = 0;
791 while (1) {
792 int ret;
793
794 if (block >= beyond) {
795 /* Reading beyond inode */
796 err = -ENOENT;
797 memset(addr, 0, UBIFS_BLOCK_SIZE);
798 } else {
Stefan Roese28ea29f2010-11-01 17:28:00 +0100799 /*
800 * Reading last block? Make sure to not write beyond
801 * the requested size in the destination buffer.
802 */
803 if (((block + 1) == beyond) || last_block_size) {
804 void *buff;
805 int dlen;
806
807 /*
808 * We need to buffer the data locally for the
809 * last block. This is to not pad the
810 * destination area to a multiple of
811 * UBIFS_BLOCK_SIZE.
812 */
Marcel Ziswilerabc574b2015-08-18 13:06:37 +0200813 buff = malloc_cache_aligned(UBIFS_BLOCK_SIZE);
Stefan Roese28ea29f2010-11-01 17:28:00 +0100814 if (!buff) {
815 printf("%s: Error, malloc fails!\n",
816 __func__);
817 err = -ENOMEM;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100818 break;
Stefan Roese28ea29f2010-11-01 17:28:00 +0100819 }
820
821 /* Read block-size into temp buffer */
822 ret = read_block(inode, buff, block, dn);
823 if (ret) {
824 err = ret;
825 if (err != -ENOENT) {
826 free(buff);
827 break;
828 }
829 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100830
Stefan Roese28ea29f2010-11-01 17:28:00 +0100831 if (last_block_size)
832 dlen = last_block_size;
Pali Rohár8d2176a2022-05-17 22:45:28 +0200833 else if (ret)
834 dlen = UBIFS_BLOCK_SIZE;
Stefan Roese28ea29f2010-11-01 17:28:00 +0100835 else
836 dlen = le32_to_cpu(dn->size);
837
838 /* Now copy required size back to dest */
839 memcpy(addr, buff, dlen);
840
841 free(buff);
842 } else {
843 ret = read_block(inode, addr, block, dn);
844 if (ret) {
845 err = ret;
846 if (err != -ENOENT)
847 break;
848 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100849 }
850 }
851 if (++i >= UBIFS_BLOCKS_PER_PAGE)
852 break;
853 block += 1;
854 addr += UBIFS_BLOCK_SIZE;
855 }
856 if (err) {
857 if (err == -ENOENT) {
858 /* Not found, so it must be a hole */
859 dbg_gen("hole");
860 goto out_free;
861 }
Heiko Schocher94b66de2015-10-22 06:19:21 +0200862 ubifs_err(c, "cannot read page %lu of inode %lu, error %d",
Stefan Roese2fc10f62009-03-19 15:35:05 +0100863 page->index, inode->i_ino, err);
864 goto error;
865 }
866
867out_free:
868 kfree(dn);
869out:
870 return 0;
871
872error:
873 kfree(dn);
874 return err;
875}
876
Hans de Goedea1644772015-09-17 18:46:56 -0400877int ubifs_read(const char *filename, void *buf, loff_t offset,
878 loff_t size, loff_t *actread)
Stefan Roese2fc10f62009-03-19 15:35:05 +0100879{
880 struct ubifs_info *c = ubifs_sb->s_fs_info;
881 unsigned long inum;
882 struct inode *inode;
883 struct page page;
884 int err = 0;
885 int i;
886 int count;
Stefan Roese28ea29f2010-11-01 17:28:00 +0100887 int last_block_size = 0;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100888
Hans de Goedea1644772015-09-17 18:46:56 -0400889 *actread = 0;
890
891 if (offset & (PAGE_SIZE - 1)) {
Vagrant Cascadianbfdfd102016-10-23 20:45:16 -0700892 printf("ubifs: Error offset must be a multiple of %d\n",
Hans de Goedea1644772015-09-17 18:46:56 -0400893 PAGE_SIZE);
894 return -1;
895 }
896
Stefan Roese2fc10f62009-03-19 15:35:05 +0100897 c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
Simon Kagstrom877501a2009-09-15 09:53:29 +0200898 /* ubifs_findfile will resolve symlinks, so we know that we get
899 * the real file here */
Hans de Goedea1644772015-09-17 18:46:56 -0400900 inum = ubifs_findfile(ubifs_sb, (char *)filename);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100901 if (!inum) {
902 err = -1;
903 goto out;
904 }
905
906 /*
907 * Read file inode
908 */
909 inode = ubifs_iget(ubifs_sb, inum);
910 if (IS_ERR(inode)) {
911 printf("%s: Error reading inode %ld!\n", __func__, inum);
912 err = PTR_ERR(inode);
913 goto out;
914 }
915
Hans de Goedea1644772015-09-17 18:46:56 -0400916 if (offset > inode->i_size) {
917 printf("ubifs: Error offset (%lld) > file-size (%lld)\n",
918 offset, size);
919 err = -1;
920 goto put_inode;
921 }
922
Stefan Roese2fc10f62009-03-19 15:35:05 +0100923 /*
Stefan Roese2fc10f62009-03-19 15:35:05 +0100924 * If no size was specified or if size bigger than filesize
925 * set size to filesize
926 */
Hans de Goedea1644772015-09-17 18:46:56 -0400927 if ((size == 0) || (size > (inode->i_size - offset)))
928 size = inode->i_size - offset;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100929
930 count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100931
Hans de Goedea1644772015-09-17 18:46:56 -0400932 page.addr = buf;
933 page.index = offset / PAGE_SIZE;
Stefan Roese2fc10f62009-03-19 15:35:05 +0100934 page.inode = inode;
935 for (i = 0; i < count; i++) {
Stefan Roese28ea29f2010-11-01 17:28:00 +0100936 /*
937 * Make sure to not read beyond the requested size
938 */
939 if (((i + 1) == count) && (size < inode->i_size))
940 last_block_size = size - (i * PAGE_SIZE);
941
942 err = do_readpage(c, inode, &page, last_block_size);
Stefan Roese2fc10f62009-03-19 15:35:05 +0100943 if (err)
944 break;
945
946 page.addr += PAGE_SIZE;
947 page.index++;
948 }
949
Hans de Goedea1644772015-09-17 18:46:56 -0400950 if (err) {
Stefan Roese2fc10f62009-03-19 15:35:05 +0100951 printf("Error reading file '%s'\n", filename);
Hans de Goedea1644772015-09-17 18:46:56 -0400952 *actread = i * PAGE_SIZE;
953 } else {
954 *actread = size;
Bastian Ruppertfd43edd2011-09-05 03:03:57 +0000955 }
Stefan Roese2fc10f62009-03-19 15:35:05 +0100956
Hans de Goedea1644772015-09-17 18:46:56 -0400957put_inode:
Stefan Roese2fc10f62009-03-19 15:35:05 +0100958 ubifs_iput(inode);
959
960out:
961 ubi_close_volume(c->ubi);
962 return err;
963}
Hans de Goedea1644772015-09-17 18:46:56 -0400964
Hans de Goedeb5030b22015-09-17 18:46:57 -0400965void ubifs_close(void)
966{
967}
968
Hans de Goedea1644772015-09-17 18:46:56 -0400969/* Compat wrappers for common/cmd_ubifs.c */
Ben Dooks68ebcf72023-06-06 09:23:28 +0100970int ubifs_load(char *filename, unsigned long addr, u32 size)
Hans de Goedea1644772015-09-17 18:46:56 -0400971{
972 loff_t actread;
973 int err;
974
Ben Dooks68ebcf72023-06-06 09:23:28 +0100975 printf("Loading file '%s' to addr 0x%08lx...\n", filename, addr);
Hans de Goedea1644772015-09-17 18:46:56 -0400976
Siva Durga Prasad Paladugu67eccfb2017-05-30 14:29:06 +0200977 err = ubifs_read(filename, (void *)(uintptr_t)addr, 0, size, &actread);
Hans de Goedea1644772015-09-17 18:46:56 -0400978 if (err == 0) {
Simon Glass4d949a22017-08-03 12:22:10 -0600979 env_set_hex("filesize", actread);
Hans de Goedea1644772015-09-17 18:46:56 -0400980 printf("Done\n");
981 }
982
983 return err;
984}
985
986void uboot_ubifs_umount(void)
987{
988 if (ubifs_sb) {
989 printf("Unmounting UBIFS volume %s!\n",
990 ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name);
991 ubifs_umount(ubifs_sb->s_fs_info);
992 ubifs_sb = NULL;
993 }
994}