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