1 /* 2 * Copyright (c) International Business Machines Corp., 2006 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 * 6 * Author: Artem Bityutskiy (Битюцкий Артём) 7 */ 8 9 #include <ubi_uboot.h> 10 #include "ubi.h" 11 #ifndef __UBOOT__ 12 #include <linux/debugfs.h> 13 #include <linux/uaccess.h> 14 #include <linux/module.h> 15 #endif 16 17 /** 18 * ubi_dump_flash - dump a region of flash. 19 * @ubi: UBI device description object 20 * @pnum: the physical eraseblock number to dump 21 * @offset: the starting offset within the physical eraseblock to dump 22 * @len: the length of the region to dump 23 */ 24 void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len) 25 { 26 int err; 27 size_t read; 28 void *buf; 29 loff_t addr = (loff_t)pnum * ubi->peb_size + offset; 30 31 buf = vmalloc(len); 32 if (!buf) 33 return; 34 err = mtd_read(ubi->mtd, addr, len, &read, buf); 35 if (err && err != -EUCLEAN) { 36 ubi_err("error %d while reading %d bytes from PEB %d:%d, read %zd bytes", 37 err, len, pnum, offset, read); 38 goto out; 39 } 40 41 ubi_msg("dumping %d bytes of data from PEB %d, offset %d", 42 len, pnum, offset); 43 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1); 44 out: 45 vfree(buf); 46 return; 47 } 48 49 /** 50 * ubi_dump_ec_hdr - dump an erase counter header. 51 * @ec_hdr: the erase counter header to dump 52 */ 53 void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) 54 { 55 pr_err("Erase counter header dump:\n"); 56 pr_err("\tmagic %#08x\n", be32_to_cpu(ec_hdr->magic)); 57 pr_err("\tversion %d\n", (int)ec_hdr->version); 58 pr_err("\tec %llu\n", (long long)be64_to_cpu(ec_hdr->ec)); 59 pr_err("\tvid_hdr_offset %d\n", be32_to_cpu(ec_hdr->vid_hdr_offset)); 60 pr_err("\tdata_offset %d\n", be32_to_cpu(ec_hdr->data_offset)); 61 pr_err("\timage_seq %d\n", be32_to_cpu(ec_hdr->image_seq)); 62 pr_err("\thdr_crc %#08x\n", be32_to_cpu(ec_hdr->hdr_crc)); 63 pr_err("erase counter header hexdump:\n"); 64 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, 65 ec_hdr, UBI_EC_HDR_SIZE, 1); 66 } 67 68 /** 69 * ubi_dump_vid_hdr - dump a volume identifier header. 70 * @vid_hdr: the volume identifier header to dump 71 */ 72 void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) 73 { 74 pr_err("Volume identifier header dump:\n"); 75 pr_err("\tmagic %08x\n", be32_to_cpu(vid_hdr->magic)); 76 pr_err("\tversion %d\n", (int)vid_hdr->version); 77 pr_err("\tvol_type %d\n", (int)vid_hdr->vol_type); 78 pr_err("\tcopy_flag %d\n", (int)vid_hdr->copy_flag); 79 pr_err("\tcompat %d\n", (int)vid_hdr->compat); 80 pr_err("\tvol_id %d\n", be32_to_cpu(vid_hdr->vol_id)); 81 pr_err("\tlnum %d\n", be32_to_cpu(vid_hdr->lnum)); 82 pr_err("\tdata_size %d\n", be32_to_cpu(vid_hdr->data_size)); 83 pr_err("\tused_ebs %d\n", be32_to_cpu(vid_hdr->used_ebs)); 84 pr_err("\tdata_pad %d\n", be32_to_cpu(vid_hdr->data_pad)); 85 pr_err("\tsqnum %llu\n", 86 (unsigned long long)be64_to_cpu(vid_hdr->sqnum)); 87 pr_err("\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc)); 88 pr_err("Volume identifier header hexdump:\n"); 89 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, 90 vid_hdr, UBI_VID_HDR_SIZE, 1); 91 } 92 93 /** 94 * ubi_dump_vol_info - dump volume information. 95 * @vol: UBI volume description object 96 */ 97 void ubi_dump_vol_info(const struct ubi_volume *vol) 98 { 99 printf("Volume information dump:\n"); 100 printf("\tvol_id %d\n", vol->vol_id); 101 printf("\treserved_pebs %d\n", vol->reserved_pebs); 102 printf("\talignment %d\n", vol->alignment); 103 printf("\tdata_pad %d\n", vol->data_pad); 104 printf("\tvol_type %d\n", vol->vol_type); 105 printf("\tname_len %d\n", vol->name_len); 106 printf("\tusable_leb_size %d\n", vol->usable_leb_size); 107 printf("\tused_ebs %d\n", vol->used_ebs); 108 printf("\tused_bytes %lld\n", vol->used_bytes); 109 printf("\tlast_eb_bytes %d\n", vol->last_eb_bytes); 110 printf("\tcorrupted %d\n", vol->corrupted); 111 printf("\tupd_marker %d\n", vol->upd_marker); 112 113 if (vol->name_len <= UBI_VOL_NAME_MAX && 114 strnlen(vol->name, vol->name_len + 1) == vol->name_len) { 115 printf("\tname %s\n", vol->name); 116 } else { 117 printf("\t1st 5 characters of name: %c%c%c%c%c\n", 118 vol->name[0], vol->name[1], vol->name[2], 119 vol->name[3], vol->name[4]); 120 } 121 } 122 123 /** 124 * ubi_dump_vtbl_record - dump a &struct ubi_vtbl_record object. 125 * @r: the object to dump 126 * @idx: volume table index 127 */ 128 void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) 129 { 130 int name_len = be16_to_cpu(r->name_len); 131 132 pr_err("Volume table record %d dump:\n", idx); 133 pr_err("\treserved_pebs %d\n", be32_to_cpu(r->reserved_pebs)); 134 pr_err("\talignment %d\n", be32_to_cpu(r->alignment)); 135 pr_err("\tdata_pad %d\n", be32_to_cpu(r->data_pad)); 136 pr_err("\tvol_type %d\n", (int)r->vol_type); 137 pr_err("\tupd_marker %d\n", (int)r->upd_marker); 138 pr_err("\tname_len %d\n", name_len); 139 140 if (r->name[0] == '\0') { 141 pr_err("\tname NULL\n"); 142 return; 143 } 144 145 if (name_len <= UBI_VOL_NAME_MAX && 146 strnlen(&r->name[0], name_len + 1) == name_len) { 147 pr_err("\tname %s\n", &r->name[0]); 148 } else { 149 pr_err("\t1st 5 characters of name: %c%c%c%c%c\n", 150 r->name[0], r->name[1], r->name[2], r->name[3], 151 r->name[4]); 152 } 153 pr_err("\tcrc %#08x\n", be32_to_cpu(r->crc)); 154 } 155 156 /** 157 * ubi_dump_av - dump a &struct ubi_ainf_volume object. 158 * @av: the object to dump 159 */ 160 void ubi_dump_av(const struct ubi_ainf_volume *av) 161 { 162 pr_err("Volume attaching information dump:\n"); 163 pr_err("\tvol_id %d\n", av->vol_id); 164 pr_err("\thighest_lnum %d\n", av->highest_lnum); 165 pr_err("\tleb_count %d\n", av->leb_count); 166 pr_err("\tcompat %d\n", av->compat); 167 pr_err("\tvol_type %d\n", av->vol_type); 168 pr_err("\tused_ebs %d\n", av->used_ebs); 169 pr_err("\tlast_data_size %d\n", av->last_data_size); 170 pr_err("\tdata_pad %d\n", av->data_pad); 171 } 172 173 /** 174 * ubi_dump_aeb - dump a &struct ubi_ainf_peb object. 175 * @aeb: the object to dump 176 * @type: object type: 0 - not corrupted, 1 - corrupted 177 */ 178 void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type) 179 { 180 pr_err("eraseblock attaching information dump:\n"); 181 pr_err("\tec %d\n", aeb->ec); 182 pr_err("\tpnum %d\n", aeb->pnum); 183 if (type == 0) { 184 pr_err("\tlnum %d\n", aeb->lnum); 185 pr_err("\tscrub %d\n", aeb->scrub); 186 pr_err("\tsqnum %llu\n", aeb->sqnum); 187 } 188 } 189 190 /** 191 * ubi_dump_mkvol_req - dump a &struct ubi_mkvol_req object. 192 * @req: the object to dump 193 */ 194 void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req) 195 { 196 char nm[17]; 197 198 pr_err("Volume creation request dump:\n"); 199 pr_err("\tvol_id %d\n", req->vol_id); 200 pr_err("\talignment %d\n", req->alignment); 201 pr_err("\tbytes %lld\n", (long long)req->bytes); 202 pr_err("\tvol_type %d\n", req->vol_type); 203 pr_err("\tname_len %d\n", req->name_len); 204 205 memcpy(nm, req->name, 16); 206 nm[16] = 0; 207 pr_err("\t1st 16 characters of name: %s\n", nm); 208 } 209 210 #ifndef __UBOOT__ 211 /* 212 * Root directory for UBI stuff in debugfs. Contains sub-directories which 213 * contain the stuff specific to particular UBI devices. 214 */ 215 static struct dentry *dfs_rootdir; 216 217 /** 218 * ubi_debugfs_init - create UBI debugfs directory. 219 * 220 * Create UBI debugfs directory. Returns zero in case of success and a negative 221 * error code in case of failure. 222 */ 223 int ubi_debugfs_init(void) 224 { 225 if (!IS_ENABLED(CONFIG_DEBUG_FS)) 226 return 0; 227 228 dfs_rootdir = debugfs_create_dir("ubi", NULL); 229 if (IS_ERR_OR_NULL(dfs_rootdir)) { 230 int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir); 231 232 ubi_err("cannot create \"ubi\" debugfs directory, error %d\n", 233 err); 234 return err; 235 } 236 237 return 0; 238 } 239 240 /** 241 * ubi_debugfs_exit - remove UBI debugfs directory. 242 */ 243 void ubi_debugfs_exit(void) 244 { 245 if (IS_ENABLED(CONFIG_DEBUG_FS)) 246 debugfs_remove(dfs_rootdir); 247 } 248 249 /* Read an UBI debugfs file */ 250 static ssize_t dfs_file_read(struct file *file, char __user *user_buf, 251 size_t count, loff_t *ppos) 252 { 253 unsigned long ubi_num = (unsigned long)file->private_data; 254 struct dentry *dent = file->f_path.dentry; 255 struct ubi_device *ubi; 256 struct ubi_debug_info *d; 257 char buf[3]; 258 int val; 259 260 ubi = ubi_get_device(ubi_num); 261 if (!ubi) 262 return -ENODEV; 263 d = &ubi->dbg; 264 265 if (dent == d->dfs_chk_gen) 266 val = d->chk_gen; 267 else if (dent == d->dfs_chk_io) 268 val = d->chk_io; 269 else if (dent == d->dfs_disable_bgt) 270 val = d->disable_bgt; 271 else if (dent == d->dfs_emulate_bitflips) 272 val = d->emulate_bitflips; 273 else if (dent == d->dfs_emulate_io_failures) 274 val = d->emulate_io_failures; 275 else { 276 count = -EINVAL; 277 goto out; 278 } 279 280 if (val) 281 buf[0] = '1'; 282 else 283 buf[0] = '0'; 284 buf[1] = '\n'; 285 buf[2] = 0x00; 286 287 count = simple_read_from_buffer(user_buf, count, ppos, buf, 2); 288 289 out: 290 ubi_put_device(ubi); 291 return count; 292 } 293 294 /* Write an UBI debugfs file */ 295 static ssize_t dfs_file_write(struct file *file, const char __user *user_buf, 296 size_t count, loff_t *ppos) 297 { 298 unsigned long ubi_num = (unsigned long)file->private_data; 299 struct dentry *dent = file->f_path.dentry; 300 struct ubi_device *ubi; 301 struct ubi_debug_info *d; 302 size_t buf_size; 303 char buf[8]; 304 int val; 305 306 ubi = ubi_get_device(ubi_num); 307 if (!ubi) 308 return -ENODEV; 309 d = &ubi->dbg; 310 311 buf_size = min_t(size_t, count, (sizeof(buf) - 1)); 312 if (copy_from_user(buf, user_buf, buf_size)) { 313 count = -EFAULT; 314 goto out; 315 } 316 317 if (buf[0] == '1') 318 val = 1; 319 else if (buf[0] == '0') 320 val = 0; 321 else { 322 count = -EINVAL; 323 goto out; 324 } 325 326 if (dent == d->dfs_chk_gen) 327 d->chk_gen = val; 328 else if (dent == d->dfs_chk_io) 329 d->chk_io = val; 330 else if (dent == d->dfs_disable_bgt) 331 d->disable_bgt = val; 332 else if (dent == d->dfs_emulate_bitflips) 333 d->emulate_bitflips = val; 334 else if (dent == d->dfs_emulate_io_failures) 335 d->emulate_io_failures = val; 336 else 337 count = -EINVAL; 338 339 out: 340 ubi_put_device(ubi); 341 return count; 342 } 343 344 /* File operations for all UBI debugfs files */ 345 static const struct file_operations dfs_fops = { 346 .read = dfs_file_read, 347 .write = dfs_file_write, 348 .open = simple_open, 349 .llseek = no_llseek, 350 .owner = THIS_MODULE, 351 }; 352 353 /** 354 * ubi_debugfs_init_dev - initialize debugfs for an UBI device. 355 * @ubi: UBI device description object 356 * 357 * This function creates all debugfs files for UBI device @ubi. Returns zero in 358 * case of success and a negative error code in case of failure. 359 */ 360 int ubi_debugfs_init_dev(struct ubi_device *ubi) 361 { 362 int err, n; 363 unsigned long ubi_num = ubi->ubi_num; 364 const char *fname; 365 struct dentry *dent; 366 struct ubi_debug_info *d = &ubi->dbg; 367 368 if (!IS_ENABLED(CONFIG_DEBUG_FS)) 369 return 0; 370 371 n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME, 372 ubi->ubi_num); 373 if (n == UBI_DFS_DIR_LEN) { 374 /* The array size is too small */ 375 fname = UBI_DFS_DIR_NAME; 376 dent = ERR_PTR(-EINVAL); 377 goto out; 378 } 379 380 fname = d->dfs_dir_name; 381 dent = debugfs_create_dir(fname, dfs_rootdir); 382 if (IS_ERR_OR_NULL(dent)) 383 goto out; 384 d->dfs_dir = dent; 385 386 fname = "chk_gen"; 387 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, 388 &dfs_fops); 389 if (IS_ERR_OR_NULL(dent)) 390 goto out_remove; 391 d->dfs_chk_gen = dent; 392 393 fname = "chk_io"; 394 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, 395 &dfs_fops); 396 if (IS_ERR_OR_NULL(dent)) 397 goto out_remove; 398 d->dfs_chk_io = dent; 399 400 fname = "tst_disable_bgt"; 401 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, 402 &dfs_fops); 403 if (IS_ERR_OR_NULL(dent)) 404 goto out_remove; 405 d->dfs_disable_bgt = dent; 406 407 fname = "tst_emulate_bitflips"; 408 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, 409 &dfs_fops); 410 if (IS_ERR_OR_NULL(dent)) 411 goto out_remove; 412 d->dfs_emulate_bitflips = dent; 413 414 fname = "tst_emulate_io_failures"; 415 dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num, 416 &dfs_fops); 417 if (IS_ERR_OR_NULL(dent)) 418 goto out_remove; 419 d->dfs_emulate_io_failures = dent; 420 421 return 0; 422 423 out_remove: 424 debugfs_remove_recursive(d->dfs_dir); 425 out: 426 err = dent ? PTR_ERR(dent) : -ENODEV; 427 ubi_err("cannot create \"%s\" debugfs file or directory, error %d\n", 428 fname, err); 429 return err; 430 } 431 432 /** 433 * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi 434 * @ubi: UBI device description object 435 */ 436 void ubi_debugfs_exit_dev(struct ubi_device *ubi) 437 { 438 if (IS_ENABLED(CONFIG_DEBUG_FS)) 439 debugfs_remove_recursive(ubi->dbg.dfs_dir); 440 } 441 #else 442 int ubi_debugfs_init(void) 443 { 444 return 0; 445 } 446 447 void ubi_debugfs_exit(void) 448 { 449 } 450 451 int ubi_debugfs_init_dev(struct ubi_device *ubi) 452 { 453 return 0; 454 } 455 456 void ubi_debugfs_exit_dev(struct ubi_device *ubi) 457 { 458 } 459 #endif 460