18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) International Business Machines Corp., 2006 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Artem Bityutskiy (Битюцкий Артём) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * UBI attaching sub-system. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * This sub-system is responsible for attaching MTD devices and it also 128c2ecf20Sopenharmony_ci * implements flash media scanning. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * The attaching information is represented by a &struct ubi_attach_info' 158c2ecf20Sopenharmony_ci * object. Information about volumes is represented by &struct ubi_ainf_volume 168c2ecf20Sopenharmony_ci * objects which are kept in volume RB-tree with root at the @volumes field. 178c2ecf20Sopenharmony_ci * The RB-tree is indexed by the volume ID. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Logical eraseblocks are represented by &struct ubi_ainf_peb objects. These 208c2ecf20Sopenharmony_ci * objects are kept in per-volume RB-trees with the root at the corresponding 218c2ecf20Sopenharmony_ci * &struct ubi_ainf_volume object. To put it differently, we keep an RB-tree of 228c2ecf20Sopenharmony_ci * per-volume objects and each of these objects is the root of RB-tree of 238c2ecf20Sopenharmony_ci * per-LEB objects. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * Corrupted physical eraseblocks are put to the @corr list, free physical 268c2ecf20Sopenharmony_ci * eraseblocks are put to the @free list and the physical eraseblock to be 278c2ecf20Sopenharmony_ci * erased are put to the @erase list. 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * About corruptions 308c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~ 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * UBI protects EC and VID headers with CRC-32 checksums, so it can detect 338c2ecf20Sopenharmony_ci * whether the headers are corrupted or not. Sometimes UBI also protects the 348c2ecf20Sopenharmony_ci * data with CRC-32, e.g., when it executes the atomic LEB change operation, or 358c2ecf20Sopenharmony_ci * when it moves the contents of a PEB for wear-leveling purposes. 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * UBI tries to distinguish between 2 types of corruptions. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * 1. Corruptions caused by power cuts. These are expected corruptions and UBI 408c2ecf20Sopenharmony_ci * tries to handle them gracefully, without printing too many warnings and 418c2ecf20Sopenharmony_ci * error messages. The idea is that we do not lose important data in these 428c2ecf20Sopenharmony_ci * cases - we may lose only the data which were being written to the media just 438c2ecf20Sopenharmony_ci * before the power cut happened, and the upper layers (e.g., UBIFS) are 448c2ecf20Sopenharmony_ci * supposed to handle such data losses (e.g., by using the FS journal). 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like 478c2ecf20Sopenharmony_ci * the reason is a power cut, UBI puts this PEB to the @erase list, and all 488c2ecf20Sopenharmony_ci * PEBs in the @erase list are scheduled for erasure later. 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * 2. Unexpected corruptions which are not caused by power cuts. During 518c2ecf20Sopenharmony_ci * attaching, such PEBs are put to the @corr list and UBI preserves them. 528c2ecf20Sopenharmony_ci * Obviously, this lessens the amount of available PEBs, and if at some point 538c2ecf20Sopenharmony_ci * UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly informs 548c2ecf20Sopenharmony_ci * about such PEBs every time the MTD device is attached. 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * However, it is difficult to reliably distinguish between these types of 578c2ecf20Sopenharmony_ci * corruptions and UBI's strategy is as follows (in case of attaching by 588c2ecf20Sopenharmony_ci * scanning). UBI assumes corruption type 2 if the VID header is corrupted and 598c2ecf20Sopenharmony_ci * the data area does not contain all 0xFFs, and there were no bit-flips or 608c2ecf20Sopenharmony_ci * integrity errors (e.g., ECC errors in case of NAND) while reading the data 618c2ecf20Sopenharmony_ci * area. Otherwise UBI assumes corruption type 1. So the decision criteria 628c2ecf20Sopenharmony_ci * are as follows. 638c2ecf20Sopenharmony_ci * o If the data area contains only 0xFFs, there are no data, and it is safe 648c2ecf20Sopenharmony_ci * to just erase this PEB - this is corruption type 1. 658c2ecf20Sopenharmony_ci * o If the data area has bit-flips or data integrity errors (ECC errors on 668c2ecf20Sopenharmony_ci * NAND), it is probably a PEB which was being erased when power cut 678c2ecf20Sopenharmony_ci * happened, so this is corruption type 1. However, this is just a guess, 688c2ecf20Sopenharmony_ci * which might be wrong. 698c2ecf20Sopenharmony_ci * o Otherwise this is corruption type 2. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#include <linux/err.h> 738c2ecf20Sopenharmony_ci#include <linux/slab.h> 748c2ecf20Sopenharmony_ci#include <linux/crc32.h> 758c2ecf20Sopenharmony_ci#include <linux/math64.h> 768c2ecf20Sopenharmony_ci#include <linux/random.h> 778c2ecf20Sopenharmony_ci#include "ubi.h" 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define AV_FIND BIT(0) 828c2ecf20Sopenharmony_ci#define AV_ADD BIT(1) 838c2ecf20Sopenharmony_ci#define AV_FIND_OR_ADD (AV_FIND | AV_ADD) 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/** 868c2ecf20Sopenharmony_ci * find_or_add_av - internal function to find a volume, add a volume or do 878c2ecf20Sopenharmony_ci * both (find and add if missing). 888c2ecf20Sopenharmony_ci * @ai: attaching information 898c2ecf20Sopenharmony_ci * @vol_id: the requested volume ID 908c2ecf20Sopenharmony_ci * @flags: a combination of the %AV_FIND and %AV_ADD flags describing the 918c2ecf20Sopenharmony_ci * expected operation. If only %AV_ADD is set, -EEXIST is returned 928c2ecf20Sopenharmony_ci * if the volume already exists. If only %AV_FIND is set, NULL is 938c2ecf20Sopenharmony_ci * returned if the volume does not exist. And if both flags are 948c2ecf20Sopenharmony_ci * set, the helper first tries to find an existing volume, and if 958c2ecf20Sopenharmony_ci * it does not exist it creates a new one. 968c2ecf20Sopenharmony_ci * @created: in value used to inform the caller whether it"s a newly created 978c2ecf20Sopenharmony_ci * volume or not. 988c2ecf20Sopenharmony_ci * 998c2ecf20Sopenharmony_ci * This function returns a pointer to a volume description or an ERR_PTR if 1008c2ecf20Sopenharmony_ci * the operation failed. It can also return NULL if only %AV_FIND is set and 1018c2ecf20Sopenharmony_ci * the volume does not exist. 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_cistatic struct ubi_ainf_volume *find_or_add_av(struct ubi_attach_info *ai, 1048c2ecf20Sopenharmony_ci int vol_id, unsigned int flags, 1058c2ecf20Sopenharmony_ci bool *created) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 1088c2ecf20Sopenharmony_ci struct rb_node **p = &ai->volumes.rb_node, *parent = NULL; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* Walk the volume RB-tree to look if this volume is already present */ 1118c2ecf20Sopenharmony_ci while (*p) { 1128c2ecf20Sopenharmony_ci parent = *p; 1138c2ecf20Sopenharmony_ci av = rb_entry(parent, struct ubi_ainf_volume, rb); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (vol_id == av->vol_id) { 1168c2ecf20Sopenharmony_ci *created = false; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (!(flags & AV_FIND)) 1198c2ecf20Sopenharmony_ci return ERR_PTR(-EEXIST); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci return av; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (vol_id > av->vol_id) 1258c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 1268c2ecf20Sopenharmony_ci else 1278c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (!(flags & AV_ADD)) 1318c2ecf20Sopenharmony_ci return NULL; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* The volume is absent - add it */ 1348c2ecf20Sopenharmony_ci av = kzalloc(sizeof(*av), GFP_KERNEL); 1358c2ecf20Sopenharmony_ci if (!av) 1368c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci av->vol_id = vol_id; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (vol_id > ai->highest_vol_id) 1418c2ecf20Sopenharmony_ci ai->highest_vol_id = vol_id; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci rb_link_node(&av->rb, parent, p); 1448c2ecf20Sopenharmony_ci rb_insert_color(&av->rb, &ai->volumes); 1458c2ecf20Sopenharmony_ci ai->vols_found += 1; 1468c2ecf20Sopenharmony_ci *created = true; 1478c2ecf20Sopenharmony_ci dbg_bld("added volume %d", vol_id); 1488c2ecf20Sopenharmony_ci return av; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/** 1528c2ecf20Sopenharmony_ci * ubi_find_or_add_av - search for a volume in the attaching information and 1538c2ecf20Sopenharmony_ci * add one if it does not exist. 1548c2ecf20Sopenharmony_ci * @ai: attaching information 1558c2ecf20Sopenharmony_ci * @vol_id: the requested volume ID 1568c2ecf20Sopenharmony_ci * @created: whether the volume has been created or not 1578c2ecf20Sopenharmony_ci * 1588c2ecf20Sopenharmony_ci * This function returns a pointer to the new volume description or an 1598c2ecf20Sopenharmony_ci * ERR_PTR if the operation failed. 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_cistatic struct ubi_ainf_volume *ubi_find_or_add_av(struct ubi_attach_info *ai, 1628c2ecf20Sopenharmony_ci int vol_id, bool *created) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci return find_or_add_av(ai, vol_id, AV_FIND_OR_ADD, created); 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/** 1688c2ecf20Sopenharmony_ci * ubi_alloc_aeb - allocate an aeb element 1698c2ecf20Sopenharmony_ci * @ai: attaching information 1708c2ecf20Sopenharmony_ci * @pnum: physical eraseblock number 1718c2ecf20Sopenharmony_ci * @ec: erase counter of the physical eraseblock 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * Allocate an aeb object and initialize the pnum and ec information. 1748c2ecf20Sopenharmony_ci * vol_id and lnum are set to UBI_UNKNOWN, and the other fields are 1758c2ecf20Sopenharmony_ci * initialized to zero. 1768c2ecf20Sopenharmony_ci * Note that the element is not added in any list or RB tree. 1778c2ecf20Sopenharmony_ci */ 1788c2ecf20Sopenharmony_cistruct ubi_ainf_peb *ubi_alloc_aeb(struct ubi_attach_info *ai, int pnum, 1798c2ecf20Sopenharmony_ci int ec) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci aeb = kmem_cache_zalloc(ai->aeb_slab_cache, GFP_KERNEL); 1848c2ecf20Sopenharmony_ci if (!aeb) 1858c2ecf20Sopenharmony_ci return NULL; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci aeb->pnum = pnum; 1888c2ecf20Sopenharmony_ci aeb->ec = ec; 1898c2ecf20Sopenharmony_ci aeb->vol_id = UBI_UNKNOWN; 1908c2ecf20Sopenharmony_ci aeb->lnum = UBI_UNKNOWN; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci return aeb; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/** 1968c2ecf20Sopenharmony_ci * ubi_free_aeb - free an aeb element 1978c2ecf20Sopenharmony_ci * @ai: attaching information 1988c2ecf20Sopenharmony_ci * @aeb: the element to free 1998c2ecf20Sopenharmony_ci * 2008c2ecf20Sopenharmony_ci * Free an aeb object. The caller must have removed the element from any list 2018c2ecf20Sopenharmony_ci * or RB tree. 2028c2ecf20Sopenharmony_ci */ 2038c2ecf20Sopenharmony_civoid ubi_free_aeb(struct ubi_attach_info *ai, struct ubi_ainf_peb *aeb) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci kmem_cache_free(ai->aeb_slab_cache, aeb); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci/** 2098c2ecf20Sopenharmony_ci * add_to_list - add physical eraseblock to a list. 2108c2ecf20Sopenharmony_ci * @ai: attaching information 2118c2ecf20Sopenharmony_ci * @pnum: physical eraseblock number to add 2128c2ecf20Sopenharmony_ci * @vol_id: the last used volume id for the PEB 2138c2ecf20Sopenharmony_ci * @lnum: the last used LEB number for the PEB 2148c2ecf20Sopenharmony_ci * @ec: erase counter of the physical eraseblock 2158c2ecf20Sopenharmony_ci * @to_head: if not zero, add to the head of the list 2168c2ecf20Sopenharmony_ci * @list: the list to add to 2178c2ecf20Sopenharmony_ci * 2188c2ecf20Sopenharmony_ci * This function allocates a 'struct ubi_ainf_peb' object for physical 2198c2ecf20Sopenharmony_ci * eraseblock @pnum and adds it to the "free", "erase", or "alien" lists. 2208c2ecf20Sopenharmony_ci * It stores the @lnum and @vol_id alongside, which can both be 2218c2ecf20Sopenharmony_ci * %UBI_UNKNOWN if they are not available, not readable, or not assigned. 2228c2ecf20Sopenharmony_ci * If @to_head is not zero, PEB will be added to the head of the list, which 2238c2ecf20Sopenharmony_ci * basically means it will be processed first later. E.g., we add corrupted 2248c2ecf20Sopenharmony_ci * PEBs (corrupted due to power cuts) to the head of the erase list to make 2258c2ecf20Sopenharmony_ci * sure we erase them first and get rid of corruptions ASAP. This function 2268c2ecf20Sopenharmony_ci * returns zero in case of success and a negative error code in case of 2278c2ecf20Sopenharmony_ci * failure. 2288c2ecf20Sopenharmony_ci */ 2298c2ecf20Sopenharmony_cistatic int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, 2308c2ecf20Sopenharmony_ci int lnum, int ec, int to_head, struct list_head *list) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (list == &ai->free) { 2358c2ecf20Sopenharmony_ci dbg_bld("add to free: PEB %d, EC %d", pnum, ec); 2368c2ecf20Sopenharmony_ci } else if (list == &ai->erase) { 2378c2ecf20Sopenharmony_ci dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); 2388c2ecf20Sopenharmony_ci } else if (list == &ai->alien) { 2398c2ecf20Sopenharmony_ci dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); 2408c2ecf20Sopenharmony_ci ai->alien_peb_count += 1; 2418c2ecf20Sopenharmony_ci } else 2428c2ecf20Sopenharmony_ci BUG(); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci aeb = ubi_alloc_aeb(ai, pnum, ec); 2458c2ecf20Sopenharmony_ci if (!aeb) 2468c2ecf20Sopenharmony_ci return -ENOMEM; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci aeb->vol_id = vol_id; 2498c2ecf20Sopenharmony_ci aeb->lnum = lnum; 2508c2ecf20Sopenharmony_ci if (to_head) 2518c2ecf20Sopenharmony_ci list_add(&aeb->u.list, list); 2528c2ecf20Sopenharmony_ci else 2538c2ecf20Sopenharmony_ci list_add_tail(&aeb->u.list, list); 2548c2ecf20Sopenharmony_ci return 0; 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci/** 2588c2ecf20Sopenharmony_ci * add_corrupted - add a corrupted physical eraseblock. 2598c2ecf20Sopenharmony_ci * @ai: attaching information 2608c2ecf20Sopenharmony_ci * @pnum: physical eraseblock number to add 2618c2ecf20Sopenharmony_ci * @ec: erase counter of the physical eraseblock 2628c2ecf20Sopenharmony_ci * 2638c2ecf20Sopenharmony_ci * This function allocates a 'struct ubi_ainf_peb' object for a corrupted 2648c2ecf20Sopenharmony_ci * physical eraseblock @pnum and adds it to the 'corr' list. The corruption 2658c2ecf20Sopenharmony_ci * was presumably not caused by a power cut. Returns zero in case of success 2668c2ecf20Sopenharmony_ci * and a negative error code in case of failure. 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_cistatic int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci aeb = ubi_alloc_aeb(ai, pnum, ec); 2758c2ecf20Sopenharmony_ci if (!aeb) 2768c2ecf20Sopenharmony_ci return -ENOMEM; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci ai->corr_peb_count += 1; 2798c2ecf20Sopenharmony_ci list_add(&aeb->u.list, &ai->corr); 2808c2ecf20Sopenharmony_ci return 0; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci/** 2848c2ecf20Sopenharmony_ci * add_fastmap - add a Fastmap related physical eraseblock. 2858c2ecf20Sopenharmony_ci * @ai: attaching information 2868c2ecf20Sopenharmony_ci * @pnum: physical eraseblock number the VID header came from 2878c2ecf20Sopenharmony_ci * @vid_hdr: the volume identifier header 2888c2ecf20Sopenharmony_ci * @ec: erase counter of the physical eraseblock 2898c2ecf20Sopenharmony_ci * 2908c2ecf20Sopenharmony_ci * This function allocates a 'struct ubi_ainf_peb' object for a Fastamp 2918c2ecf20Sopenharmony_ci * physical eraseblock @pnum and adds it to the 'fastmap' list. 2928c2ecf20Sopenharmony_ci * Such blocks can be Fastmap super and data blocks from both the most 2938c2ecf20Sopenharmony_ci * recent Fastmap we're attaching from or from old Fastmaps which will 2948c2ecf20Sopenharmony_ci * be erased. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_cistatic int add_fastmap(struct ubi_attach_info *ai, int pnum, 2978c2ecf20Sopenharmony_ci struct ubi_vid_hdr *vid_hdr, int ec) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci aeb = ubi_alloc_aeb(ai, pnum, ec); 3028c2ecf20Sopenharmony_ci if (!aeb) 3038c2ecf20Sopenharmony_ci return -ENOMEM; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci aeb->vol_id = be32_to_cpu(vid_hdr->vol_id); 3068c2ecf20Sopenharmony_ci aeb->sqnum = be64_to_cpu(vid_hdr->sqnum); 3078c2ecf20Sopenharmony_ci list_add(&aeb->u.list, &ai->fastmap); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci dbg_bld("add to fastmap list: PEB %d, vol_id %d, sqnum: %llu", pnum, 3108c2ecf20Sopenharmony_ci aeb->vol_id, aeb->sqnum); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci return 0; 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci/** 3168c2ecf20Sopenharmony_ci * validate_vid_hdr - check volume identifier header. 3178c2ecf20Sopenharmony_ci * @ubi: UBI device description object 3188c2ecf20Sopenharmony_ci * @vid_hdr: the volume identifier header to check 3198c2ecf20Sopenharmony_ci * @av: information about the volume this logical eraseblock belongs to 3208c2ecf20Sopenharmony_ci * @pnum: physical eraseblock number the VID header came from 3218c2ecf20Sopenharmony_ci * 3228c2ecf20Sopenharmony_ci * This function checks that data stored in @vid_hdr is consistent. Returns 3238c2ecf20Sopenharmony_ci * non-zero if an inconsistency was found and zero if not. 3248c2ecf20Sopenharmony_ci * 3258c2ecf20Sopenharmony_ci * Note, UBI does sanity check of everything it reads from the flash media. 3268c2ecf20Sopenharmony_ci * Most of the checks are done in the I/O sub-system. Here we check that the 3278c2ecf20Sopenharmony_ci * information in the VID header is consistent to the information in other VID 3288c2ecf20Sopenharmony_ci * headers of the same volume. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_cistatic int validate_vid_hdr(const struct ubi_device *ubi, 3318c2ecf20Sopenharmony_ci const struct ubi_vid_hdr *vid_hdr, 3328c2ecf20Sopenharmony_ci const struct ubi_ainf_volume *av, int pnum) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci int vol_type = vid_hdr->vol_type; 3358c2ecf20Sopenharmony_ci int vol_id = be32_to_cpu(vid_hdr->vol_id); 3368c2ecf20Sopenharmony_ci int used_ebs = be32_to_cpu(vid_hdr->used_ebs); 3378c2ecf20Sopenharmony_ci int data_pad = be32_to_cpu(vid_hdr->data_pad); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (av->leb_count != 0) { 3408c2ecf20Sopenharmony_ci int av_vol_type; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* 3438c2ecf20Sopenharmony_ci * This is not the first logical eraseblock belonging to this 3448c2ecf20Sopenharmony_ci * volume. Ensure that the data in its VID header is consistent 3458c2ecf20Sopenharmony_ci * to the data in previous logical eraseblock headers. 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci if (vol_id != av->vol_id) { 3498c2ecf20Sopenharmony_ci ubi_err(ubi, "inconsistent vol_id"); 3508c2ecf20Sopenharmony_ci goto bad; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci if (av->vol_type == UBI_STATIC_VOLUME) 3548c2ecf20Sopenharmony_ci av_vol_type = UBI_VID_STATIC; 3558c2ecf20Sopenharmony_ci else 3568c2ecf20Sopenharmony_ci av_vol_type = UBI_VID_DYNAMIC; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (vol_type != av_vol_type) { 3598c2ecf20Sopenharmony_ci ubi_err(ubi, "inconsistent vol_type"); 3608c2ecf20Sopenharmony_ci goto bad; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if (used_ebs != av->used_ebs) { 3648c2ecf20Sopenharmony_ci ubi_err(ubi, "inconsistent used_ebs"); 3658c2ecf20Sopenharmony_ci goto bad; 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (data_pad != av->data_pad) { 3698c2ecf20Sopenharmony_ci ubi_err(ubi, "inconsistent data_pad"); 3708c2ecf20Sopenharmony_ci goto bad; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci return 0; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cibad: 3778c2ecf20Sopenharmony_ci ubi_err(ubi, "inconsistent VID header at PEB %d", pnum); 3788c2ecf20Sopenharmony_ci ubi_dump_vid_hdr(vid_hdr); 3798c2ecf20Sopenharmony_ci ubi_dump_av(av); 3808c2ecf20Sopenharmony_ci return -EINVAL; 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/** 3848c2ecf20Sopenharmony_ci * add_volume - add volume to the attaching information. 3858c2ecf20Sopenharmony_ci * @ai: attaching information 3868c2ecf20Sopenharmony_ci * @vol_id: ID of the volume to add 3878c2ecf20Sopenharmony_ci * @pnum: physical eraseblock number 3888c2ecf20Sopenharmony_ci * @vid_hdr: volume identifier header 3898c2ecf20Sopenharmony_ci * 3908c2ecf20Sopenharmony_ci * If the volume corresponding to the @vid_hdr logical eraseblock is already 3918c2ecf20Sopenharmony_ci * present in the attaching information, this function does nothing. Otherwise 3928c2ecf20Sopenharmony_ci * it adds corresponding volume to the attaching information. Returns a pointer 3938c2ecf20Sopenharmony_ci * to the allocated "av" object in case of success and a negative error code in 3948c2ecf20Sopenharmony_ci * case of failure. 3958c2ecf20Sopenharmony_ci */ 3968c2ecf20Sopenharmony_cistatic struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai, 3978c2ecf20Sopenharmony_ci int vol_id, int pnum, 3988c2ecf20Sopenharmony_ci const struct ubi_vid_hdr *vid_hdr) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 4018c2ecf20Sopenharmony_ci bool created; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id)); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci av = ubi_find_or_add_av(ai, vol_id, &created); 4068c2ecf20Sopenharmony_ci if (IS_ERR(av) || !created) 4078c2ecf20Sopenharmony_ci return av; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci av->used_ebs = be32_to_cpu(vid_hdr->used_ebs); 4108c2ecf20Sopenharmony_ci av->data_pad = be32_to_cpu(vid_hdr->data_pad); 4118c2ecf20Sopenharmony_ci av->compat = vid_hdr->compat; 4128c2ecf20Sopenharmony_ci av->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME 4138c2ecf20Sopenharmony_ci : UBI_STATIC_VOLUME; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci return av; 4168c2ecf20Sopenharmony_ci} 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci/** 4198c2ecf20Sopenharmony_ci * ubi_compare_lebs - find out which logical eraseblock is newer. 4208c2ecf20Sopenharmony_ci * @ubi: UBI device description object 4218c2ecf20Sopenharmony_ci * @aeb: first logical eraseblock to compare 4228c2ecf20Sopenharmony_ci * @pnum: physical eraseblock number of the second logical eraseblock to 4238c2ecf20Sopenharmony_ci * compare 4248c2ecf20Sopenharmony_ci * @vid_hdr: volume identifier header of the second logical eraseblock 4258c2ecf20Sopenharmony_ci * 4268c2ecf20Sopenharmony_ci * This function compares 2 copies of a LEB and informs which one is newer. In 4278c2ecf20Sopenharmony_ci * case of success this function returns a positive value, in case of failure, a 4288c2ecf20Sopenharmony_ci * negative error code is returned. The success return codes use the following 4298c2ecf20Sopenharmony_ci * bits: 4308c2ecf20Sopenharmony_ci * o bit 0 is cleared: the first PEB (described by @aeb) is newer than the 4318c2ecf20Sopenharmony_ci * second PEB (described by @pnum and @vid_hdr); 4328c2ecf20Sopenharmony_ci * o bit 0 is set: the second PEB is newer; 4338c2ecf20Sopenharmony_ci * o bit 1 is cleared: no bit-flips were detected in the newer LEB; 4348c2ecf20Sopenharmony_ci * o bit 1 is set: bit-flips were detected in the newer LEB; 4358c2ecf20Sopenharmony_ci * o bit 2 is cleared: the older LEB is not corrupted; 4368c2ecf20Sopenharmony_ci * o bit 2 is set: the older LEB is corrupted. 4378c2ecf20Sopenharmony_ci */ 4388c2ecf20Sopenharmony_ciint ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, 4398c2ecf20Sopenharmony_ci int pnum, const struct ubi_vid_hdr *vid_hdr) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci int len, err, second_is_newer, bitflips = 0, corrupted = 0; 4428c2ecf20Sopenharmony_ci uint32_t data_crc, crc; 4438c2ecf20Sopenharmony_ci struct ubi_vid_io_buf *vidb = NULL; 4448c2ecf20Sopenharmony_ci unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci if (sqnum2 == aeb->sqnum) { 4478c2ecf20Sopenharmony_ci /* 4488c2ecf20Sopenharmony_ci * This must be a really ancient UBI image which has been 4498c2ecf20Sopenharmony_ci * created before sequence numbers support has been added. At 4508c2ecf20Sopenharmony_ci * that times we used 32-bit LEB versions stored in logical 4518c2ecf20Sopenharmony_ci * eraseblocks. That was before UBI got into mainline. We do not 4528c2ecf20Sopenharmony_ci * support these images anymore. Well, those images still work, 4538c2ecf20Sopenharmony_ci * but only if no unclean reboots happened. 4548c2ecf20Sopenharmony_ci */ 4558c2ecf20Sopenharmony_ci ubi_err(ubi, "unsupported on-flash UBI format"); 4568c2ecf20Sopenharmony_ci return -EINVAL; 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci /* Obviously the LEB with lower sequence counter is older */ 4608c2ecf20Sopenharmony_ci second_is_newer = (sqnum2 > aeb->sqnum); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* 4638c2ecf20Sopenharmony_ci * Now we know which copy is newer. If the copy flag of the PEB with 4648c2ecf20Sopenharmony_ci * newer version is not set, then we just return, otherwise we have to 4658c2ecf20Sopenharmony_ci * check data CRC. For the second PEB we already have the VID header, 4668c2ecf20Sopenharmony_ci * for the first one - we'll need to re-read it from flash. 4678c2ecf20Sopenharmony_ci * 4688c2ecf20Sopenharmony_ci * Note: this may be optimized so that we wouldn't read twice. 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci if (second_is_newer) { 4728c2ecf20Sopenharmony_ci if (!vid_hdr->copy_flag) { 4738c2ecf20Sopenharmony_ci /* It is not a copy, so it is newer */ 4748c2ecf20Sopenharmony_ci dbg_bld("second PEB %d is newer, copy_flag is unset", 4758c2ecf20Sopenharmony_ci pnum); 4768c2ecf20Sopenharmony_ci return 1; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci } else { 4798c2ecf20Sopenharmony_ci if (!aeb->copy_flag) { 4808c2ecf20Sopenharmony_ci /* It is not a copy, so it is newer */ 4818c2ecf20Sopenharmony_ci dbg_bld("first PEB %d is newer, copy_flag is unset", 4828c2ecf20Sopenharmony_ci pnum); 4838c2ecf20Sopenharmony_ci return bitflips << 1; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL); 4878c2ecf20Sopenharmony_ci if (!vidb) 4888c2ecf20Sopenharmony_ci return -ENOMEM; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci pnum = aeb->pnum; 4918c2ecf20Sopenharmony_ci err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 0); 4928c2ecf20Sopenharmony_ci if (err) { 4938c2ecf20Sopenharmony_ci if (err == UBI_IO_BITFLIPS) 4948c2ecf20Sopenharmony_ci bitflips = 1; 4958c2ecf20Sopenharmony_ci else { 4968c2ecf20Sopenharmony_ci ubi_err(ubi, "VID of PEB %d header is bad, but it was OK earlier, err %d", 4978c2ecf20Sopenharmony_ci pnum, err); 4988c2ecf20Sopenharmony_ci if (err > 0) 4998c2ecf20Sopenharmony_ci err = -EIO; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci goto out_free_vidh; 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci vid_hdr = ubi_get_vid_hdr(vidb); 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci /* Read the data of the copy and check the CRC */ 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci len = be32_to_cpu(vid_hdr->data_size); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci mutex_lock(&ubi->buf_mutex); 5138c2ecf20Sopenharmony_ci err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, len); 5148c2ecf20Sopenharmony_ci if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) 5158c2ecf20Sopenharmony_ci goto out_unlock; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci data_crc = be32_to_cpu(vid_hdr->data_crc); 5188c2ecf20Sopenharmony_ci crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, len); 5198c2ecf20Sopenharmony_ci if (crc != data_crc) { 5208c2ecf20Sopenharmony_ci dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x", 5218c2ecf20Sopenharmony_ci pnum, crc, data_crc); 5228c2ecf20Sopenharmony_ci corrupted = 1; 5238c2ecf20Sopenharmony_ci bitflips = 0; 5248c2ecf20Sopenharmony_ci second_is_newer = !second_is_newer; 5258c2ecf20Sopenharmony_ci } else { 5268c2ecf20Sopenharmony_ci dbg_bld("PEB %d CRC is OK", pnum); 5278c2ecf20Sopenharmony_ci bitflips |= !!err; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci mutex_unlock(&ubi->buf_mutex); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci ubi_free_vid_buf(vidb); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci if (second_is_newer) 5348c2ecf20Sopenharmony_ci dbg_bld("second PEB %d is newer, copy_flag is set", pnum); 5358c2ecf20Sopenharmony_ci else 5368c2ecf20Sopenharmony_ci dbg_bld("first PEB %d is newer, copy_flag is set", pnum); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci return second_is_newer | (bitflips << 1) | (corrupted << 2); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ciout_unlock: 5418c2ecf20Sopenharmony_ci mutex_unlock(&ubi->buf_mutex); 5428c2ecf20Sopenharmony_ciout_free_vidh: 5438c2ecf20Sopenharmony_ci ubi_free_vid_buf(vidb); 5448c2ecf20Sopenharmony_ci return err; 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci/** 5488c2ecf20Sopenharmony_ci * ubi_add_to_av - add used physical eraseblock to the attaching information. 5498c2ecf20Sopenharmony_ci * @ubi: UBI device description object 5508c2ecf20Sopenharmony_ci * @ai: attaching information 5518c2ecf20Sopenharmony_ci * @pnum: the physical eraseblock number 5528c2ecf20Sopenharmony_ci * @ec: erase counter 5538c2ecf20Sopenharmony_ci * @vid_hdr: the volume identifier header 5548c2ecf20Sopenharmony_ci * @bitflips: if bit-flips were detected when this physical eraseblock was read 5558c2ecf20Sopenharmony_ci * 5568c2ecf20Sopenharmony_ci * This function adds information about a used physical eraseblock to the 5578c2ecf20Sopenharmony_ci * 'used' tree of the corresponding volume. The function is rather complex 5588c2ecf20Sopenharmony_ci * because it has to handle cases when this is not the first physical 5598c2ecf20Sopenharmony_ci * eraseblock belonging to the same logical eraseblock, and the newer one has 5608c2ecf20Sopenharmony_ci * to be picked, while the older one has to be dropped. This function returns 5618c2ecf20Sopenharmony_ci * zero in case of success and a negative error code in case of failure. 5628c2ecf20Sopenharmony_ci */ 5638c2ecf20Sopenharmony_ciint ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, 5648c2ecf20Sopenharmony_ci int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci int err, vol_id, lnum; 5678c2ecf20Sopenharmony_ci unsigned long long sqnum; 5688c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 5698c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 5708c2ecf20Sopenharmony_ci struct rb_node **p, *parent = NULL; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci vol_id = be32_to_cpu(vid_hdr->vol_id); 5738c2ecf20Sopenharmony_ci lnum = be32_to_cpu(vid_hdr->lnum); 5748c2ecf20Sopenharmony_ci sqnum = be64_to_cpu(vid_hdr->sqnum); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d", 5778c2ecf20Sopenharmony_ci pnum, vol_id, lnum, ec, sqnum, bitflips); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci av = add_volume(ai, vol_id, pnum, vid_hdr); 5808c2ecf20Sopenharmony_ci if (IS_ERR(av)) 5818c2ecf20Sopenharmony_ci return PTR_ERR(av); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci if (ai->max_sqnum < sqnum) 5848c2ecf20Sopenharmony_ci ai->max_sqnum = sqnum; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci /* 5878c2ecf20Sopenharmony_ci * Walk the RB-tree of logical eraseblocks of volume @vol_id to look 5888c2ecf20Sopenharmony_ci * if this is the first instance of this logical eraseblock or not. 5898c2ecf20Sopenharmony_ci */ 5908c2ecf20Sopenharmony_ci p = &av->root.rb_node; 5918c2ecf20Sopenharmony_ci while (*p) { 5928c2ecf20Sopenharmony_ci int cmp_res; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci parent = *p; 5958c2ecf20Sopenharmony_ci aeb = rb_entry(parent, struct ubi_ainf_peb, u.rb); 5968c2ecf20Sopenharmony_ci if (lnum != aeb->lnum) { 5978c2ecf20Sopenharmony_ci if (lnum < aeb->lnum) 5988c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 5998c2ecf20Sopenharmony_ci else 6008c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 6018c2ecf20Sopenharmony_ci continue; 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* 6058c2ecf20Sopenharmony_ci * There is already a physical eraseblock describing the same 6068c2ecf20Sopenharmony_ci * logical eraseblock present. 6078c2ecf20Sopenharmony_ci */ 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci dbg_bld("this LEB already exists: PEB %d, sqnum %llu, EC %d", 6108c2ecf20Sopenharmony_ci aeb->pnum, aeb->sqnum, aeb->ec); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* 6138c2ecf20Sopenharmony_ci * Make sure that the logical eraseblocks have different 6148c2ecf20Sopenharmony_ci * sequence numbers. Otherwise the image is bad. 6158c2ecf20Sopenharmony_ci * 6168c2ecf20Sopenharmony_ci * However, if the sequence number is zero, we assume it must 6178c2ecf20Sopenharmony_ci * be an ancient UBI image from the era when UBI did not have 6188c2ecf20Sopenharmony_ci * sequence numbers. We still can attach these images, unless 6198c2ecf20Sopenharmony_ci * there is a need to distinguish between old and new 6208c2ecf20Sopenharmony_ci * eraseblocks, in which case we'll refuse the image in 6218c2ecf20Sopenharmony_ci * 'ubi_compare_lebs()'. In other words, we attach old clean 6228c2ecf20Sopenharmony_ci * images, but refuse attaching old images with duplicated 6238c2ecf20Sopenharmony_ci * logical eraseblocks because there was an unclean reboot. 6248c2ecf20Sopenharmony_ci */ 6258c2ecf20Sopenharmony_ci if (aeb->sqnum == sqnum && sqnum != 0) { 6268c2ecf20Sopenharmony_ci ubi_err(ubi, "two LEBs with same sequence number %llu", 6278c2ecf20Sopenharmony_ci sqnum); 6288c2ecf20Sopenharmony_ci ubi_dump_aeb(aeb, 0); 6298c2ecf20Sopenharmony_ci ubi_dump_vid_hdr(vid_hdr); 6308c2ecf20Sopenharmony_ci return -EINVAL; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci /* 6348c2ecf20Sopenharmony_ci * Now we have to drop the older one and preserve the newer 6358c2ecf20Sopenharmony_ci * one. 6368c2ecf20Sopenharmony_ci */ 6378c2ecf20Sopenharmony_ci cmp_res = ubi_compare_lebs(ubi, aeb, pnum, vid_hdr); 6388c2ecf20Sopenharmony_ci if (cmp_res < 0) 6398c2ecf20Sopenharmony_ci return cmp_res; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci if (cmp_res & 1) { 6428c2ecf20Sopenharmony_ci /* 6438c2ecf20Sopenharmony_ci * This logical eraseblock is newer than the one 6448c2ecf20Sopenharmony_ci * found earlier. 6458c2ecf20Sopenharmony_ci */ 6468c2ecf20Sopenharmony_ci err = validate_vid_hdr(ubi, vid_hdr, av, pnum); 6478c2ecf20Sopenharmony_ci if (err) 6488c2ecf20Sopenharmony_ci return err; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci err = add_to_list(ai, aeb->pnum, aeb->vol_id, 6518c2ecf20Sopenharmony_ci aeb->lnum, aeb->ec, cmp_res & 4, 6528c2ecf20Sopenharmony_ci &ai->erase); 6538c2ecf20Sopenharmony_ci if (err) 6548c2ecf20Sopenharmony_ci return err; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci aeb->ec = ec; 6578c2ecf20Sopenharmony_ci aeb->pnum = pnum; 6588c2ecf20Sopenharmony_ci aeb->vol_id = vol_id; 6598c2ecf20Sopenharmony_ci aeb->lnum = lnum; 6608c2ecf20Sopenharmony_ci aeb->scrub = ((cmp_res & 2) || bitflips); 6618c2ecf20Sopenharmony_ci aeb->copy_flag = vid_hdr->copy_flag; 6628c2ecf20Sopenharmony_ci aeb->sqnum = sqnum; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci if (av->highest_lnum == lnum) 6658c2ecf20Sopenharmony_ci av->last_data_size = 6668c2ecf20Sopenharmony_ci be32_to_cpu(vid_hdr->data_size); 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci return 0; 6698c2ecf20Sopenharmony_ci } else { 6708c2ecf20Sopenharmony_ci /* 6718c2ecf20Sopenharmony_ci * This logical eraseblock is older than the one found 6728c2ecf20Sopenharmony_ci * previously. 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_ci return add_to_list(ai, pnum, vol_id, lnum, ec, 6758c2ecf20Sopenharmony_ci cmp_res & 4, &ai->erase); 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci /* 6808c2ecf20Sopenharmony_ci * We've met this logical eraseblock for the first time, add it to the 6818c2ecf20Sopenharmony_ci * attaching information. 6828c2ecf20Sopenharmony_ci */ 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci err = validate_vid_hdr(ubi, vid_hdr, av, pnum); 6858c2ecf20Sopenharmony_ci if (err) 6868c2ecf20Sopenharmony_ci return err; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci aeb = ubi_alloc_aeb(ai, pnum, ec); 6898c2ecf20Sopenharmony_ci if (!aeb) 6908c2ecf20Sopenharmony_ci return -ENOMEM; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci aeb->vol_id = vol_id; 6938c2ecf20Sopenharmony_ci aeb->lnum = lnum; 6948c2ecf20Sopenharmony_ci aeb->scrub = bitflips; 6958c2ecf20Sopenharmony_ci aeb->copy_flag = vid_hdr->copy_flag; 6968c2ecf20Sopenharmony_ci aeb->sqnum = sqnum; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci if (av->highest_lnum <= lnum) { 6998c2ecf20Sopenharmony_ci av->highest_lnum = lnum; 7008c2ecf20Sopenharmony_ci av->last_data_size = be32_to_cpu(vid_hdr->data_size); 7018c2ecf20Sopenharmony_ci } 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci av->leb_count += 1; 7048c2ecf20Sopenharmony_ci rb_link_node(&aeb->u.rb, parent, p); 7058c2ecf20Sopenharmony_ci rb_insert_color(&aeb->u.rb, &av->root); 7068c2ecf20Sopenharmony_ci return 0; 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci/** 7108c2ecf20Sopenharmony_ci * ubi_add_av - add volume to the attaching information. 7118c2ecf20Sopenharmony_ci * @ai: attaching information 7128c2ecf20Sopenharmony_ci * @vol_id: the requested volume ID 7138c2ecf20Sopenharmony_ci * 7148c2ecf20Sopenharmony_ci * This function returns a pointer to the new volume description or an 7158c2ecf20Sopenharmony_ci * ERR_PTR if the operation failed. 7168c2ecf20Sopenharmony_ci */ 7178c2ecf20Sopenharmony_cistruct ubi_ainf_volume *ubi_add_av(struct ubi_attach_info *ai, int vol_id) 7188c2ecf20Sopenharmony_ci{ 7198c2ecf20Sopenharmony_ci bool created; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci return find_or_add_av(ai, vol_id, AV_ADD, &created); 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci/** 7258c2ecf20Sopenharmony_ci * ubi_find_av - find volume in the attaching information. 7268c2ecf20Sopenharmony_ci * @ai: attaching information 7278c2ecf20Sopenharmony_ci * @vol_id: the requested volume ID 7288c2ecf20Sopenharmony_ci * 7298c2ecf20Sopenharmony_ci * This function returns a pointer to the volume description or %NULL if there 7308c2ecf20Sopenharmony_ci * are no data about this volume in the attaching information. 7318c2ecf20Sopenharmony_ci */ 7328c2ecf20Sopenharmony_cistruct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, 7338c2ecf20Sopenharmony_ci int vol_id) 7348c2ecf20Sopenharmony_ci{ 7358c2ecf20Sopenharmony_ci bool created; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci return find_or_add_av((struct ubi_attach_info *)ai, vol_id, AV_FIND, 7388c2ecf20Sopenharmony_ci &created); 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_cistatic void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av, 7428c2ecf20Sopenharmony_ci struct list_head *list); 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci/** 7458c2ecf20Sopenharmony_ci * ubi_remove_av - delete attaching information about a volume. 7468c2ecf20Sopenharmony_ci * @ai: attaching information 7478c2ecf20Sopenharmony_ci * @av: the volume attaching information to delete 7488c2ecf20Sopenharmony_ci */ 7498c2ecf20Sopenharmony_civoid ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) 7508c2ecf20Sopenharmony_ci{ 7518c2ecf20Sopenharmony_ci dbg_bld("remove attaching information about volume %d", av->vol_id); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci rb_erase(&av->rb, &ai->volumes); 7548c2ecf20Sopenharmony_ci destroy_av(ai, av, &ai->erase); 7558c2ecf20Sopenharmony_ci ai->vols_found -= 1; 7568c2ecf20Sopenharmony_ci} 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci/** 7598c2ecf20Sopenharmony_ci * early_erase_peb - erase a physical eraseblock. 7608c2ecf20Sopenharmony_ci * @ubi: UBI device description object 7618c2ecf20Sopenharmony_ci * @ai: attaching information 7628c2ecf20Sopenharmony_ci * @pnum: physical eraseblock number to erase; 7638c2ecf20Sopenharmony_ci * @ec: erase counter value to write (%UBI_UNKNOWN if it is unknown) 7648c2ecf20Sopenharmony_ci * 7658c2ecf20Sopenharmony_ci * This function erases physical eraseblock 'pnum', and writes the erase 7668c2ecf20Sopenharmony_ci * counter header to it. This function should only be used on UBI device 7678c2ecf20Sopenharmony_ci * initialization stages, when the EBA sub-system had not been yet initialized. 7688c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in 7698c2ecf20Sopenharmony_ci * case of failure. 7708c2ecf20Sopenharmony_ci */ 7718c2ecf20Sopenharmony_cistatic int early_erase_peb(struct ubi_device *ubi, 7728c2ecf20Sopenharmony_ci const struct ubi_attach_info *ai, int pnum, int ec) 7738c2ecf20Sopenharmony_ci{ 7748c2ecf20Sopenharmony_ci int err; 7758c2ecf20Sopenharmony_ci struct ubi_ec_hdr *ec_hdr; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci if ((long long)ec >= UBI_MAX_ERASECOUNTER) { 7788c2ecf20Sopenharmony_ci /* 7798c2ecf20Sopenharmony_ci * Erase counter overflow. Upgrade UBI and use 64-bit 7808c2ecf20Sopenharmony_ci * erase counters internally. 7818c2ecf20Sopenharmony_ci */ 7828c2ecf20Sopenharmony_ci ubi_err(ubi, "erase counter overflow at PEB %d, EC %d", 7838c2ecf20Sopenharmony_ci pnum, ec); 7848c2ecf20Sopenharmony_ci return -EINVAL; 7858c2ecf20Sopenharmony_ci } 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); 7888c2ecf20Sopenharmony_ci if (!ec_hdr) 7898c2ecf20Sopenharmony_ci return -ENOMEM; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci ec_hdr->ec = cpu_to_be64(ec); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci err = ubi_io_sync_erase(ubi, pnum, 0); 7948c2ecf20Sopenharmony_ci if (err < 0) 7958c2ecf20Sopenharmony_ci goto out_free; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci err = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ciout_free: 8008c2ecf20Sopenharmony_ci kfree(ec_hdr); 8018c2ecf20Sopenharmony_ci return err; 8028c2ecf20Sopenharmony_ci} 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci/** 8058c2ecf20Sopenharmony_ci * ubi_early_get_peb - get a free physical eraseblock. 8068c2ecf20Sopenharmony_ci * @ubi: UBI device description object 8078c2ecf20Sopenharmony_ci * @ai: attaching information 8088c2ecf20Sopenharmony_ci * 8098c2ecf20Sopenharmony_ci * This function returns a free physical eraseblock. It is supposed to be 8108c2ecf20Sopenharmony_ci * called on the UBI initialization stages when the wear-leveling sub-system is 8118c2ecf20Sopenharmony_ci * not initialized yet. This function picks a physical eraseblocks from one of 8128c2ecf20Sopenharmony_ci * the lists, writes the EC header if it is needed, and removes it from the 8138c2ecf20Sopenharmony_ci * list. 8148c2ecf20Sopenharmony_ci * 8158c2ecf20Sopenharmony_ci * This function returns a pointer to the "aeb" of the found free PEB in case 8168c2ecf20Sopenharmony_ci * of success and an error code in case of failure. 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_cistruct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, 8198c2ecf20Sopenharmony_ci struct ubi_attach_info *ai) 8208c2ecf20Sopenharmony_ci{ 8218c2ecf20Sopenharmony_ci int err = 0; 8228c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb, *tmp_aeb; 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci if (!list_empty(&ai->free)) { 8258c2ecf20Sopenharmony_ci aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list); 8268c2ecf20Sopenharmony_ci list_del(&aeb->u.list); 8278c2ecf20Sopenharmony_ci dbg_bld("return free PEB %d, EC %d", aeb->pnum, aeb->ec); 8288c2ecf20Sopenharmony_ci return aeb; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci /* 8328c2ecf20Sopenharmony_ci * We try to erase the first physical eraseblock from the erase list 8338c2ecf20Sopenharmony_ci * and pick it if we succeed, or try to erase the next one if not. And 8348c2ecf20Sopenharmony_ci * so forth. We don't want to take care about bad eraseblocks here - 8358c2ecf20Sopenharmony_ci * they'll be handled later. 8368c2ecf20Sopenharmony_ci */ 8378c2ecf20Sopenharmony_ci list_for_each_entry_safe(aeb, tmp_aeb, &ai->erase, u.list) { 8388c2ecf20Sopenharmony_ci if (aeb->ec == UBI_UNKNOWN) 8398c2ecf20Sopenharmony_ci aeb->ec = ai->mean_ec; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1); 8428c2ecf20Sopenharmony_ci if (err) 8438c2ecf20Sopenharmony_ci continue; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci aeb->ec += 1; 8468c2ecf20Sopenharmony_ci list_del(&aeb->u.list); 8478c2ecf20Sopenharmony_ci dbg_bld("return PEB %d, EC %d", aeb->pnum, aeb->ec); 8488c2ecf20Sopenharmony_ci return aeb; 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci ubi_err(ubi, "no free eraseblocks"); 8528c2ecf20Sopenharmony_ci return ERR_PTR(-ENOSPC); 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci/** 8568c2ecf20Sopenharmony_ci * check_corruption - check the data area of PEB. 8578c2ecf20Sopenharmony_ci * @ubi: UBI device description object 8588c2ecf20Sopenharmony_ci * @vid_hdr: the (corrupted) VID header of this PEB 8598c2ecf20Sopenharmony_ci * @pnum: the physical eraseblock number to check 8608c2ecf20Sopenharmony_ci * 8618c2ecf20Sopenharmony_ci * This is a helper function which is used to distinguish between VID header 8628c2ecf20Sopenharmony_ci * corruptions caused by power cuts and other reasons. If the PEB contains only 8638c2ecf20Sopenharmony_ci * 0xFF bytes in the data area, the VID header is most probably corrupted 8648c2ecf20Sopenharmony_ci * because of a power cut (%0 is returned in this case). Otherwise, it was 8658c2ecf20Sopenharmony_ci * probably corrupted for some other reasons (%1 is returned in this case). A 8668c2ecf20Sopenharmony_ci * negative error code is returned if a read error occurred. 8678c2ecf20Sopenharmony_ci * 8688c2ecf20Sopenharmony_ci * If the corruption reason was a power cut, UBI can safely erase this PEB. 8698c2ecf20Sopenharmony_ci * Otherwise, it should preserve it to avoid possibly destroying important 8708c2ecf20Sopenharmony_ci * information. 8718c2ecf20Sopenharmony_ci */ 8728c2ecf20Sopenharmony_cistatic int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, 8738c2ecf20Sopenharmony_ci int pnum) 8748c2ecf20Sopenharmony_ci{ 8758c2ecf20Sopenharmony_ci int err; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci mutex_lock(&ubi->buf_mutex); 8788c2ecf20Sopenharmony_ci memset(ubi->peb_buf, 0x00, ubi->leb_size); 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci err = ubi_io_read(ubi, ubi->peb_buf, pnum, ubi->leb_start, 8818c2ecf20Sopenharmony_ci ubi->leb_size); 8828c2ecf20Sopenharmony_ci if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) { 8838c2ecf20Sopenharmony_ci /* 8848c2ecf20Sopenharmony_ci * Bit-flips or integrity errors while reading the data area. 8858c2ecf20Sopenharmony_ci * It is difficult to say for sure what type of corruption is 8868c2ecf20Sopenharmony_ci * this, but presumably a power cut happened while this PEB was 8878c2ecf20Sopenharmony_ci * erased, so it became unstable and corrupted, and should be 8888c2ecf20Sopenharmony_ci * erased. 8898c2ecf20Sopenharmony_ci */ 8908c2ecf20Sopenharmony_ci err = 0; 8918c2ecf20Sopenharmony_ci goto out_unlock; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (err) 8958c2ecf20Sopenharmony_ci goto out_unlock; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size)) 8988c2ecf20Sopenharmony_ci goto out_unlock; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci ubi_err(ubi, "PEB %d contains corrupted VID header, and the data does not contain all 0xFF", 9018c2ecf20Sopenharmony_ci pnum); 9028c2ecf20Sopenharmony_ci ubi_err(ubi, "this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection"); 9038c2ecf20Sopenharmony_ci ubi_dump_vid_hdr(vid_hdr); 9048c2ecf20Sopenharmony_ci pr_err("hexdump of PEB %d offset %d, length %d", 9058c2ecf20Sopenharmony_ci pnum, ubi->leb_start, ubi->leb_size); 9068c2ecf20Sopenharmony_ci ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, 9078c2ecf20Sopenharmony_ci ubi->peb_buf, ubi->leb_size, 1); 9088c2ecf20Sopenharmony_ci err = 1; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ciout_unlock: 9118c2ecf20Sopenharmony_ci mutex_unlock(&ubi->buf_mutex); 9128c2ecf20Sopenharmony_ci return err; 9138c2ecf20Sopenharmony_ci} 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_cistatic bool vol_ignored(int vol_id) 9168c2ecf20Sopenharmony_ci{ 9178c2ecf20Sopenharmony_ci switch (vol_id) { 9188c2ecf20Sopenharmony_ci case UBI_LAYOUT_VOLUME_ID: 9198c2ecf20Sopenharmony_ci return true; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 9238c2ecf20Sopenharmony_ci return ubi_is_fm_vol(vol_id); 9248c2ecf20Sopenharmony_ci#else 9258c2ecf20Sopenharmony_ci return false; 9268c2ecf20Sopenharmony_ci#endif 9278c2ecf20Sopenharmony_ci} 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci/** 9308c2ecf20Sopenharmony_ci * scan_peb - scan and process UBI headers of a PEB. 9318c2ecf20Sopenharmony_ci * @ubi: UBI device description object 9328c2ecf20Sopenharmony_ci * @ai: attaching information 9338c2ecf20Sopenharmony_ci * @pnum: the physical eraseblock number 9348c2ecf20Sopenharmony_ci * @fast: true if we're scanning for a Fastmap 9358c2ecf20Sopenharmony_ci * 9368c2ecf20Sopenharmony_ci * This function reads UBI headers of PEB @pnum, checks them, and adds 9378c2ecf20Sopenharmony_ci * information about this PEB to the corresponding list or RB-tree in the 9388c2ecf20Sopenharmony_ci * "attaching info" structure. Returns zero if the physical eraseblock was 9398c2ecf20Sopenharmony_ci * successfully handled and a negative error code in case of failure. 9408c2ecf20Sopenharmony_ci */ 9418c2ecf20Sopenharmony_cistatic int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, 9428c2ecf20Sopenharmony_ci int pnum, bool fast) 9438c2ecf20Sopenharmony_ci{ 9448c2ecf20Sopenharmony_ci struct ubi_ec_hdr *ech = ai->ech; 9458c2ecf20Sopenharmony_ci struct ubi_vid_io_buf *vidb = ai->vidb; 9468c2ecf20Sopenharmony_ci struct ubi_vid_hdr *vidh = ubi_get_vid_hdr(vidb); 9478c2ecf20Sopenharmony_ci long long ec; 9488c2ecf20Sopenharmony_ci int err, bitflips = 0, vol_id = -1, ec_err = 0; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci dbg_bld("scan PEB %d", pnum); 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci /* Skip bad physical eraseblocks */ 9538c2ecf20Sopenharmony_ci err = ubi_io_is_bad(ubi, pnum); 9548c2ecf20Sopenharmony_ci if (err < 0) 9558c2ecf20Sopenharmony_ci return err; 9568c2ecf20Sopenharmony_ci else if (err) { 9578c2ecf20Sopenharmony_ci ai->bad_peb_count += 1; 9588c2ecf20Sopenharmony_ci return 0; 9598c2ecf20Sopenharmony_ci } 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); 9628c2ecf20Sopenharmony_ci if (err < 0) 9638c2ecf20Sopenharmony_ci return err; 9648c2ecf20Sopenharmony_ci switch (err) { 9658c2ecf20Sopenharmony_ci case 0: 9668c2ecf20Sopenharmony_ci break; 9678c2ecf20Sopenharmony_ci case UBI_IO_BITFLIPS: 9688c2ecf20Sopenharmony_ci bitflips = 1; 9698c2ecf20Sopenharmony_ci break; 9708c2ecf20Sopenharmony_ci case UBI_IO_FF: 9718c2ecf20Sopenharmony_ci ai->empty_peb_count += 1; 9728c2ecf20Sopenharmony_ci return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, 9738c2ecf20Sopenharmony_ci UBI_UNKNOWN, 0, &ai->erase); 9748c2ecf20Sopenharmony_ci case UBI_IO_FF_BITFLIPS: 9758c2ecf20Sopenharmony_ci ai->empty_peb_count += 1; 9768c2ecf20Sopenharmony_ci return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, 9778c2ecf20Sopenharmony_ci UBI_UNKNOWN, 1, &ai->erase); 9788c2ecf20Sopenharmony_ci case UBI_IO_BAD_HDR_EBADMSG: 9798c2ecf20Sopenharmony_ci case UBI_IO_BAD_HDR: 9808c2ecf20Sopenharmony_ci /* 9818c2ecf20Sopenharmony_ci * We have to also look at the VID header, possibly it is not 9828c2ecf20Sopenharmony_ci * corrupted. Set %bitflips flag in order to make this PEB be 9838c2ecf20Sopenharmony_ci * moved and EC be re-created. 9848c2ecf20Sopenharmony_ci */ 9858c2ecf20Sopenharmony_ci ec_err = err; 9868c2ecf20Sopenharmony_ci ec = UBI_UNKNOWN; 9878c2ecf20Sopenharmony_ci bitflips = 1; 9888c2ecf20Sopenharmony_ci break; 9898c2ecf20Sopenharmony_ci default: 9908c2ecf20Sopenharmony_ci ubi_err(ubi, "'ubi_io_read_ec_hdr()' returned unknown code %d", 9918c2ecf20Sopenharmony_ci err); 9928c2ecf20Sopenharmony_ci return -EINVAL; 9938c2ecf20Sopenharmony_ci } 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci if (!ec_err) { 9968c2ecf20Sopenharmony_ci int image_seq; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci /* Make sure UBI version is OK */ 9998c2ecf20Sopenharmony_ci if (ech->version != UBI_VERSION) { 10008c2ecf20Sopenharmony_ci ubi_err(ubi, "this UBI version is %d, image version is %d", 10018c2ecf20Sopenharmony_ci UBI_VERSION, (int)ech->version); 10028c2ecf20Sopenharmony_ci return -EINVAL; 10038c2ecf20Sopenharmony_ci } 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci ec = be64_to_cpu(ech->ec); 10068c2ecf20Sopenharmony_ci if (ec > UBI_MAX_ERASECOUNTER) { 10078c2ecf20Sopenharmony_ci /* 10088c2ecf20Sopenharmony_ci * Erase counter overflow. The EC headers have 64 bits 10098c2ecf20Sopenharmony_ci * reserved, but we anyway make use of only 31 bit 10108c2ecf20Sopenharmony_ci * values, as this seems to be enough for any existing 10118c2ecf20Sopenharmony_ci * flash. Upgrade UBI and use 64-bit erase counters 10128c2ecf20Sopenharmony_ci * internally. 10138c2ecf20Sopenharmony_ci */ 10148c2ecf20Sopenharmony_ci ubi_err(ubi, "erase counter overflow, max is %d", 10158c2ecf20Sopenharmony_ci UBI_MAX_ERASECOUNTER); 10168c2ecf20Sopenharmony_ci ubi_dump_ec_hdr(ech); 10178c2ecf20Sopenharmony_ci return -EINVAL; 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci /* 10218c2ecf20Sopenharmony_ci * Make sure that all PEBs have the same image sequence number. 10228c2ecf20Sopenharmony_ci * This allows us to detect situations when users flash UBI 10238c2ecf20Sopenharmony_ci * images incorrectly, so that the flash has the new UBI image 10248c2ecf20Sopenharmony_ci * and leftovers from the old one. This feature was added 10258c2ecf20Sopenharmony_ci * relatively recently, and the sequence number was always 10268c2ecf20Sopenharmony_ci * zero, because old UBI implementations always set it to zero. 10278c2ecf20Sopenharmony_ci * For this reasons, we do not panic if some PEBs have zero 10288c2ecf20Sopenharmony_ci * sequence number, while other PEBs have non-zero sequence 10298c2ecf20Sopenharmony_ci * number. 10308c2ecf20Sopenharmony_ci */ 10318c2ecf20Sopenharmony_ci image_seq = be32_to_cpu(ech->image_seq); 10328c2ecf20Sopenharmony_ci if (!ubi->image_seq) 10338c2ecf20Sopenharmony_ci ubi->image_seq = image_seq; 10348c2ecf20Sopenharmony_ci if (image_seq && ubi->image_seq != image_seq) { 10358c2ecf20Sopenharmony_ci ubi_err(ubi, "bad image sequence number %d in PEB %d, expected %d", 10368c2ecf20Sopenharmony_ci image_seq, pnum, ubi->image_seq); 10378c2ecf20Sopenharmony_ci ubi_dump_ec_hdr(ech); 10388c2ecf20Sopenharmony_ci return -EINVAL; 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci } 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci /* OK, we've done with the EC header, let's look at the VID header */ 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 0); 10458c2ecf20Sopenharmony_ci if (err < 0) 10468c2ecf20Sopenharmony_ci return err; 10478c2ecf20Sopenharmony_ci switch (err) { 10488c2ecf20Sopenharmony_ci case 0: 10498c2ecf20Sopenharmony_ci break; 10508c2ecf20Sopenharmony_ci case UBI_IO_BITFLIPS: 10518c2ecf20Sopenharmony_ci bitflips = 1; 10528c2ecf20Sopenharmony_ci break; 10538c2ecf20Sopenharmony_ci case UBI_IO_BAD_HDR_EBADMSG: 10548c2ecf20Sopenharmony_ci if (ec_err == UBI_IO_BAD_HDR_EBADMSG) 10558c2ecf20Sopenharmony_ci /* 10568c2ecf20Sopenharmony_ci * Both EC and VID headers are corrupted and were read 10578c2ecf20Sopenharmony_ci * with data integrity error, probably this is a bad 10588c2ecf20Sopenharmony_ci * PEB, bit it is not marked as bad yet. This may also 10598c2ecf20Sopenharmony_ci * be a result of power cut during erasure. 10608c2ecf20Sopenharmony_ci */ 10618c2ecf20Sopenharmony_ci ai->maybe_bad_peb_count += 1; 10628c2ecf20Sopenharmony_ci fallthrough; 10638c2ecf20Sopenharmony_ci case UBI_IO_BAD_HDR: 10648c2ecf20Sopenharmony_ci /* 10658c2ecf20Sopenharmony_ci * If we're facing a bad VID header we have to drop *all* 10668c2ecf20Sopenharmony_ci * Fastmap data structures we find. The most recent Fastmap 10678c2ecf20Sopenharmony_ci * could be bad and therefore there is a chance that we attach 10688c2ecf20Sopenharmony_ci * from an old one. On a fine MTD stack a PEB must not render 10698c2ecf20Sopenharmony_ci * bad all of a sudden, but the reality is different. 10708c2ecf20Sopenharmony_ci * So, let's be paranoid and help finding the root cause by 10718c2ecf20Sopenharmony_ci * falling back to scanning mode instead of attaching with a 10728c2ecf20Sopenharmony_ci * bad EBA table and cause data corruption which is hard to 10738c2ecf20Sopenharmony_ci * analyze. 10748c2ecf20Sopenharmony_ci */ 10758c2ecf20Sopenharmony_ci if (fast) 10768c2ecf20Sopenharmony_ci ai->force_full_scan = 1; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci if (ec_err) 10798c2ecf20Sopenharmony_ci /* 10808c2ecf20Sopenharmony_ci * Both headers are corrupted. There is a possibility 10818c2ecf20Sopenharmony_ci * that this a valid UBI PEB which has corresponding 10828c2ecf20Sopenharmony_ci * LEB, but the headers are corrupted. However, it is 10838c2ecf20Sopenharmony_ci * impossible to distinguish it from a PEB which just 10848c2ecf20Sopenharmony_ci * contains garbage because of a power cut during erase 10858c2ecf20Sopenharmony_ci * operation. So we just schedule this PEB for erasure. 10868c2ecf20Sopenharmony_ci * 10878c2ecf20Sopenharmony_ci * Besides, in case of NOR flash, we deliberately 10888c2ecf20Sopenharmony_ci * corrupt both headers because NOR flash erasure is 10898c2ecf20Sopenharmony_ci * slow and can start from the end. 10908c2ecf20Sopenharmony_ci */ 10918c2ecf20Sopenharmony_ci err = 0; 10928c2ecf20Sopenharmony_ci else 10938c2ecf20Sopenharmony_ci /* 10948c2ecf20Sopenharmony_ci * The EC was OK, but the VID header is corrupted. We 10958c2ecf20Sopenharmony_ci * have to check what is in the data area. 10968c2ecf20Sopenharmony_ci */ 10978c2ecf20Sopenharmony_ci err = check_corruption(ubi, vidh, pnum); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci if (err < 0) 11008c2ecf20Sopenharmony_ci return err; 11018c2ecf20Sopenharmony_ci else if (!err) 11028c2ecf20Sopenharmony_ci /* This corruption is caused by a power cut */ 11038c2ecf20Sopenharmony_ci err = add_to_list(ai, pnum, UBI_UNKNOWN, 11048c2ecf20Sopenharmony_ci UBI_UNKNOWN, ec, 1, &ai->erase); 11058c2ecf20Sopenharmony_ci else 11068c2ecf20Sopenharmony_ci /* This is an unexpected corruption */ 11078c2ecf20Sopenharmony_ci err = add_corrupted(ai, pnum, ec); 11088c2ecf20Sopenharmony_ci if (err) 11098c2ecf20Sopenharmony_ci return err; 11108c2ecf20Sopenharmony_ci goto adjust_mean_ec; 11118c2ecf20Sopenharmony_ci case UBI_IO_FF_BITFLIPS: 11128c2ecf20Sopenharmony_ci err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, 11138c2ecf20Sopenharmony_ci ec, 1, &ai->erase); 11148c2ecf20Sopenharmony_ci if (err) 11158c2ecf20Sopenharmony_ci return err; 11168c2ecf20Sopenharmony_ci goto adjust_mean_ec; 11178c2ecf20Sopenharmony_ci case UBI_IO_FF: 11188c2ecf20Sopenharmony_ci if (ec_err || bitflips) 11198c2ecf20Sopenharmony_ci err = add_to_list(ai, pnum, UBI_UNKNOWN, 11208c2ecf20Sopenharmony_ci UBI_UNKNOWN, ec, 1, &ai->erase); 11218c2ecf20Sopenharmony_ci else 11228c2ecf20Sopenharmony_ci err = add_to_list(ai, pnum, UBI_UNKNOWN, 11238c2ecf20Sopenharmony_ci UBI_UNKNOWN, ec, 0, &ai->free); 11248c2ecf20Sopenharmony_ci if (err) 11258c2ecf20Sopenharmony_ci return err; 11268c2ecf20Sopenharmony_ci goto adjust_mean_ec; 11278c2ecf20Sopenharmony_ci default: 11288c2ecf20Sopenharmony_ci ubi_err(ubi, "'ubi_io_read_vid_hdr()' returned unknown code %d", 11298c2ecf20Sopenharmony_ci err); 11308c2ecf20Sopenharmony_ci return -EINVAL; 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci vol_id = be32_to_cpu(vidh->vol_id); 11348c2ecf20Sopenharmony_ci if (vol_id > UBI_MAX_VOLUMES && !vol_ignored(vol_id)) { 11358c2ecf20Sopenharmony_ci int lnum = be32_to_cpu(vidh->lnum); 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci /* Unsupported internal volume */ 11388c2ecf20Sopenharmony_ci switch (vidh->compat) { 11398c2ecf20Sopenharmony_ci case UBI_COMPAT_DELETE: 11408c2ecf20Sopenharmony_ci ubi_msg(ubi, "\"delete\" compatible internal volume %d:%d found, will remove it", 11418c2ecf20Sopenharmony_ci vol_id, lnum); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci err = add_to_list(ai, pnum, vol_id, lnum, 11448c2ecf20Sopenharmony_ci ec, 1, &ai->erase); 11458c2ecf20Sopenharmony_ci if (err) 11468c2ecf20Sopenharmony_ci return err; 11478c2ecf20Sopenharmony_ci return 0; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci case UBI_COMPAT_RO: 11508c2ecf20Sopenharmony_ci ubi_msg(ubi, "read-only compatible internal volume %d:%d found, switch to read-only mode", 11518c2ecf20Sopenharmony_ci vol_id, lnum); 11528c2ecf20Sopenharmony_ci ubi->ro_mode = 1; 11538c2ecf20Sopenharmony_ci break; 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci case UBI_COMPAT_PRESERVE: 11568c2ecf20Sopenharmony_ci ubi_msg(ubi, "\"preserve\" compatible internal volume %d:%d found", 11578c2ecf20Sopenharmony_ci vol_id, lnum); 11588c2ecf20Sopenharmony_ci err = add_to_list(ai, pnum, vol_id, lnum, 11598c2ecf20Sopenharmony_ci ec, 0, &ai->alien); 11608c2ecf20Sopenharmony_ci if (err) 11618c2ecf20Sopenharmony_ci return err; 11628c2ecf20Sopenharmony_ci return 0; 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci case UBI_COMPAT_REJECT: 11658c2ecf20Sopenharmony_ci ubi_err(ubi, "incompatible internal volume %d:%d found", 11668c2ecf20Sopenharmony_ci vol_id, lnum); 11678c2ecf20Sopenharmony_ci return -EINVAL; 11688c2ecf20Sopenharmony_ci } 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci if (ec_err) 11728c2ecf20Sopenharmony_ci ubi_warn(ubi, "valid VID header but corrupted EC header at PEB %d", 11738c2ecf20Sopenharmony_ci pnum); 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci if (ubi_is_fm_vol(vol_id)) 11768c2ecf20Sopenharmony_ci err = add_fastmap(ai, pnum, vidh, ec); 11778c2ecf20Sopenharmony_ci else 11788c2ecf20Sopenharmony_ci err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips); 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci if (err) 11818c2ecf20Sopenharmony_ci return err; 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ciadjust_mean_ec: 11848c2ecf20Sopenharmony_ci if (!ec_err) { 11858c2ecf20Sopenharmony_ci ai->ec_sum += ec; 11868c2ecf20Sopenharmony_ci ai->ec_count += 1; 11878c2ecf20Sopenharmony_ci if (ec > ai->max_ec) 11888c2ecf20Sopenharmony_ci ai->max_ec = ec; 11898c2ecf20Sopenharmony_ci if (ec < ai->min_ec) 11908c2ecf20Sopenharmony_ci ai->min_ec = ec; 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci return 0; 11948c2ecf20Sopenharmony_ci} 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci/** 11978c2ecf20Sopenharmony_ci * late_analysis - analyze the overall situation with PEB. 11988c2ecf20Sopenharmony_ci * @ubi: UBI device description object 11998c2ecf20Sopenharmony_ci * @ai: attaching information 12008c2ecf20Sopenharmony_ci * 12018c2ecf20Sopenharmony_ci * This is a helper function which takes a look what PEBs we have after we 12028c2ecf20Sopenharmony_ci * gather information about all of them ("ai" is compete). It decides whether 12038c2ecf20Sopenharmony_ci * the flash is empty and should be formatted of whether there are too many 12048c2ecf20Sopenharmony_ci * corrupted PEBs and we should not attach this MTD device. Returns zero if we 12058c2ecf20Sopenharmony_ci * should proceed with attaching the MTD device, and %-EINVAL if we should not. 12068c2ecf20Sopenharmony_ci */ 12078c2ecf20Sopenharmony_cistatic int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai) 12088c2ecf20Sopenharmony_ci{ 12098c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 12108c2ecf20Sopenharmony_ci int max_corr, peb_count; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci peb_count = ubi->peb_count - ai->bad_peb_count - ai->alien_peb_count; 12138c2ecf20Sopenharmony_ci max_corr = peb_count / 20 ?: 8; 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci /* 12168c2ecf20Sopenharmony_ci * Few corrupted PEBs is not a problem and may be just a result of 12178c2ecf20Sopenharmony_ci * unclean reboots. However, many of them may indicate some problems 12188c2ecf20Sopenharmony_ci * with the flash HW or driver. 12198c2ecf20Sopenharmony_ci */ 12208c2ecf20Sopenharmony_ci if (ai->corr_peb_count) { 12218c2ecf20Sopenharmony_ci ubi_err(ubi, "%d PEBs are corrupted and preserved", 12228c2ecf20Sopenharmony_ci ai->corr_peb_count); 12238c2ecf20Sopenharmony_ci pr_err("Corrupted PEBs are:"); 12248c2ecf20Sopenharmony_ci list_for_each_entry(aeb, &ai->corr, u.list) 12258c2ecf20Sopenharmony_ci pr_cont(" %d", aeb->pnum); 12268c2ecf20Sopenharmony_ci pr_cont("\n"); 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci /* 12298c2ecf20Sopenharmony_ci * If too many PEBs are corrupted, we refuse attaching, 12308c2ecf20Sopenharmony_ci * otherwise, only print a warning. 12318c2ecf20Sopenharmony_ci */ 12328c2ecf20Sopenharmony_ci if (ai->corr_peb_count >= max_corr) { 12338c2ecf20Sopenharmony_ci ubi_err(ubi, "too many corrupted PEBs, refusing"); 12348c2ecf20Sopenharmony_ci return -EINVAL; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci if (ai->empty_peb_count + ai->maybe_bad_peb_count == peb_count) { 12398c2ecf20Sopenharmony_ci /* 12408c2ecf20Sopenharmony_ci * All PEBs are empty, or almost all - a couple PEBs look like 12418c2ecf20Sopenharmony_ci * they may be bad PEBs which were not marked as bad yet. 12428c2ecf20Sopenharmony_ci * 12438c2ecf20Sopenharmony_ci * This piece of code basically tries to distinguish between 12448c2ecf20Sopenharmony_ci * the following situations: 12458c2ecf20Sopenharmony_ci * 12468c2ecf20Sopenharmony_ci * 1. Flash is empty, but there are few bad PEBs, which are not 12478c2ecf20Sopenharmony_ci * marked as bad so far, and which were read with error. We 12488c2ecf20Sopenharmony_ci * want to go ahead and format this flash. While formatting, 12498c2ecf20Sopenharmony_ci * the faulty PEBs will probably be marked as bad. 12508c2ecf20Sopenharmony_ci * 12518c2ecf20Sopenharmony_ci * 2. Flash contains non-UBI data and we do not want to format 12528c2ecf20Sopenharmony_ci * it and destroy possibly important information. 12538c2ecf20Sopenharmony_ci */ 12548c2ecf20Sopenharmony_ci if (ai->maybe_bad_peb_count <= 2) { 12558c2ecf20Sopenharmony_ci ai->is_empty = 1; 12568c2ecf20Sopenharmony_ci ubi_msg(ubi, "empty MTD device detected"); 12578c2ecf20Sopenharmony_ci get_random_bytes(&ubi->image_seq, 12588c2ecf20Sopenharmony_ci sizeof(ubi->image_seq)); 12598c2ecf20Sopenharmony_ci } else { 12608c2ecf20Sopenharmony_ci ubi_err(ubi, "MTD device is not UBI-formatted and possibly contains non-UBI data - refusing it"); 12618c2ecf20Sopenharmony_ci return -EINVAL; 12628c2ecf20Sopenharmony_ci } 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci } 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci return 0; 12678c2ecf20Sopenharmony_ci} 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci/** 12708c2ecf20Sopenharmony_ci * destroy_av - free volume attaching information. 12718c2ecf20Sopenharmony_ci * @av: volume attaching information 12728c2ecf20Sopenharmony_ci * @ai: attaching information 12738c2ecf20Sopenharmony_ci * @list: put the aeb elements in there if !NULL, otherwise free them 12748c2ecf20Sopenharmony_ci * 12758c2ecf20Sopenharmony_ci * This function destroys the volume attaching information. 12768c2ecf20Sopenharmony_ci */ 12778c2ecf20Sopenharmony_cistatic void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av, 12788c2ecf20Sopenharmony_ci struct list_head *list) 12798c2ecf20Sopenharmony_ci{ 12808c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 12818c2ecf20Sopenharmony_ci struct rb_node *this = av->root.rb_node; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci while (this) { 12848c2ecf20Sopenharmony_ci if (this->rb_left) 12858c2ecf20Sopenharmony_ci this = this->rb_left; 12868c2ecf20Sopenharmony_ci else if (this->rb_right) 12878c2ecf20Sopenharmony_ci this = this->rb_right; 12888c2ecf20Sopenharmony_ci else { 12898c2ecf20Sopenharmony_ci aeb = rb_entry(this, struct ubi_ainf_peb, u.rb); 12908c2ecf20Sopenharmony_ci this = rb_parent(this); 12918c2ecf20Sopenharmony_ci if (this) { 12928c2ecf20Sopenharmony_ci if (this->rb_left == &aeb->u.rb) 12938c2ecf20Sopenharmony_ci this->rb_left = NULL; 12948c2ecf20Sopenharmony_ci else 12958c2ecf20Sopenharmony_ci this->rb_right = NULL; 12968c2ecf20Sopenharmony_ci } 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci if (list) 12998c2ecf20Sopenharmony_ci list_add_tail(&aeb->u.list, list); 13008c2ecf20Sopenharmony_ci else 13018c2ecf20Sopenharmony_ci ubi_free_aeb(ai, aeb); 13028c2ecf20Sopenharmony_ci } 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci kfree(av); 13058c2ecf20Sopenharmony_ci} 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci/** 13088c2ecf20Sopenharmony_ci * destroy_ai - destroy attaching information. 13098c2ecf20Sopenharmony_ci * @ai: attaching information 13108c2ecf20Sopenharmony_ci */ 13118c2ecf20Sopenharmony_cistatic void destroy_ai(struct ubi_attach_info *ai) 13128c2ecf20Sopenharmony_ci{ 13138c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb, *aeb_tmp; 13148c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 13158c2ecf20Sopenharmony_ci struct rb_node *rb; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci list_for_each_entry_safe(aeb, aeb_tmp, &ai->alien, u.list) { 13188c2ecf20Sopenharmony_ci list_del(&aeb->u.list); 13198c2ecf20Sopenharmony_ci ubi_free_aeb(ai, aeb); 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci list_for_each_entry_safe(aeb, aeb_tmp, &ai->erase, u.list) { 13228c2ecf20Sopenharmony_ci list_del(&aeb->u.list); 13238c2ecf20Sopenharmony_ci ubi_free_aeb(ai, aeb); 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci list_for_each_entry_safe(aeb, aeb_tmp, &ai->corr, u.list) { 13268c2ecf20Sopenharmony_ci list_del(&aeb->u.list); 13278c2ecf20Sopenharmony_ci ubi_free_aeb(ai, aeb); 13288c2ecf20Sopenharmony_ci } 13298c2ecf20Sopenharmony_ci list_for_each_entry_safe(aeb, aeb_tmp, &ai->free, u.list) { 13308c2ecf20Sopenharmony_ci list_del(&aeb->u.list); 13318c2ecf20Sopenharmony_ci ubi_free_aeb(ai, aeb); 13328c2ecf20Sopenharmony_ci } 13338c2ecf20Sopenharmony_ci list_for_each_entry_safe(aeb, aeb_tmp, &ai->fastmap, u.list) { 13348c2ecf20Sopenharmony_ci list_del(&aeb->u.list); 13358c2ecf20Sopenharmony_ci ubi_free_aeb(ai, aeb); 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci /* Destroy the volume RB-tree */ 13398c2ecf20Sopenharmony_ci rb = ai->volumes.rb_node; 13408c2ecf20Sopenharmony_ci while (rb) { 13418c2ecf20Sopenharmony_ci if (rb->rb_left) 13428c2ecf20Sopenharmony_ci rb = rb->rb_left; 13438c2ecf20Sopenharmony_ci else if (rb->rb_right) 13448c2ecf20Sopenharmony_ci rb = rb->rb_right; 13458c2ecf20Sopenharmony_ci else { 13468c2ecf20Sopenharmony_ci av = rb_entry(rb, struct ubi_ainf_volume, rb); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci rb = rb_parent(rb); 13498c2ecf20Sopenharmony_ci if (rb) { 13508c2ecf20Sopenharmony_ci if (rb->rb_left == &av->rb) 13518c2ecf20Sopenharmony_ci rb->rb_left = NULL; 13528c2ecf20Sopenharmony_ci else 13538c2ecf20Sopenharmony_ci rb->rb_right = NULL; 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci destroy_av(ai, av, NULL); 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci } 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci kmem_cache_destroy(ai->aeb_slab_cache); 13618c2ecf20Sopenharmony_ci kfree(ai); 13628c2ecf20Sopenharmony_ci} 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci/** 13658c2ecf20Sopenharmony_ci * scan_all - scan entire MTD device. 13668c2ecf20Sopenharmony_ci * @ubi: UBI device description object 13678c2ecf20Sopenharmony_ci * @ai: attach info object 13688c2ecf20Sopenharmony_ci * @start: start scanning at this PEB 13698c2ecf20Sopenharmony_ci * 13708c2ecf20Sopenharmony_ci * This function does full scanning of an MTD device and returns complete 13718c2ecf20Sopenharmony_ci * information about it in form of a "struct ubi_attach_info" object. In case 13728c2ecf20Sopenharmony_ci * of failure, an error code is returned. 13738c2ecf20Sopenharmony_ci */ 13748c2ecf20Sopenharmony_cistatic int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai, 13758c2ecf20Sopenharmony_ci int start) 13768c2ecf20Sopenharmony_ci{ 13778c2ecf20Sopenharmony_ci int err, pnum; 13788c2ecf20Sopenharmony_ci struct rb_node *rb1, *rb2; 13798c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 13808c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci err = -ENOMEM; 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci ai->ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); 13858c2ecf20Sopenharmony_ci if (!ai->ech) 13868c2ecf20Sopenharmony_ci return err; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci ai->vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL); 13898c2ecf20Sopenharmony_ci if (!ai->vidb) 13908c2ecf20Sopenharmony_ci goto out_ech; 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci for (pnum = start; pnum < ubi->peb_count; pnum++) { 13938c2ecf20Sopenharmony_ci cond_resched(); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci dbg_gen("process PEB %d", pnum); 13968c2ecf20Sopenharmony_ci err = scan_peb(ubi, ai, pnum, false); 13978c2ecf20Sopenharmony_ci if (err < 0) 13988c2ecf20Sopenharmony_ci goto out_vidh; 13998c2ecf20Sopenharmony_ci } 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci ubi_msg(ubi, "scanning is finished"); 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci /* Calculate mean erase counter */ 14048c2ecf20Sopenharmony_ci if (ai->ec_count) 14058c2ecf20Sopenharmony_ci ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count); 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci err = late_analysis(ubi, ai); 14088c2ecf20Sopenharmony_ci if (err) 14098c2ecf20Sopenharmony_ci goto out_vidh; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci /* 14128c2ecf20Sopenharmony_ci * In case of unknown erase counter we use the mean erase counter 14138c2ecf20Sopenharmony_ci * value. 14148c2ecf20Sopenharmony_ci */ 14158c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { 14168c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) 14178c2ecf20Sopenharmony_ci if (aeb->ec == UBI_UNKNOWN) 14188c2ecf20Sopenharmony_ci aeb->ec = ai->mean_ec; 14198c2ecf20Sopenharmony_ci } 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci list_for_each_entry(aeb, &ai->free, u.list) { 14228c2ecf20Sopenharmony_ci if (aeb->ec == UBI_UNKNOWN) 14238c2ecf20Sopenharmony_ci aeb->ec = ai->mean_ec; 14248c2ecf20Sopenharmony_ci } 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci list_for_each_entry(aeb, &ai->corr, u.list) 14278c2ecf20Sopenharmony_ci if (aeb->ec == UBI_UNKNOWN) 14288c2ecf20Sopenharmony_ci aeb->ec = ai->mean_ec; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci list_for_each_entry(aeb, &ai->erase, u.list) 14318c2ecf20Sopenharmony_ci if (aeb->ec == UBI_UNKNOWN) 14328c2ecf20Sopenharmony_ci aeb->ec = ai->mean_ec; 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci err = self_check_ai(ubi, ai); 14358c2ecf20Sopenharmony_ci if (err) 14368c2ecf20Sopenharmony_ci goto out_vidh; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci ubi_free_vid_buf(ai->vidb); 14398c2ecf20Sopenharmony_ci kfree(ai->ech); 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci return 0; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ciout_vidh: 14448c2ecf20Sopenharmony_ci ubi_free_vid_buf(ai->vidb); 14458c2ecf20Sopenharmony_ciout_ech: 14468c2ecf20Sopenharmony_ci kfree(ai->ech); 14478c2ecf20Sopenharmony_ci return err; 14488c2ecf20Sopenharmony_ci} 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_cistatic struct ubi_attach_info *alloc_ai(void) 14518c2ecf20Sopenharmony_ci{ 14528c2ecf20Sopenharmony_ci struct ubi_attach_info *ai; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL); 14558c2ecf20Sopenharmony_ci if (!ai) 14568c2ecf20Sopenharmony_ci return ai; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ai->corr); 14598c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ai->free); 14608c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ai->erase); 14618c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ai->alien); 14628c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ai->fastmap); 14638c2ecf20Sopenharmony_ci ai->volumes = RB_ROOT; 14648c2ecf20Sopenharmony_ci ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache", 14658c2ecf20Sopenharmony_ci sizeof(struct ubi_ainf_peb), 14668c2ecf20Sopenharmony_ci 0, 0, NULL); 14678c2ecf20Sopenharmony_ci if (!ai->aeb_slab_cache) { 14688c2ecf20Sopenharmony_ci kfree(ai); 14698c2ecf20Sopenharmony_ci ai = NULL; 14708c2ecf20Sopenharmony_ci } 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci return ai; 14738c2ecf20Sopenharmony_ci} 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci/** 14788c2ecf20Sopenharmony_ci * scan_fast - try to find a fastmap and attach from it. 14798c2ecf20Sopenharmony_ci * @ubi: UBI device description object 14808c2ecf20Sopenharmony_ci * @ai: attach info object 14818c2ecf20Sopenharmony_ci * 14828c2ecf20Sopenharmony_ci * Returns 0 on success, negative return values indicate an internal 14838c2ecf20Sopenharmony_ci * error. 14848c2ecf20Sopenharmony_ci * UBI_NO_FASTMAP denotes that no fastmap was found. 14858c2ecf20Sopenharmony_ci * UBI_BAD_FASTMAP denotes that the found fastmap was invalid. 14868c2ecf20Sopenharmony_ci */ 14878c2ecf20Sopenharmony_cistatic int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai) 14888c2ecf20Sopenharmony_ci{ 14898c2ecf20Sopenharmony_ci int err, pnum; 14908c2ecf20Sopenharmony_ci struct ubi_attach_info *scan_ai; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci err = -ENOMEM; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci scan_ai = alloc_ai(); 14958c2ecf20Sopenharmony_ci if (!scan_ai) 14968c2ecf20Sopenharmony_ci goto out; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci scan_ai->ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); 14998c2ecf20Sopenharmony_ci if (!scan_ai->ech) 15008c2ecf20Sopenharmony_ci goto out_ai; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci scan_ai->vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL); 15038c2ecf20Sopenharmony_ci if (!scan_ai->vidb) 15048c2ecf20Sopenharmony_ci goto out_ech; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) { 15078c2ecf20Sopenharmony_ci cond_resched(); 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci dbg_gen("process PEB %d", pnum); 15108c2ecf20Sopenharmony_ci err = scan_peb(ubi, scan_ai, pnum, true); 15118c2ecf20Sopenharmony_ci if (err < 0) 15128c2ecf20Sopenharmony_ci goto out_vidh; 15138c2ecf20Sopenharmony_ci } 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci ubi_free_vid_buf(scan_ai->vidb); 15168c2ecf20Sopenharmony_ci kfree(scan_ai->ech); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci if (scan_ai->force_full_scan) 15198c2ecf20Sopenharmony_ci err = UBI_NO_FASTMAP; 15208c2ecf20Sopenharmony_ci else 15218c2ecf20Sopenharmony_ci err = ubi_scan_fastmap(ubi, *ai, scan_ai); 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci if (err) { 15248c2ecf20Sopenharmony_ci /* 15258c2ecf20Sopenharmony_ci * Didn't attach via fastmap, do a full scan but reuse what 15268c2ecf20Sopenharmony_ci * we've aready scanned. 15278c2ecf20Sopenharmony_ci */ 15288c2ecf20Sopenharmony_ci destroy_ai(*ai); 15298c2ecf20Sopenharmony_ci *ai = scan_ai; 15308c2ecf20Sopenharmony_ci } else 15318c2ecf20Sopenharmony_ci destroy_ai(scan_ai); 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci return err; 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ciout_vidh: 15368c2ecf20Sopenharmony_ci ubi_free_vid_buf(scan_ai->vidb); 15378c2ecf20Sopenharmony_ciout_ech: 15388c2ecf20Sopenharmony_ci kfree(scan_ai->ech); 15398c2ecf20Sopenharmony_ciout_ai: 15408c2ecf20Sopenharmony_ci destroy_ai(scan_ai); 15418c2ecf20Sopenharmony_ciout: 15428c2ecf20Sopenharmony_ci return err; 15438c2ecf20Sopenharmony_ci} 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci#endif 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci/** 15488c2ecf20Sopenharmony_ci * ubi_attach - attach an MTD device. 15498c2ecf20Sopenharmony_ci * @ubi: UBI device descriptor 15508c2ecf20Sopenharmony_ci * @force_scan: if set to non-zero attach by scanning 15518c2ecf20Sopenharmony_ci * 15528c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in 15538c2ecf20Sopenharmony_ci * case of failure. 15548c2ecf20Sopenharmony_ci */ 15558c2ecf20Sopenharmony_ciint ubi_attach(struct ubi_device *ubi, int force_scan) 15568c2ecf20Sopenharmony_ci{ 15578c2ecf20Sopenharmony_ci int err; 15588c2ecf20Sopenharmony_ci struct ubi_attach_info *ai; 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci ai = alloc_ai(); 15618c2ecf20Sopenharmony_ci if (!ai) 15628c2ecf20Sopenharmony_ci return -ENOMEM; 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 15658c2ecf20Sopenharmony_ci /* On small flash devices we disable fastmap in any case. */ 15668c2ecf20Sopenharmony_ci if ((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) { 15678c2ecf20Sopenharmony_ci ubi->fm_disabled = 1; 15688c2ecf20Sopenharmony_ci force_scan = 1; 15698c2ecf20Sopenharmony_ci } 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci if (force_scan) 15728c2ecf20Sopenharmony_ci err = scan_all(ubi, ai, 0); 15738c2ecf20Sopenharmony_ci else { 15748c2ecf20Sopenharmony_ci err = scan_fast(ubi, &ai); 15758c2ecf20Sopenharmony_ci if (err > 0 || mtd_is_eccerr(err)) { 15768c2ecf20Sopenharmony_ci if (err != UBI_NO_FASTMAP) { 15778c2ecf20Sopenharmony_ci destroy_ai(ai); 15788c2ecf20Sopenharmony_ci ai = alloc_ai(); 15798c2ecf20Sopenharmony_ci if (!ai) 15808c2ecf20Sopenharmony_ci return -ENOMEM; 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci err = scan_all(ubi, ai, 0); 15838c2ecf20Sopenharmony_ci } else { 15848c2ecf20Sopenharmony_ci err = scan_all(ubi, ai, UBI_FM_MAX_START); 15858c2ecf20Sopenharmony_ci } 15868c2ecf20Sopenharmony_ci } 15878c2ecf20Sopenharmony_ci } 15888c2ecf20Sopenharmony_ci#else 15898c2ecf20Sopenharmony_ci err = scan_all(ubi, ai, 0); 15908c2ecf20Sopenharmony_ci#endif 15918c2ecf20Sopenharmony_ci if (err) 15928c2ecf20Sopenharmony_ci goto out_ai; 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci ubi->bad_peb_count = ai->bad_peb_count; 15958c2ecf20Sopenharmony_ci ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count; 15968c2ecf20Sopenharmony_ci ubi->corr_peb_count = ai->corr_peb_count; 15978c2ecf20Sopenharmony_ci ubi->max_ec = ai->max_ec; 15988c2ecf20Sopenharmony_ci ubi->mean_ec = ai->mean_ec; 15998c2ecf20Sopenharmony_ci dbg_gen("max. sequence number: %llu", ai->max_sqnum); 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci err = ubi_read_volume_table(ubi, ai); 16028c2ecf20Sopenharmony_ci if (err) 16038c2ecf20Sopenharmony_ci goto out_ai; 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci err = ubi_wl_init(ubi, ai); 16068c2ecf20Sopenharmony_ci if (err) 16078c2ecf20Sopenharmony_ci goto out_vtbl; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci err = ubi_eba_init(ubi, ai); 16108c2ecf20Sopenharmony_ci if (err) 16118c2ecf20Sopenharmony_ci goto out_wl; 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 16148c2ecf20Sopenharmony_ci if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) { 16158c2ecf20Sopenharmony_ci struct ubi_attach_info *scan_ai; 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci scan_ai = alloc_ai(); 16188c2ecf20Sopenharmony_ci if (!scan_ai) { 16198c2ecf20Sopenharmony_ci err = -ENOMEM; 16208c2ecf20Sopenharmony_ci goto out_wl; 16218c2ecf20Sopenharmony_ci } 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci err = scan_all(ubi, scan_ai, 0); 16248c2ecf20Sopenharmony_ci if (err) { 16258c2ecf20Sopenharmony_ci destroy_ai(scan_ai); 16268c2ecf20Sopenharmony_ci goto out_wl; 16278c2ecf20Sopenharmony_ci } 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci err = self_check_eba(ubi, ai, scan_ai); 16308c2ecf20Sopenharmony_ci destroy_ai(scan_ai); 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci if (err) 16338c2ecf20Sopenharmony_ci goto out_wl; 16348c2ecf20Sopenharmony_ci } 16358c2ecf20Sopenharmony_ci#endif 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci destroy_ai(ai); 16388c2ecf20Sopenharmony_ci return 0; 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ciout_wl: 16418c2ecf20Sopenharmony_ci ubi_wl_close(ubi); 16428c2ecf20Sopenharmony_ciout_vtbl: 16438c2ecf20Sopenharmony_ci ubi_free_all_volumes(ubi); 16448c2ecf20Sopenharmony_ci vfree(ubi->vtbl); 16458c2ecf20Sopenharmony_ciout_ai: 16468c2ecf20Sopenharmony_ci destroy_ai(ai); 16478c2ecf20Sopenharmony_ci return err; 16488c2ecf20Sopenharmony_ci} 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci/** 16518c2ecf20Sopenharmony_ci * self_check_ai - check the attaching information. 16528c2ecf20Sopenharmony_ci * @ubi: UBI device description object 16538c2ecf20Sopenharmony_ci * @ai: attaching information 16548c2ecf20Sopenharmony_ci * 16558c2ecf20Sopenharmony_ci * This function returns zero if the attaching information is all right, and a 16568c2ecf20Sopenharmony_ci * negative error code if not or if an error occurred. 16578c2ecf20Sopenharmony_ci */ 16588c2ecf20Sopenharmony_cistatic int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai) 16598c2ecf20Sopenharmony_ci{ 16608c2ecf20Sopenharmony_ci struct ubi_vid_io_buf *vidb = ai->vidb; 16618c2ecf20Sopenharmony_ci struct ubi_vid_hdr *vidh = ubi_get_vid_hdr(vidb); 16628c2ecf20Sopenharmony_ci int pnum, err, vols_found = 0; 16638c2ecf20Sopenharmony_ci struct rb_node *rb1, *rb2; 16648c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 16658c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb, *last_aeb; 16668c2ecf20Sopenharmony_ci uint8_t *buf; 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci if (!ubi_dbg_chk_gen(ubi)) 16698c2ecf20Sopenharmony_ci return 0; 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci /* 16728c2ecf20Sopenharmony_ci * At first, check that attaching information is OK. 16738c2ecf20Sopenharmony_ci */ 16748c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { 16758c2ecf20Sopenharmony_ci int leb_count = 0; 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci cond_resched(); 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci vols_found += 1; 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci if (ai->is_empty) { 16828c2ecf20Sopenharmony_ci ubi_err(ubi, "bad is_empty flag"); 16838c2ecf20Sopenharmony_ci goto bad_av; 16848c2ecf20Sopenharmony_ci } 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci if (av->vol_id < 0 || av->highest_lnum < 0 || 16878c2ecf20Sopenharmony_ci av->leb_count < 0 || av->vol_type < 0 || av->used_ebs < 0 || 16888c2ecf20Sopenharmony_ci av->data_pad < 0 || av->last_data_size < 0) { 16898c2ecf20Sopenharmony_ci ubi_err(ubi, "negative values"); 16908c2ecf20Sopenharmony_ci goto bad_av; 16918c2ecf20Sopenharmony_ci } 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci if (av->vol_id >= UBI_MAX_VOLUMES && 16948c2ecf20Sopenharmony_ci av->vol_id < UBI_INTERNAL_VOL_START) { 16958c2ecf20Sopenharmony_ci ubi_err(ubi, "bad vol_id"); 16968c2ecf20Sopenharmony_ci goto bad_av; 16978c2ecf20Sopenharmony_ci } 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci if (av->vol_id > ai->highest_vol_id) { 17008c2ecf20Sopenharmony_ci ubi_err(ubi, "highest_vol_id is %d, but vol_id %d is there", 17018c2ecf20Sopenharmony_ci ai->highest_vol_id, av->vol_id); 17028c2ecf20Sopenharmony_ci goto out; 17038c2ecf20Sopenharmony_ci } 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci if (av->vol_type != UBI_DYNAMIC_VOLUME && 17068c2ecf20Sopenharmony_ci av->vol_type != UBI_STATIC_VOLUME) { 17078c2ecf20Sopenharmony_ci ubi_err(ubi, "bad vol_type"); 17088c2ecf20Sopenharmony_ci goto bad_av; 17098c2ecf20Sopenharmony_ci } 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci if (av->data_pad > ubi->leb_size / 2) { 17128c2ecf20Sopenharmony_ci ubi_err(ubi, "bad data_pad"); 17138c2ecf20Sopenharmony_ci goto bad_av; 17148c2ecf20Sopenharmony_ci } 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci last_aeb = NULL; 17178c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) { 17188c2ecf20Sopenharmony_ci cond_resched(); 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci last_aeb = aeb; 17218c2ecf20Sopenharmony_ci leb_count += 1; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci if (aeb->pnum < 0 || aeb->ec < 0) { 17248c2ecf20Sopenharmony_ci ubi_err(ubi, "negative values"); 17258c2ecf20Sopenharmony_ci goto bad_aeb; 17268c2ecf20Sopenharmony_ci } 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci if (aeb->ec < ai->min_ec) { 17298c2ecf20Sopenharmony_ci ubi_err(ubi, "bad ai->min_ec (%d), %d found", 17308c2ecf20Sopenharmony_ci ai->min_ec, aeb->ec); 17318c2ecf20Sopenharmony_ci goto bad_aeb; 17328c2ecf20Sopenharmony_ci } 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci if (aeb->ec > ai->max_ec) { 17358c2ecf20Sopenharmony_ci ubi_err(ubi, "bad ai->max_ec (%d), %d found", 17368c2ecf20Sopenharmony_ci ai->max_ec, aeb->ec); 17378c2ecf20Sopenharmony_ci goto bad_aeb; 17388c2ecf20Sopenharmony_ci } 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci if (aeb->pnum >= ubi->peb_count) { 17418c2ecf20Sopenharmony_ci ubi_err(ubi, "too high PEB number %d, total PEBs %d", 17428c2ecf20Sopenharmony_ci aeb->pnum, ubi->peb_count); 17438c2ecf20Sopenharmony_ci goto bad_aeb; 17448c2ecf20Sopenharmony_ci } 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci if (av->vol_type == UBI_STATIC_VOLUME) { 17478c2ecf20Sopenharmony_ci if (aeb->lnum >= av->used_ebs) { 17488c2ecf20Sopenharmony_ci ubi_err(ubi, "bad lnum or used_ebs"); 17498c2ecf20Sopenharmony_ci goto bad_aeb; 17508c2ecf20Sopenharmony_ci } 17518c2ecf20Sopenharmony_ci } else { 17528c2ecf20Sopenharmony_ci if (av->used_ebs != 0) { 17538c2ecf20Sopenharmony_ci ubi_err(ubi, "non-zero used_ebs"); 17548c2ecf20Sopenharmony_ci goto bad_aeb; 17558c2ecf20Sopenharmony_ci } 17568c2ecf20Sopenharmony_ci } 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci if (aeb->lnum > av->highest_lnum) { 17598c2ecf20Sopenharmony_ci ubi_err(ubi, "incorrect highest_lnum or lnum"); 17608c2ecf20Sopenharmony_ci goto bad_aeb; 17618c2ecf20Sopenharmony_ci } 17628c2ecf20Sopenharmony_ci } 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci if (av->leb_count != leb_count) { 17658c2ecf20Sopenharmony_ci ubi_err(ubi, "bad leb_count, %d objects in the tree", 17668c2ecf20Sopenharmony_ci leb_count); 17678c2ecf20Sopenharmony_ci goto bad_av; 17688c2ecf20Sopenharmony_ci } 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci if (!last_aeb) 17718c2ecf20Sopenharmony_ci continue; 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci aeb = last_aeb; 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci if (aeb->lnum != av->highest_lnum) { 17768c2ecf20Sopenharmony_ci ubi_err(ubi, "bad highest_lnum"); 17778c2ecf20Sopenharmony_ci goto bad_aeb; 17788c2ecf20Sopenharmony_ci } 17798c2ecf20Sopenharmony_ci } 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci if (vols_found != ai->vols_found) { 17828c2ecf20Sopenharmony_ci ubi_err(ubi, "bad ai->vols_found %d, should be %d", 17838c2ecf20Sopenharmony_ci ai->vols_found, vols_found); 17848c2ecf20Sopenharmony_ci goto out; 17858c2ecf20Sopenharmony_ci } 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci /* Check that attaching information is correct */ 17888c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { 17898c2ecf20Sopenharmony_ci last_aeb = NULL; 17908c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) { 17918c2ecf20Sopenharmony_ci int vol_type; 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci cond_resched(); 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci last_aeb = aeb; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci err = ubi_io_read_vid_hdr(ubi, aeb->pnum, vidb, 1); 17988c2ecf20Sopenharmony_ci if (err && err != UBI_IO_BITFLIPS) { 17998c2ecf20Sopenharmony_ci ubi_err(ubi, "VID header is not OK (%d)", 18008c2ecf20Sopenharmony_ci err); 18018c2ecf20Sopenharmony_ci if (err > 0) 18028c2ecf20Sopenharmony_ci err = -EIO; 18038c2ecf20Sopenharmony_ci return err; 18048c2ecf20Sopenharmony_ci } 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci vol_type = vidh->vol_type == UBI_VID_DYNAMIC ? 18078c2ecf20Sopenharmony_ci UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; 18088c2ecf20Sopenharmony_ci if (av->vol_type != vol_type) { 18098c2ecf20Sopenharmony_ci ubi_err(ubi, "bad vol_type"); 18108c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18118c2ecf20Sopenharmony_ci } 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci if (aeb->sqnum != be64_to_cpu(vidh->sqnum)) { 18148c2ecf20Sopenharmony_ci ubi_err(ubi, "bad sqnum %llu", aeb->sqnum); 18158c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18168c2ecf20Sopenharmony_ci } 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci if (av->vol_id != be32_to_cpu(vidh->vol_id)) { 18198c2ecf20Sopenharmony_ci ubi_err(ubi, "bad vol_id %d", av->vol_id); 18208c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci if (av->compat != vidh->compat) { 18248c2ecf20Sopenharmony_ci ubi_err(ubi, "bad compat %d", vidh->compat); 18258c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18268c2ecf20Sopenharmony_ci } 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci if (aeb->lnum != be32_to_cpu(vidh->lnum)) { 18298c2ecf20Sopenharmony_ci ubi_err(ubi, "bad lnum %d", aeb->lnum); 18308c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18318c2ecf20Sopenharmony_ci } 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci if (av->used_ebs != be32_to_cpu(vidh->used_ebs)) { 18348c2ecf20Sopenharmony_ci ubi_err(ubi, "bad used_ebs %d", av->used_ebs); 18358c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18368c2ecf20Sopenharmony_ci } 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci if (av->data_pad != be32_to_cpu(vidh->data_pad)) { 18398c2ecf20Sopenharmony_ci ubi_err(ubi, "bad data_pad %d", av->data_pad); 18408c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci } 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci if (!last_aeb) 18458c2ecf20Sopenharmony_ci continue; 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci if (av->highest_lnum != be32_to_cpu(vidh->lnum)) { 18488c2ecf20Sopenharmony_ci ubi_err(ubi, "bad highest_lnum %d", av->highest_lnum); 18498c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18508c2ecf20Sopenharmony_ci } 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci if (av->last_data_size != be32_to_cpu(vidh->data_size)) { 18538c2ecf20Sopenharmony_ci ubi_err(ubi, "bad last_data_size %d", 18548c2ecf20Sopenharmony_ci av->last_data_size); 18558c2ecf20Sopenharmony_ci goto bad_vid_hdr; 18568c2ecf20Sopenharmony_ci } 18578c2ecf20Sopenharmony_ci } 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci /* 18608c2ecf20Sopenharmony_ci * Make sure that all the physical eraseblocks are in one of the lists 18618c2ecf20Sopenharmony_ci * or trees. 18628c2ecf20Sopenharmony_ci */ 18638c2ecf20Sopenharmony_ci buf = kzalloc(ubi->peb_count, GFP_KERNEL); 18648c2ecf20Sopenharmony_ci if (!buf) 18658c2ecf20Sopenharmony_ci return -ENOMEM; 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci for (pnum = 0; pnum < ubi->peb_count; pnum++) { 18688c2ecf20Sopenharmony_ci err = ubi_io_is_bad(ubi, pnum); 18698c2ecf20Sopenharmony_ci if (err < 0) { 18708c2ecf20Sopenharmony_ci kfree(buf); 18718c2ecf20Sopenharmony_ci return err; 18728c2ecf20Sopenharmony_ci } else if (err) 18738c2ecf20Sopenharmony_ci buf[pnum] = 1; 18748c2ecf20Sopenharmony_ci } 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) 18778c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) 18788c2ecf20Sopenharmony_ci buf[aeb->pnum] = 1; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci list_for_each_entry(aeb, &ai->free, u.list) 18818c2ecf20Sopenharmony_ci buf[aeb->pnum] = 1; 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci list_for_each_entry(aeb, &ai->corr, u.list) 18848c2ecf20Sopenharmony_ci buf[aeb->pnum] = 1; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci list_for_each_entry(aeb, &ai->erase, u.list) 18878c2ecf20Sopenharmony_ci buf[aeb->pnum] = 1; 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci list_for_each_entry(aeb, &ai->alien, u.list) 18908c2ecf20Sopenharmony_ci buf[aeb->pnum] = 1; 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci err = 0; 18938c2ecf20Sopenharmony_ci for (pnum = 0; pnum < ubi->peb_count; pnum++) 18948c2ecf20Sopenharmony_ci if (!buf[pnum]) { 18958c2ecf20Sopenharmony_ci ubi_err(ubi, "PEB %d is not referred", pnum); 18968c2ecf20Sopenharmony_ci err = 1; 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci kfree(buf); 19008c2ecf20Sopenharmony_ci if (err) 19018c2ecf20Sopenharmony_ci goto out; 19028c2ecf20Sopenharmony_ci return 0; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_cibad_aeb: 19058c2ecf20Sopenharmony_ci ubi_err(ubi, "bad attaching information about LEB %d", aeb->lnum); 19068c2ecf20Sopenharmony_ci ubi_dump_aeb(aeb, 0); 19078c2ecf20Sopenharmony_ci ubi_dump_av(av); 19088c2ecf20Sopenharmony_ci goto out; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_cibad_av: 19118c2ecf20Sopenharmony_ci ubi_err(ubi, "bad attaching information about volume %d", av->vol_id); 19128c2ecf20Sopenharmony_ci ubi_dump_av(av); 19138c2ecf20Sopenharmony_ci goto out; 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_cibad_vid_hdr: 19168c2ecf20Sopenharmony_ci ubi_err(ubi, "bad attaching information about volume %d", av->vol_id); 19178c2ecf20Sopenharmony_ci ubi_dump_av(av); 19188c2ecf20Sopenharmony_ci ubi_dump_vid_hdr(vidh); 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ciout: 19218c2ecf20Sopenharmony_ci dump_stack(); 19228c2ecf20Sopenharmony_ci return -EINVAL; 19238c2ecf20Sopenharmony_ci} 1924