Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (c) International Business Machines Corp., 2006
0004  *
0005  * Author: Artem Bityutskiy (Битюцкий Артём)
0006  */
0007 
0008 /* Here we keep miscellaneous functions which are used all over the UBI code */
0009 
0010 #include "ubi.h"
0011 
0012 /**
0013  * calc_data_len - calculate how much real data is stored in a buffer.
0014  * @ubi: UBI device description object
0015  * @buf: a buffer with the contents of the physical eraseblock
0016  * @length: the buffer length
0017  *
0018  * This function calculates how much "real data" is stored in @buf and returnes
0019  * the length. Continuous 0xFF bytes at the end of the buffer are not
0020  * considered as "real data".
0021  */
0022 int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
0023               int length)
0024 {
0025     int i;
0026 
0027     ubi_assert(!(length & (ubi->min_io_size - 1)));
0028 
0029     for (i = length - 1; i >= 0; i--)
0030         if (((const uint8_t *)buf)[i] != 0xFF)
0031             break;
0032 
0033     /* The resulting length must be aligned to the minimum flash I/O size */
0034     length = ALIGN(i + 1, ubi->min_io_size);
0035     return length;
0036 }
0037 
0038 /**
0039  * ubi_check_volume - check the contents of a static volume.
0040  * @ubi: UBI device description object
0041  * @vol_id: ID of the volume to check
0042  *
0043  * This function checks if static volume @vol_id is corrupted by fully reading
0044  * it and checking data CRC. This function returns %0 if the volume is not
0045  * corrupted, %1 if it is corrupted and a negative error code in case of
0046  * failure. Dynamic volumes are not checked and zero is returned immediately.
0047  */
0048 int ubi_check_volume(struct ubi_device *ubi, int vol_id)
0049 {
0050     void *buf;
0051     int err = 0, i;
0052     struct ubi_volume *vol = ubi->volumes[vol_id];
0053 
0054     if (vol->vol_type != UBI_STATIC_VOLUME)
0055         return 0;
0056 
0057     buf = vmalloc(vol->usable_leb_size);
0058     if (!buf)
0059         return -ENOMEM;
0060 
0061     for (i = 0; i < vol->used_ebs; i++) {
0062         int size;
0063 
0064         cond_resched();
0065 
0066         if (i == vol->used_ebs - 1)
0067             size = vol->last_eb_bytes;
0068         else
0069             size = vol->usable_leb_size;
0070 
0071         err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1);
0072         if (err) {
0073             if (mtd_is_eccerr(err))
0074                 err = 1;
0075             break;
0076         }
0077     }
0078 
0079     vfree(buf);
0080     return err;
0081 }
0082 
0083 /**
0084  * ubi_update_reserved - update bad eraseblock handling accounting data.
0085  * @ubi: UBI device description object
0086  *
0087  * This function calculates the gap between current number of PEBs reserved for
0088  * bad eraseblock handling and the required level of PEBs that must be
0089  * reserved, and if necessary, reserves more PEBs to fill that gap, according
0090  * to availability. Should be called with ubi->volumes_lock held.
0091  */
0092 void ubi_update_reserved(struct ubi_device *ubi)
0093 {
0094     int need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
0095 
0096     if (need <= 0 || ubi->avail_pebs == 0)
0097         return;
0098 
0099     need = min_t(int, need, ubi->avail_pebs);
0100     ubi->avail_pebs -= need;
0101     ubi->rsvd_pebs += need;
0102     ubi->beb_rsvd_pebs += need;
0103     ubi_msg(ubi, "reserved more %d PEBs for bad PEB handling", need);
0104 }
0105 
0106 /**
0107  * ubi_calculate_reserved - calculate how many PEBs must be reserved for bad
0108  * eraseblock handling.
0109  * @ubi: UBI device description object
0110  */
0111 void ubi_calculate_reserved(struct ubi_device *ubi)
0112 {
0113     /*
0114      * Calculate the actual number of PEBs currently needed to be reserved
0115      * for future bad eraseblock handling.
0116      */
0117     ubi->beb_rsvd_level = ubi->bad_peb_limit - ubi->bad_peb_count;
0118     if (ubi->beb_rsvd_level < 0) {
0119         ubi->beb_rsvd_level = 0;
0120         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)",
0121              ubi->bad_peb_count, ubi->bad_peb_limit);
0122     }
0123 }
0124 
0125 /**
0126  * ubi_check_pattern - check if buffer contains only a certain byte pattern.
0127  * @buf: buffer to check
0128  * @patt: the pattern to check
0129  * @size: buffer size in bytes
0130  *
0131  * This function returns %1 in there are only @patt bytes in @buf, and %0 if
0132  * something else was also found.
0133  */
0134 int ubi_check_pattern(const void *buf, uint8_t patt, int size)
0135 {
0136     int i;
0137 
0138     for (i = 0; i < size; i++)
0139         if (((const uint8_t *)buf)[i] != patt)
0140             return 0;
0141     return 1;
0142 }
0143 
0144 /* Normal UBI messages */
0145 void ubi_msg(const struct ubi_device *ubi, const char *fmt, ...)
0146 {
0147     struct va_format vaf;
0148     va_list args;
0149 
0150     va_start(args, fmt);
0151 
0152     vaf.fmt = fmt;
0153     vaf.va = &args;
0154 
0155     pr_notice(UBI_NAME_STR "%d: %pV\n", ubi->ubi_num, &vaf);
0156 
0157     va_end(args);
0158 }
0159 
0160 /* UBI warning messages */
0161 void ubi_warn(const struct ubi_device *ubi, const char *fmt, ...)
0162 {
0163     struct va_format vaf;
0164     va_list args;
0165 
0166     va_start(args, fmt);
0167 
0168     vaf.fmt = fmt;
0169     vaf.va = &args;
0170 
0171     pr_warn(UBI_NAME_STR "%d warning: %ps: %pV\n",
0172         ubi->ubi_num, __builtin_return_address(0), &vaf);
0173 
0174     va_end(args);
0175 }
0176 
0177 /* UBI error messages */
0178 void ubi_err(const struct ubi_device *ubi, const char *fmt, ...)
0179 {
0180     struct va_format vaf;
0181     va_list args;
0182 
0183     va_start(args, fmt);
0184 
0185     vaf.fmt = fmt;
0186     vaf.va = &args;
0187 
0188     pr_err(UBI_NAME_STR "%d error: %ps: %pV\n",
0189            ubi->ubi_num, __builtin_return_address(0), &vaf);
0190     va_end(args);
0191 }