162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) International Business Machines Corp., 2006
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: Artem Bityutskiy (Битюцкий Артём)
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/* Here we keep miscellaneous functions which are used all over the UBI code */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "ubi.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/**
1362306a36Sopenharmony_ci * ubi_calc_data_len - calculate how much real data is stored in a buffer.
1462306a36Sopenharmony_ci * @ubi: UBI device description object
1562306a36Sopenharmony_ci * @buf: a buffer with the contents of the physical eraseblock
1662306a36Sopenharmony_ci * @length: the buffer length
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * This function calculates how much "real data" is stored in @buf and returnes
1962306a36Sopenharmony_ci * the length. Continuous 0xFF bytes at the end of the buffer are not
2062306a36Sopenharmony_ci * considered as "real data".
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ciint ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
2362306a36Sopenharmony_ci		      int length)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	int i;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	ubi_assert(!(length & (ubi->min_io_size - 1)));
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	for (i = length - 1; i >= 0; i--)
3062306a36Sopenharmony_ci		if (((const uint8_t *)buf)[i] != 0xFF)
3162306a36Sopenharmony_ci			break;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	/* The resulting length must be aligned to the minimum flash I/O size */
3462306a36Sopenharmony_ci	length = ALIGN(i + 1, ubi->min_io_size);
3562306a36Sopenharmony_ci	return length;
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/**
3962306a36Sopenharmony_ci * ubi_check_volume - check the contents of a static volume.
4062306a36Sopenharmony_ci * @ubi: UBI device description object
4162306a36Sopenharmony_ci * @vol_id: ID of the volume to check
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * This function checks if static volume @vol_id is corrupted by fully reading
4462306a36Sopenharmony_ci * it and checking data CRC. This function returns %0 if the volume is not
4562306a36Sopenharmony_ci * corrupted, %1 if it is corrupted and a negative error code in case of
4662306a36Sopenharmony_ci * failure. Dynamic volumes are not checked and zero is returned immediately.
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_ciint ubi_check_volume(struct ubi_device *ubi, int vol_id)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	void *buf;
5162306a36Sopenharmony_ci	int err = 0, i;
5262306a36Sopenharmony_ci	struct ubi_volume *vol = ubi->volumes[vol_id];
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	if (vol->vol_type != UBI_STATIC_VOLUME)
5562306a36Sopenharmony_ci		return 0;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	buf = vmalloc(vol->usable_leb_size);
5862306a36Sopenharmony_ci	if (!buf)
5962306a36Sopenharmony_ci		return -ENOMEM;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	for (i = 0; i < vol->used_ebs; i++) {
6262306a36Sopenharmony_ci		int size;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci		cond_resched();
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci		if (i == vol->used_ebs - 1)
6762306a36Sopenharmony_ci			size = vol->last_eb_bytes;
6862306a36Sopenharmony_ci		else
6962306a36Sopenharmony_ci			size = vol->usable_leb_size;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci		err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1);
7262306a36Sopenharmony_ci		if (err) {
7362306a36Sopenharmony_ci			if (mtd_is_eccerr(err))
7462306a36Sopenharmony_ci				err = 1;
7562306a36Sopenharmony_ci			break;
7662306a36Sopenharmony_ci		}
7762306a36Sopenharmony_ci	}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	vfree(buf);
8062306a36Sopenharmony_ci	return err;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/**
8462306a36Sopenharmony_ci * ubi_update_reserved - update bad eraseblock handling accounting data.
8562306a36Sopenharmony_ci * @ubi: UBI device description object
8662306a36Sopenharmony_ci *
8762306a36Sopenharmony_ci * This function calculates the gap between current number of PEBs reserved for
8862306a36Sopenharmony_ci * bad eraseblock handling and the required level of PEBs that must be
8962306a36Sopenharmony_ci * reserved, and if necessary, reserves more PEBs to fill that gap, according
9062306a36Sopenharmony_ci * to availability. Should be called with ubi->volumes_lock held.
9162306a36Sopenharmony_ci */
9262306a36Sopenharmony_civoid ubi_update_reserved(struct ubi_device *ubi)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	int need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	if (need <= 0 || ubi->avail_pebs == 0)
9762306a36Sopenharmony_ci		return;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	need = min_t(int, need, ubi->avail_pebs);
10062306a36Sopenharmony_ci	ubi->avail_pebs -= need;
10162306a36Sopenharmony_ci	ubi->rsvd_pebs += need;
10262306a36Sopenharmony_ci	ubi->beb_rsvd_pebs += need;
10362306a36Sopenharmony_ci	ubi_msg(ubi, "reserved more %d PEBs for bad PEB handling", need);
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci/**
10762306a36Sopenharmony_ci * ubi_calculate_reserved - calculate how many PEBs must be reserved for bad
10862306a36Sopenharmony_ci * eraseblock handling.
10962306a36Sopenharmony_ci * @ubi: UBI device description object
11062306a36Sopenharmony_ci */
11162306a36Sopenharmony_civoid ubi_calculate_reserved(struct ubi_device *ubi)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	/*
11462306a36Sopenharmony_ci	 * Calculate the actual number of PEBs currently needed to be reserved
11562306a36Sopenharmony_ci	 * for future bad eraseblock handling.
11662306a36Sopenharmony_ci	 */
11762306a36Sopenharmony_ci	ubi->beb_rsvd_level = ubi->bad_peb_limit - ubi->bad_peb_count;
11862306a36Sopenharmony_ci	if (ubi->beb_rsvd_level < 0) {
11962306a36Sopenharmony_ci		ubi->beb_rsvd_level = 0;
12062306a36Sopenharmony_ci		ubi_warn(ubi, "number of bad PEBs (%d) is above the expected limit (%d), not reserving any PEBs for bad PEB handling, will use available PEBs (if any)",
12162306a36Sopenharmony_ci			 ubi->bad_peb_count, ubi->bad_peb_limit);
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci/**
12662306a36Sopenharmony_ci * ubi_check_pattern - check if buffer contains only a certain byte pattern.
12762306a36Sopenharmony_ci * @buf: buffer to check
12862306a36Sopenharmony_ci * @patt: the pattern to check
12962306a36Sopenharmony_ci * @size: buffer size in bytes
13062306a36Sopenharmony_ci *
13162306a36Sopenharmony_ci * This function returns %1 in there are only @patt bytes in @buf, and %0 if
13262306a36Sopenharmony_ci * something else was also found.
13362306a36Sopenharmony_ci */
13462306a36Sopenharmony_ciint ubi_check_pattern(const void *buf, uint8_t patt, int size)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	int i;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	for (i = 0; i < size; i++)
13962306a36Sopenharmony_ci		if (((const uint8_t *)buf)[i] != patt)
14062306a36Sopenharmony_ci			return 0;
14162306a36Sopenharmony_ci	return 1;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/* Normal UBI messages */
14562306a36Sopenharmony_civoid ubi_msg(const struct ubi_device *ubi, const char *fmt, ...)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	struct va_format vaf;
14862306a36Sopenharmony_ci	va_list args;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	va_start(args, fmt);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	vaf.fmt = fmt;
15362306a36Sopenharmony_ci	vaf.va = &args;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	pr_notice(UBI_NAME_STR "%d: %pV\n", ubi->ubi_num, &vaf);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	va_end(args);
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/* UBI warning messages */
16162306a36Sopenharmony_civoid ubi_warn(const struct ubi_device *ubi, const char *fmt, ...)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	struct va_format vaf;
16462306a36Sopenharmony_ci	va_list args;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	va_start(args, fmt);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	vaf.fmt = fmt;
16962306a36Sopenharmony_ci	vaf.va = &args;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	pr_warn(UBI_NAME_STR "%d warning: %ps: %pV\n",
17262306a36Sopenharmony_ci		ubi->ubi_num, __builtin_return_address(0), &vaf);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	va_end(args);
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci/* UBI error messages */
17862306a36Sopenharmony_civoid ubi_err(const struct ubi_device *ubi, const char *fmt, ...)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct va_format vaf;
18162306a36Sopenharmony_ci	va_list args;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	va_start(args, fmt);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	vaf.fmt = fmt;
18662306a36Sopenharmony_ci	vaf.va = &args;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	pr_err(UBI_NAME_STR "%d error: %ps: %pV\n",
18962306a36Sopenharmony_ci	       ubi->ubi_num, __builtin_return_address(0), &vaf);
19062306a36Sopenharmony_ci	va_end(args);
19162306a36Sopenharmony_ci}
192