1// SPDX-License-Identifier: GPL-2.0+ 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 <log.h> 11#include <malloc.h> 12#include <ubi_uboot.h> 13#include "ubi.h" 14 15/** 16 * calc_data_len - calculate how much real data is stored in a buffer. 17 * @ubi: UBI device description object 18 * @buf: a buffer with the contents of the physical eraseblock 19 * @length: the buffer length 20 * 21 * This function calculates how much "real data" is stored in @buf and returnes 22 * the length. Continuous 0xFF bytes at the end of the buffer are not 23 * considered as "real data". 24 */ 25int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, 26 int length) 27{ 28 int i; 29 30 ubi_assert(!(length & (ubi->min_io_size - 1))); 31 32 for (i = length - 1; i >= 0; i--) 33 if (((const uint8_t *)buf)[i] != 0xFF) 34 break; 35 36 /* The resulting length must be aligned to the minimum flash I/O size */ 37 length = ALIGN(i + 1, ubi->min_io_size); 38 return length; 39} 40 41/** 42 * ubi_check_volume - check the contents of a static volume. 43 * @ubi: UBI device description object 44 * @vol_id: ID of the volume to check 45 * 46 * This function checks if static volume @vol_id is corrupted by fully reading 47 * it and checking data CRC. This function returns %0 if the volume is not 48 * corrupted, %1 if it is corrupted and a negative error code in case of 49 * failure. Dynamic volumes are not checked and zero is returned immediately. 50 */ 51int ubi_check_volume(struct ubi_device *ubi, int vol_id) 52{ 53 void *buf; 54 int err = 0, i; 55 struct ubi_volume *vol = ubi->volumes[vol_id]; 56 57 if (vol->vol_type != UBI_STATIC_VOLUME) 58 return 0; 59 60 buf = vmalloc(vol->usable_leb_size); 61 if (!buf) 62 return -ENOMEM; 63 64 for (i = 0; i < vol->used_ebs; i++) { 65 int size; 66 67 cond_resched(); 68 69 if (i == vol->used_ebs - 1) 70 size = vol->last_eb_bytes; 71 else 72 size = vol->usable_leb_size; 73 74 err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1); 75 if (err) { 76 if (mtd_is_eccerr(err)) 77 err = 1; 78 break; 79 } 80 } 81 82 vfree(buf); 83 return err; 84} 85 86/** 87 * ubi_update_reserved - update bad eraseblock handling accounting data. 88 * @ubi: UBI device description object 89 * 90 * This function calculates the gap between current number of PEBs reserved for 91 * bad eraseblock handling and the required level of PEBs that must be 92 * reserved, and if necessary, reserves more PEBs to fill that gap, according 93 * to availability. Should be called with ubi->volumes_lock held. 94 */ 95void ubi_update_reserved(struct ubi_device *ubi) 96{ 97 int need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs; 98 99 if (need <= 0 || ubi->avail_pebs == 0) 100 return; 101 102 need = min_t(int, need, ubi->avail_pebs); 103 ubi->avail_pebs -= need; 104 ubi->rsvd_pebs += need; 105 ubi->beb_rsvd_pebs += need; 106 ubi_msg(ubi, "reserved more %d PEBs for bad PEB handling", need); 107} 108 109/** 110 * ubi_calculate_reserved - calculate how many PEBs must be reserved for bad 111 * eraseblock handling. 112 * @ubi: UBI device description object 113 */ 114void ubi_calculate_reserved(struct ubi_device *ubi) 115{ 116 /* 117 * Calculate the actual number of PEBs currently needed to be reserved 118 * for future bad eraseblock handling. 119 */ 120 ubi->beb_rsvd_level = ubi->bad_peb_limit - ubi->bad_peb_count; 121 if (ubi->beb_rsvd_level < 0) { 122 ubi->beb_rsvd_level = 0; 123 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)", 124 ubi->bad_peb_count, ubi->bad_peb_limit); 125 } 126} 127 128/** 129 * ubi_check_pattern - check if buffer contains only a certain byte pattern. 130 * @buf: buffer to check 131 * @patt: the pattern to check 132 * @size: buffer size in bytes 133 * 134 * This function returns %1 in there are only @patt bytes in @buf, and %0 if 135 * something else was also found. 136 */ 137int ubi_check_pattern(const void *buf, uint8_t patt, int size) 138{ 139 int i; 140 141 for (i = 0; i < size; i++) 142 if (((const uint8_t *)buf)[i] != patt) 143 return 0; 144 return 1; 145} 146