linux/drivers/mtd/ubi/misc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (c) International Business Machines Corp., 2006
   4 *
   5 * Author: Artem Bityutskiy (Битюцкий Артём)
   6 */
   7
   8/* Here we keep miscellaneous functions which are used all over the UBI code */
   9
  10#include "ubi.h"
  11
  12/**
  13 * calc_data_len - calculate how much real data is stored in a buffer.
  14 * @ubi: UBI device description object
  15 * @buf: a buffer with the contents of the physical eraseblock
  16 * @length: the buffer length
  17 *
  18 * This function calculates how much "real data" is stored in @buf and returnes
  19 * the length. Continuous 0xFF bytes at the end of the buffer are not
  20 * considered as "real data".
  21 */
  22int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
  23                      int length)
  24{
  25        int i;
  26
  27        ubi_assert(!(length & (ubi->min_io_size - 1)));
  28
  29        for (i = length - 1; i >= 0; i--)
  30                if (((const uint8_t *)buf)[i] != 0xFF)
  31                        break;
  32
  33        /* The resulting length must be aligned to the minimum flash I/O size */
  34        length = ALIGN(i + 1, ubi->min_io_size);
  35        return length;
  36}
  37
  38/**
  39 * ubi_check_volume - check the contents of a static volume.
  40 * @ubi: UBI device description object
  41 * @vol_id: ID of the volume to check
  42 *
  43 * This function checks if static volume @vol_id is corrupted by fully reading
  44 * it and checking data CRC. This function returns %0 if the volume is not
  45 * corrupted, %1 if it is corrupted and a negative error code in case of
  46 * failure. Dynamic volumes are not checked and zero is returned immediately.
  47 */
  48int ubi_check_volume(struct ubi_device *ubi, int vol_id)
  49{
  50        void *buf;
  51        int err = 0, i;
  52        struct ubi_volume *vol = ubi->volumes[vol_id];
  53
  54        if (vol->vol_type != UBI_STATIC_VOLUME)
  55                return 0;
  56
  57        buf = vmalloc(vol->usable_leb_size);
  58        if (!buf)
  59                return -ENOMEM;
  60
  61        for (i = 0; i < vol->used_ebs; i++) {
  62                int size;
  63
  64                cond_resched();
  65
  66                if (i == vol->used_ebs - 1)
  67                        size = vol->last_eb_bytes;
  68                else
  69                        size = vol->usable_leb_size;
  70
  71                err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1);
  72                if (err) {
  73                        if (mtd_is_eccerr(err))
  74                                err = 1;
  75                        break;
  76                }
  77        }
  78
  79        vfree(buf);
  80        return err;
  81}
  82
  83/**
  84 * ubi_update_reserved - update bad eraseblock handling accounting data.
  85 * @ubi: UBI device description object
  86 *
  87 * This function calculates the gap between current number of PEBs reserved for
  88 * bad eraseblock handling and the required level of PEBs that must be
  89 * reserved, and if necessary, reserves more PEBs to fill that gap, according
  90 * to availability. Should be called with ubi->volumes_lock held.
  91 */
  92void ubi_update_reserved(struct ubi_device *ubi)
  93{
  94        int need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
  95
  96        if (need <= 0 || ubi->avail_pebs == 0)
  97                return;
  98
  99        need = min_t(int, need, ubi->avail_pebs);
 100        ubi->avail_pebs -= need;
 101        ubi->rsvd_pebs += need;
 102        ubi->beb_rsvd_pebs += need;
 103        ubi_msg(ubi, "reserved more %d PEBs for bad PEB handling", need);
 104}
 105
 106/**
 107 * ubi_calculate_reserved - calculate how many PEBs must be reserved for bad
 108 * eraseblock handling.
 109 * @ubi: UBI device description object
 110 */
 111void ubi_calculate_reserved(struct ubi_device *ubi)
 112{
 113        /*
 114         * Calculate the actual number of PEBs currently needed to be reserved
 115         * for future bad eraseblock handling.
 116         */
 117        ubi->beb_rsvd_level = ubi->bad_peb_limit - ubi->bad_peb_count;
 118        if (ubi->beb_rsvd_level < 0) {
 119                ubi->beb_rsvd_level = 0;
 120                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)",
 121                         ubi->bad_peb_count, ubi->bad_peb_limit);
 122        }
 123}
 124
 125/**
 126 * ubi_check_pattern - check if buffer contains only a certain byte pattern.
 127 * @buf: buffer to check
 128 * @patt: the pattern to check
 129 * @size: buffer size in bytes
 130 *
 131 * This function returns %1 in there are only @patt bytes in @buf, and %0 if
 132 * something else was also found.
 133 */
 134int ubi_check_pattern(const void *buf, uint8_t patt, int size)
 135{
 136        int i;
 137
 138        for (i = 0; i < size; i++)
 139                if (((const uint8_t *)buf)[i] != patt)
 140                        return 0;
 141        return 1;
 142}
 143
 144/* Normal UBI messages */
 145void ubi_msg(const struct ubi_device *ubi, const char *fmt, ...)
 146{
 147        struct va_format vaf;
 148        va_list args;
 149
 150        va_start(args, fmt);
 151
 152        vaf.fmt = fmt;
 153        vaf.va = &args;
 154
 155        pr_notice(UBI_NAME_STR "%d: %pV\n", ubi->ubi_num, &vaf);
 156
 157        va_end(args);
 158}
 159
 160/* UBI warning messages */
 161void ubi_warn(const struct ubi_device *ubi, const char *fmt, ...)
 162{
 163        struct va_format vaf;
 164        va_list args;
 165
 166        va_start(args, fmt);
 167
 168        vaf.fmt = fmt;
 169        vaf.va = &args;
 170
 171        pr_warn(UBI_NAME_STR "%d warning: %ps: %pV\n",
 172                ubi->ubi_num, __builtin_return_address(0), &vaf);
 173
 174        va_end(args);
 175}
 176
 177/* UBI error messages */
 178void ubi_err(const struct ubi_device *ubi, const char *fmt, ...)
 179{
 180        struct va_format vaf;
 181        va_list args;
 182
 183        va_start(args, fmt);
 184
 185        vaf.fmt = fmt;
 186        vaf.va = &args;
 187
 188        pr_err(UBI_NAME_STR "%d error: %ps: %pV\n",
 189               ubi->ubi_num, __builtin_return_address(0), &vaf);
 190        va_end(args);
 191}
 192