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