docs: update for new data placement options
[fio.git] / oslib / libmtd.c
1 /*
2  * Copyright (c) International Business Machines Corp., 2006
3  * Copyright (C) 2009 Nokia Corporation
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13  * the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * Author: Artem Bityutskiy
20  *
21  * MTD library.
22  */
23
24 /* Imported from mtd-utils by dehrenberg */
25
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <dirent.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <inttypes.h>
37
38 #include "../compiler/compiler.h"
39
40 #include <mtd/mtd-user.h>
41 #include "libmtd.h"
42
43 #include "libmtd_int.h"
44 #include "libmtd_common.h"
45
46 /**
47  * mkpath - compose full path from 2 given components.
48  * @path: the first component
49  * @name: the second component
50  *
51  * This function returns the resulting path in case of success and %NULL in
52  * case of failure.
53  */
54 static char *mkpath(const char *path, const char *name)
55 {
56         char *n;
57         size_t len1 = strlen(path);
58         size_t len2 = strlen(name);
59
60         n = xmalloc(len1 + len2 + 6);
61
62         memcpy(n, path, len1);
63         if (n[len1 - 1] != '/')
64                 n[len1++] = '/';
65
66         memcpy(n + len1, name, len2 + 1);
67         return n;
68 }
69
70 /**
71  * read_data - read data from a file.
72  * @file: the file to read from
73  * @buf: the buffer to read to
74  * @buf_len: buffer length
75  *
76  * This function returns number of read bytes in case of success and %-1 in
77  * case of failure. Note, if the file contains more then @buf_len bytes of
78  * date, this function fails with %EINVAL error code.
79  */
80 static int read_data(const char *file, void *buf, int buf_len)
81 {
82         int fd, rd, tmp, tmp1;
83
84         fd = open(file, O_RDONLY | O_CLOEXEC);
85         if (fd == -1)
86                 return -1;
87
88         rd = read(fd, buf, buf_len);
89         if (rd == -1) {
90                 sys_errmsg("cannot read \"%s\"", file);
91                 goto out_error;
92         }
93
94         if (rd == buf_len) {
95                 errmsg("contents of \"%s\" is too long", file);
96                 errno = EINVAL;
97                 goto out_error;
98         }
99
100         ((char *)buf)[rd] = '\0';
101
102         /* Make sure all data is read */
103         tmp1 = read(fd, &tmp, 1);
104         if (tmp1 == 1) {
105                 sys_errmsg("cannot read \"%s\"", file);
106                 goto out_error;
107         }
108         if (tmp1) {
109                 errmsg("file \"%s\" contains too much data (> %d bytes)",
110                        file, buf_len);
111                 errno = EINVAL;
112                 goto out_error;
113         }
114
115         if (close(fd)) {
116                 sys_errmsg("close failed on \"%s\"", file);
117                 return -1;
118         }
119
120         return rd;
121
122 out_error:
123         close(fd);
124         return -1;
125 }
126
127 /**
128  * read_major - read major and minor numbers from a file.
129  * @file: name of the file to read from
130  * @major: major number is returned here
131  * @minor: minor number is returned here
132  *
133  * This function returns % in case of success, and %-1 in case of failure.
134  */
135 static int read_major(const char *file, int *major, int *minor)
136 {
137         int ret;
138         char buf[50];
139
140         ret = read_data(file, buf, 50);
141         if (ret < 0)
142                 return ret;
143
144         ret = sscanf(buf, "%d:%d\n", major, minor);
145         if (ret != 2) {
146                 errno = EINVAL;
147                 return errmsg("\"%s\" does not have major:minor format", file);
148         }
149
150         if (*major < 0 || *minor < 0) {
151                 errno = EINVAL;
152                 return errmsg("bad major:minor %d:%d in \"%s\"",
153                               *major, *minor, file);
154         }
155
156         return 0;
157 }
158
159 /**
160  * dev_get_major - get major and minor numbers of an MTD device.
161  * @lib: libmtd descriptor
162  * @mtd_num: MTD device number
163  * @major: major number is returned here
164  * @minor: minor number is returned here
165  *
166  * This function returns zero in case of success and %-1 in case of failure.
167  */
168 static int dev_get_major(struct libmtd *lib, int mtd_num, int *major, int *minor)
169 {
170         char file[strlen(lib->mtd_dev) + 50];
171
172         sprintf(file, lib->mtd_dev, mtd_num);
173         return read_major(file, major, minor);
174 }
175
176 /**
177  * dev_read_data - read data from an MTD device's sysfs file.
178  * @patt: file pattern to read from
179  * @mtd_num: MTD device number
180  * @buf: buffer to read to
181  * @buf_len: buffer length
182  *
183  * This function returns number of read bytes in case of success and %-1 in
184  * case of failure.
185  */
186 static int dev_read_data(const char *patt, int mtd_num, void *buf, int buf_len)
187 {
188         char file[strlen(patt) + 100];
189
190         sprintf(file, patt, mtd_num);
191         return read_data(file, buf, buf_len);
192 }
193
194 /**
195  * read_hex_ll - read a hex 'long long' value from a file.
196  * @file: the file to read from
197  * @value: the result is stored here
198  *
199  * This function reads file @file and interprets its contents as hexadecimal
200  * 'long long' integer. If this is not true, it fails with %EINVAL error code.
201  * Returns %0 in case of success and %-1 in case of failure.
202  */
203 static int read_hex_ll(const char *file, long long *value)
204 {
205         int fd, rd;
206         char buf[50];
207
208         fd = open(file, O_RDONLY | O_CLOEXEC);
209         if (fd == -1)
210                 return -1;
211
212         rd = read(fd, buf, sizeof(buf));
213         if (rd == -1) {
214                 sys_errmsg("cannot read \"%s\"", file);
215                 goto out_error;
216         }
217         if (rd == sizeof(buf)) {
218                 errmsg("contents of \"%s\" is too long", file);
219                 errno = EINVAL;
220                 goto out_error;
221         }
222         buf[rd] = '\0';
223
224         if (sscanf(buf, "%llx\n", value) != 1) {
225                 errmsg("cannot read integer from \"%s\"\n", file);
226                 errno = EINVAL;
227                 goto out_error;
228         }
229
230         if (*value < 0) {
231                 errmsg("negative value %lld in \"%s\"", *value, file);
232                 errno = EINVAL;
233                 goto out_error;
234         }
235
236         if (close(fd))
237                 return sys_errmsg("close failed on \"%s\"", file);
238
239         return 0;
240
241 out_error:
242         close(fd);
243         return -1;
244 }
245
246 /**
247  * read_pos_ll - read a positive 'long long' value from a file.
248  * @file: the file to read from
249  * @value: the result is stored here
250  *
251  * This function reads file @file and interprets its contents as a positive
252  * 'long long' integer. If this is not true, it fails with %EINVAL error code.
253  * Returns %0 in case of success and %-1 in case of failure.
254  */
255 static int read_pos_ll(const char *file, long long *value)
256 {
257         int fd, rd;
258         char buf[50];
259
260         fd = open(file, O_RDONLY | O_CLOEXEC);
261         if (fd == -1)
262                 return -1;
263
264         rd = read(fd, buf, 50);
265         if (rd == -1) {
266                 sys_errmsg("cannot read \"%s\"", file);
267                 goto out_error;
268         }
269         if (rd == 50) {
270                 errmsg("contents of \"%s\" is too long", file);
271                 errno = EINVAL;
272                 goto out_error;
273         }
274
275         if (sscanf(buf, "%lld\n", value) != 1) {
276                 errmsg("cannot read integer from \"%s\"\n", file);
277                 errno = EINVAL;
278                 goto out_error;
279         }
280
281         if (*value < 0) {
282                 errmsg("negative value %lld in \"%s\"", *value, file);
283                 errno = EINVAL;
284                 goto out_error;
285         }
286
287         if (close(fd))
288                 return sys_errmsg("close failed on \"%s\"", file);
289
290         return 0;
291
292 out_error:
293         close(fd);
294         return -1;
295 }
296
297 /**
298  * read_hex_int - read an 'int' value from a file.
299  * @file: the file to read from
300  * @value: the result is stored here
301  *
302  * This function is the same as 'read_pos_ll()', but it reads an 'int'
303  * value, not 'long long'.
304  */
305 static int read_hex_int(const char *file, int *value)
306 {
307         long long res;
308
309         if (read_hex_ll(file, &res))
310                 return -1;
311
312         /* Make sure the value has correct range */
313         if (res > INT_MAX || res < INT_MIN) {
314                 errmsg("value %lld read from file \"%s\" is out of range",
315                        res, file);
316                 errno = EINVAL;
317                 return -1;
318         }
319
320         *value = res;
321         return 0;
322 }
323
324 /**
325  * read_pos_int - read a positive 'int' value from a file.
326  * @file: the file to read from
327  * @value: the result is stored here
328  *
329  * This function is the same as 'read_pos_ll()', but it reads an 'int'
330  * value, not 'long long'.
331  */
332 static int read_pos_int(const char *file, int *value)
333 {
334         long long res;
335
336         if (read_pos_ll(file, &res))
337                 return -1;
338
339         /* Make sure the value is not too big */
340         if (res > INT_MAX) {
341                 errmsg("value %lld read from file \"%s\" is out of range",
342                        res, file);
343                 errno = EINVAL;
344                 return -1;
345         }
346
347         *value = res;
348         return 0;
349 }
350
351 /**
352  * dev_read_hex_int - read an hex 'int' value from an MTD device sysfs file.
353  * @patt: file pattern to read from
354  * @mtd_num: MTD device number
355  * @value: the result is stored here
356  *
357  * This function returns %0 in case of success and %-1 in case of failure.
358  */
359 static int dev_read_hex_int(const char *patt, int mtd_num, int *value)
360 {
361         char file[strlen(patt) + 50];
362
363         sprintf(file, patt, mtd_num);
364         return read_hex_int(file, value);
365 }
366
367 /**
368  * dev_read_pos_int - read a positive 'int' value from an MTD device sysfs file.
369  * @patt: file pattern to read from
370  * @mtd_num: MTD device number
371  * @value: the result is stored here
372  *
373  * This function returns %0 in case of success and %-1 in case of failure.
374  */
375 static int dev_read_pos_int(const char *patt, int mtd_num, int *value)
376 {
377         char file[strlen(patt) + 50];
378
379         sprintf(file, patt, mtd_num);
380         return read_pos_int(file, value);
381 }
382
383 /**
384  * dev_read_pos_ll - read a positive 'long long' value from an MTD device sysfs file.
385  * @patt: file pattern to read from
386  * @mtd_num: MTD device number
387  * @value: the result is stored here
388  *
389  * This function returns %0 in case of success and %-1 in case of failure.
390  */
391 static int dev_read_pos_ll(const char *patt, int mtd_num, long long *value)
392 {
393         char file[strlen(patt) + 50];
394
395         sprintf(file, patt, mtd_num);
396         return read_pos_ll(file, value);
397 }
398
399 /**
400  * type_str2int - convert MTD device type to integer.
401  * @str: MTD device type string to convert
402  *
403  * This function converts MTD device type string @str, read from sysfs, into an
404  * integer.
405  */
406 static int type_str2int(const char *str)
407 {
408         if (!strcmp(str, "nand"))
409                 return MTD_NANDFLASH;
410         if (!strcmp(str, "mlc-nand"))
411                 return MTD_MLCNANDFLASH;
412         if (!strcmp(str, "nor"))
413                 return MTD_NORFLASH;
414         if (!strcmp(str, "rom"))
415                 return MTD_ROM;
416         if (!strcmp(str, "absent"))
417                 return MTD_ABSENT;
418         if (!strcmp(str, "dataflash"))
419                 return MTD_DATAFLASH;
420         if (!strcmp(str, "ram"))
421                 return MTD_RAM;
422         if (!strcmp(str, "ubi"))
423                 return MTD_UBIVOLUME;
424         return -1;
425 }
426
427 /**
428  * dev_node2num - find UBI device number by its character device node.
429  * @lib: MTD library descriptor
430  * @node: name of the MTD device node
431  * @mtd_num: MTD device number is returned here
432  *
433  * This function returns %0 in case of success and %-1 in case of failure.
434  */
435 static int dev_node2num(struct libmtd *lib, const char *node, int *mtd_num)
436 {
437         struct stat st;
438         int i, mjr, mnr;
439         struct mtd_info info;
440
441         if (stat(node, &st))
442                 return sys_errmsg("cannot get information about \"%s\"", node);
443
444         if (!S_ISCHR(st.st_mode)) {
445                 errmsg("\"%s\" is not a character device", node);
446                 errno = EINVAL;
447                 return -1;
448         }
449
450         mjr = major(st.st_rdev);
451         mnr = minor(st.st_rdev);
452
453         if (mtd_get_info((libmtd_t *)lib, &info))
454                 return -1;
455
456         for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) {
457                 int mjr1, mnr1, ret;
458
459                 ret = dev_get_major(lib, i, &mjr1, &mnr1);
460                 if (ret) {
461                         if (errno == ENOENT)
462                                 continue;
463                         if (!errno)
464                                 break;
465                         return -1;
466                 }
467
468                 if (mjr1 == mjr && mnr1 == mnr) {
469                         errno = 0;
470                         *mtd_num = i;
471                         return 0;
472                 }
473         }
474
475         errno = ENODEV;
476         return -1;
477 }
478
479 /**
480  * sysfs_is_supported - check whether the MTD sub-system supports MTD.
481  * @lib: MTD library descriptor
482  *
483  * The Linux kernel MTD subsystem gained MTD support starting from kernel
484  * 2.6.30 and libmtd tries to use sysfs interface if possible, because the NAND
485  * sub-page size is available there (and not available at all in pre-sysfs
486  * kernels).
487  *
488  * Very old kernels did not have "/sys/class/mtd" directory. Not very old
489  * kernels (e.g., 2.6.29) did have "/sys/class/mtd/mtdX" directories, by there
490  * were no files there, e.g., the "name" file was not present. So all we can do
491  * is to check for a "/sys/class/mtd/mtdX/name" file. But this is not a
492  * reliable check, because if this is a new system with no MTD devices - we'll
493  * treat it as a pre-sysfs system.
494  */
495 static int sysfs_is_supported(struct libmtd *lib)
496 {
497         int fd, num = -1;
498         DIR *sysfs_mtd;
499         char file[strlen(lib->mtd_name) + 10];
500
501         sysfs_mtd = opendir(lib->sysfs_mtd);
502         if (!sysfs_mtd) {
503                 if (errno == ENOENT) {
504                         errno = 0;
505                         return 0;
506                 }
507                 return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd);
508         }
509
510         /*
511          * First of all find an "mtdX" directory. This is needed because there
512          * may be, for example, mtd1 but no mtd0.
513          */
514         while (1) {
515                 int ret, mtd_num;
516                 char tmp_buf[256];
517                 struct dirent *dirent;
518
519                 dirent = readdir(sysfs_mtd);
520                 if (!dirent)
521                         break;
522
523                 if (strlen(dirent->d_name) >= 255) {
524                         errmsg("invalid entry in %s: \"%s\"",
525                                lib->sysfs_mtd, dirent->d_name);
526                         errno = EINVAL;
527                         closedir(sysfs_mtd);
528                         return -1;
529                 }
530
531                 ret = sscanf(dirent->d_name, MTD_NAME_PATT"%s",
532                              &mtd_num, tmp_buf);
533                 if (ret == 1) {
534                         num = mtd_num;
535                         break;
536                 }
537         }
538
539         if (closedir(sysfs_mtd))
540                 return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd);
541
542         if (num == -1)
543                 /* No mtd device, treat this as pre-sysfs system */
544                 return 0;
545
546         sprintf(file, lib->mtd_name, num);
547         fd = open(file, O_RDONLY | O_CLOEXEC);
548         if (fd == -1)
549                 return 0;
550
551         if (close(fd)) {
552                 sys_errmsg("close failed on \"%s\"", file);
553                 return -1;
554         }
555
556         return 1;
557 }
558
559 libmtd_t libmtd_open(void)
560 {
561         struct libmtd *lib;
562
563         lib = xzalloc(sizeof(*lib));
564
565         lib->offs64_ioctls = OFFS64_IOCTLS_UNKNOWN;
566
567         lib->sysfs_mtd = mkpath("/sys", SYSFS_MTD);
568         if (!lib->sysfs_mtd)
569                 goto out_error;
570
571         lib->mtd = mkpath(lib->sysfs_mtd, MTD_NAME_PATT);
572         if (!lib->mtd)
573                 goto out_error;
574
575         lib->mtd_name = mkpath(lib->mtd, MTD_NAME);
576         if (!lib->mtd_name)
577                 goto out_error;
578
579         if (!sysfs_is_supported(lib)) {
580                 free(lib->mtd);
581                 free(lib->sysfs_mtd);
582                 free(lib->mtd_name);
583                 lib->mtd_name = lib->mtd = lib->sysfs_mtd = NULL;
584                 return lib;
585         }
586
587         lib->mtd_dev = mkpath(lib->mtd, MTD_DEV);
588         if (!lib->mtd_dev)
589                 goto out_error;
590
591         lib->mtd_type = mkpath(lib->mtd, MTD_TYPE);
592         if (!lib->mtd_type)
593                 goto out_error;
594
595         lib->mtd_eb_size = mkpath(lib->mtd, MTD_EB_SIZE);
596         if (!lib->mtd_eb_size)
597                 goto out_error;
598
599         lib->mtd_size = mkpath(lib->mtd, MTD_SIZE);
600         if (!lib->mtd_size)
601                 goto out_error;
602
603         lib->mtd_min_io_size = mkpath(lib->mtd, MTD_MIN_IO_SIZE);
604         if (!lib->mtd_min_io_size)
605                 goto out_error;
606
607         lib->mtd_subpage_size = mkpath(lib->mtd, MTD_SUBPAGE_SIZE);
608         if (!lib->mtd_subpage_size)
609                 goto out_error;
610
611         lib->mtd_oob_size = mkpath(lib->mtd, MTD_OOB_SIZE);
612         if (!lib->mtd_oob_size)
613                 goto out_error;
614
615         lib->mtd_region_cnt = mkpath(lib->mtd, MTD_REGION_CNT);
616         if (!lib->mtd_region_cnt)
617                 goto out_error;
618
619         lib->mtd_flags = mkpath(lib->mtd, MTD_FLAGS);
620         if (!lib->mtd_flags)
621                 goto out_error;
622
623         lib->sysfs_supported = 1;
624         return lib;
625
626 out_error:
627         libmtd_close((libmtd_t)lib);
628         return NULL;
629 }
630
631 void libmtd_close(libmtd_t desc)
632 {
633         struct libmtd *lib = (struct libmtd *)desc;
634
635         free(lib->mtd_flags);
636         free(lib->mtd_region_cnt);
637         free(lib->mtd_oob_size);
638         free(lib->mtd_subpage_size);
639         free(lib->mtd_min_io_size);
640         free(lib->mtd_size);
641         free(lib->mtd_eb_size);
642         free(lib->mtd_type);
643         free(lib->mtd_dev);
644         free(lib->mtd_name);
645         free(lib->mtd);
646         free(lib->sysfs_mtd);
647         free(lib);
648 }
649
650 int mtd_dev_present(libmtd_t desc, int mtd_num) {
651         struct stat st;
652         struct libmtd *lib = (struct libmtd *)desc;
653
654         if (!lib->sysfs_supported) {
655                 return legacy_dev_present(mtd_num) == 1;
656         } else {
657                 char file[strlen(lib->mtd) + 10];
658
659                 sprintf(file, lib->mtd, mtd_num);
660                 return !stat(file, &st);
661         }
662 }
663
664 int mtd_get_info(libmtd_t desc, struct mtd_info *info)
665 {
666         DIR *sysfs_mtd;
667         struct dirent *dirent;
668         struct libmtd *lib = (struct libmtd *)desc;
669
670         memset(info, 0, sizeof(struct mtd_info));
671
672         if (!lib->sysfs_supported)
673                 return legacy_mtd_get_info(info);
674
675         info->sysfs_supported = 1;
676
677         /*
678          * We have to scan the MTD sysfs directory to identify how many MTD
679          * devices are present.
680          */
681         sysfs_mtd = opendir(lib->sysfs_mtd);
682         if (!sysfs_mtd) {
683                 if (errno == ENOENT) {
684                         errno = ENODEV;
685                         return -1;
686                 }
687                 return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd);
688         }
689
690         info->lowest_mtd_num = INT_MAX;
691         while (1) {
692                 int mtd_num, ret;
693                 char tmp_buf[256];
694
695                 errno = 0;
696                 dirent = readdir(sysfs_mtd);
697                 if (!dirent)
698                         break;
699
700                 if (strlen(dirent->d_name) >= 255) {
701                         errmsg("invalid entry in %s: \"%s\"",
702                                lib->sysfs_mtd, dirent->d_name);
703                         errno = EINVAL;
704                         goto out_close;
705                 }
706
707                 ret = sscanf(dirent->d_name, MTD_NAME_PATT"%s",
708                              &mtd_num, tmp_buf);
709                 if (ret == 1) {
710                         info->mtd_dev_cnt += 1;
711                         if (mtd_num > info->highest_mtd_num)
712                                 info->highest_mtd_num = mtd_num;
713                         if (mtd_num < info->lowest_mtd_num)
714                                 info->lowest_mtd_num = mtd_num;
715                 }
716         }
717
718         if (!dirent && errno) {
719                 sys_errmsg("readdir failed on \"%s\"", lib->sysfs_mtd);
720                 goto out_close;
721         }
722
723         if (closedir(sysfs_mtd))
724                 return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd);
725
726         if (info->lowest_mtd_num == INT_MAX)
727                 info->lowest_mtd_num = 0;
728
729         return 0;
730
731 out_close:
732         closedir(sysfs_mtd);
733         return -1;
734 }
735
736 int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd)
737 {
738         int ret;
739         struct libmtd *lib = (struct libmtd *)desc;
740
741         memset(mtd, 0, sizeof(struct mtd_dev_info));
742         mtd->mtd_num = mtd_num;
743
744         if (!mtd_dev_present(desc, mtd_num)) {
745                 errno = ENODEV;
746                 return -1;
747         } else if (!lib->sysfs_supported)
748                 return legacy_get_dev_info1(mtd_num, mtd);
749
750         if (dev_get_major(lib, mtd_num, &mtd->major, &mtd->minor))
751                 return -1;
752
753         ret = dev_read_data(lib->mtd_name, mtd_num, &mtd->name,
754                             MTD_NAME_MAX + 1);
755         if (ret < 0)
756                 return -1;
757         ((char *)mtd->name)[ret - 1] = '\0';
758
759         ret = dev_read_data(lib->mtd_type, mtd_num, &mtd->type_str,
760                             MTD_TYPE_MAX + 1);
761         if (ret < 0)
762                 return -1;
763         ((char *)mtd->type_str)[ret - 1] = '\0';
764
765         if (dev_read_pos_int(lib->mtd_eb_size, mtd_num, &mtd->eb_size))
766                 return -1;
767         if (dev_read_pos_ll(lib->mtd_size, mtd_num, &mtd->size))
768                 return -1;
769         if (dev_read_pos_int(lib->mtd_min_io_size, mtd_num, &mtd->min_io_size))
770                 return -1;
771         if (dev_read_pos_int(lib->mtd_subpage_size, mtd_num, &mtd->subpage_size))
772                 return -1;
773         if (dev_read_pos_int(lib->mtd_oob_size, mtd_num, &mtd->oob_size))
774                 return -1;
775         if (dev_read_pos_int(lib->mtd_region_cnt, mtd_num, &mtd->region_cnt))
776                 return -1;
777         if (dev_read_hex_int(lib->mtd_flags, mtd_num, &ret))
778                 return -1;
779         mtd->writable = !!(ret & MTD_WRITEABLE);
780
781         mtd->eb_cnt = mtd->size / mtd->eb_size;
782         mtd->type = type_str2int(mtd->type_str);
783         mtd->bb_allowed = !!(mtd->type == MTD_NANDFLASH ||
784                                 mtd->type == MTD_MLCNANDFLASH);
785
786         return 0;
787 }
788
789 int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
790 {
791         int mtd_num;
792         struct libmtd *lib = (struct libmtd *)desc;
793
794         if (!lib->sysfs_supported)
795                 return legacy_get_dev_info(node, mtd);
796
797         if (dev_node2num(lib, node, &mtd_num))
798                 return -1;
799
800         return mtd_get_dev_info1(desc, mtd_num, mtd);
801 }
802
803 static inline int mtd_ioctl_error(const struct mtd_dev_info *mtd, int eb,
804                                   const char *sreq)
805 {
806         return sys_errmsg("%s ioctl failed for eraseblock %d (mtd%d)",
807                           sreq, eb, mtd->mtd_num);
808 }
809
810 static int mtd_valid_erase_block(const struct mtd_dev_info *mtd, int eb)
811 {
812         if (eb < 0 || eb >= mtd->eb_cnt) {
813                 errmsg("bad eraseblock number %d, mtd%d has %d eraseblocks",
814                        eb, mtd->mtd_num, mtd->eb_cnt);
815                 errno = EINVAL;
816                 return -1;
817         }
818         return 0;
819 }
820
821 static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
822                      const char *sreq)
823 {
824         int ret;
825         struct erase_info_user ei;
826
827         ret = mtd_valid_erase_block(mtd, eb);
828         if (ret)
829                 return ret;
830
831         ei.start = eb * mtd->eb_size;
832         ei.length = mtd->eb_size;
833
834         ret = ioctl(fd, req, &ei);
835         if (ret < 0)
836                 return mtd_ioctl_error(mtd, eb, sreq);
837
838         return 0;
839 }
840 #define mtd_xlock(mtd, fd, eb, req) mtd_xlock(mtd, fd, eb, req, #req)
841
842 int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb)
843 {
844         return mtd_xlock(mtd, fd, eb, MEMLOCK);
845 }
846
847 int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb)
848 {
849         return mtd_xlock(mtd, fd, eb, MEMUNLOCK);
850 }
851
852 int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
853 {
854         int ret;
855         struct libmtd *lib = (struct libmtd *)desc;
856         struct erase_info_user64 ei64;
857         struct erase_info_user ei;
858
859         ret = mtd_valid_erase_block(mtd, eb);
860         if (ret)
861                 return ret;
862
863         ei64.start = (__u64)eb * mtd->eb_size;
864         ei64.length = mtd->eb_size;
865
866         if (lib->offs64_ioctls == OFFS64_IOCTLS_SUPPORTED ||
867             lib->offs64_ioctls == OFFS64_IOCTLS_UNKNOWN) {
868                 ret = ioctl(fd, MEMERASE64, &ei64);
869                 if (ret == 0)
870                         return ret;
871
872                 if (errno != ENOTTY ||
873                     lib->offs64_ioctls != OFFS64_IOCTLS_UNKNOWN)
874                         return mtd_ioctl_error(mtd, eb, "MEMERASE64");
875
876                 /*
877                  * MEMERASE64 support was added in kernel version 2.6.31, so
878                  * probably we are working with older kernel and this ioctl is
879                  * not supported.
880                  */
881                 lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED;
882         }
883
884         if (ei64.start + ei64.length > 0xFFFFFFFF) {
885                 errmsg("this system can address only %u eraseblocks",
886                        0xFFFFFFFFU / mtd->eb_size);
887                 errno = EINVAL;
888                 return -1;
889         }
890
891         ei.start = ei64.start;
892         ei.length = ei64.length;
893         ret = ioctl(fd, MEMERASE, &ei);
894         if (ret < 0)
895                 return mtd_ioctl_error(mtd, eb, "MEMERASE");
896         return 0;
897 }
898
899 int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo)
900 {
901         int ret;
902
903         if (regidx < 0) {
904                 errno = ENODEV;
905                 return -1;
906         }
907
908         reginfo->regionindex = regidx;
909
910         ret = ioctl(fd, MEMGETREGIONINFO, reginfo);
911         if (ret < 0)
912                 return sys_errmsg("%s ioctl failed for erase region %d",
913                         "MEMGETREGIONINFO", regidx);
914
915         return 0;
916 }
917
918 int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb)
919 {
920         int ret;
921         erase_info_t ei;
922
923         ei.start = eb * mtd->eb_size;
924         ei.length = mtd->eb_size;
925
926         ret = ioctl(fd, MEMISLOCKED, &ei);
927         if (ret < 0) {
928                 if (errno != ENOTTY && errno != EOPNOTSUPP)
929                         return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
930                 else
931                         errno = EOPNOTSUPP;
932         }
933
934         return ret;
935 }
936
937 /* Patterns to write to a physical eraseblock when torturing it */
938 static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
939
940 /**
941  * check_pattern - check if buffer contains only a certain byte pattern.
942  * @buf: buffer to check
943  * @patt: the pattern to check
944  * @size: buffer size in bytes
945  *
946  * This function returns %1 in there are only @patt bytes in @buf, and %0 if
947  * something else was also found.
948  */
949 static int check_pattern(const void *buf, uint8_t patt, int size)
950 {
951         int i;
952
953         for (i = 0; i < size; i++)
954                 if (((const uint8_t *)buf)[i] != patt)
955                         return 0;
956         return 1;
957 }
958
959 int mtd_torture(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
960 {
961         int err, i, patt_count;
962         void *buf;
963
964         normsg("run torture test for PEB %d", eb);
965         patt_count = FIO_ARRAY_SIZE(patterns);
966
967         buf = xmalloc(mtd->eb_size);
968
969         for (i = 0; i < patt_count; i++) {
970                 err = mtd_erase(desc, mtd, fd, eb);
971                 if (err)
972                         goto out;
973
974                 /* Make sure the PEB contains only 0xFF bytes */
975                 err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
976                 if (err)
977                         goto out;
978
979                 err = check_pattern(buf, 0xFF, mtd->eb_size);
980                 if (err == 0) {
981                         errmsg("erased PEB %d, but a non-0xFF byte found", eb);
982                         errno = EIO;
983                         goto out;
984                 }
985
986                 /* Write a pattern and check it */
987                 memset(buf, patterns[i], mtd->eb_size);
988                 err = mtd_write(desc, mtd, fd, eb, 0, buf, mtd->eb_size, NULL,
989                                 0, 0);
990                 if (err)
991                         goto out;
992
993                 memset(buf, ~patterns[i], mtd->eb_size);
994                 err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
995                 if (err)
996                         goto out;
997
998                 err = check_pattern(buf, patterns[i], mtd->eb_size);
999                 if (err == 0) {
1000                         errmsg("pattern %x checking failed for PEB %d",
1001                                 patterns[i], eb);
1002                         errno = EIO;
1003                         goto out;
1004                 }
1005         }
1006
1007         normsg("PEB %d passed torture test, do not mark it a bad", eb);
1008
1009 out:
1010         free(buf);
1011         return -1;
1012 }
1013
1014 int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb)
1015 {
1016         int ret;
1017         loff_t seek;
1018
1019         ret = mtd_valid_erase_block(mtd, eb);
1020         if (ret)
1021                 return ret;
1022
1023         if (!mtd->bb_allowed)
1024                 return 0;
1025
1026         seek = (loff_t)eb * mtd->eb_size;
1027         ret = ioctl(fd, MEMGETBADBLOCK, &seek);
1028         if (ret == -1)
1029                 return mtd_ioctl_error(mtd, eb, "MEMGETBADBLOCK");
1030         return ret;
1031 }
1032
1033 int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb)
1034 {
1035         int ret;
1036         loff_t seek;
1037
1038         if (!mtd->bb_allowed) {
1039                 errno = EINVAL;
1040                 return -1;
1041         }
1042
1043         ret = mtd_valid_erase_block(mtd, eb);
1044         if (ret)
1045                 return ret;
1046
1047         seek = (loff_t)eb * mtd->eb_size;
1048         ret = ioctl(fd, MEMSETBADBLOCK, &seek);
1049         if (ret == -1)
1050                 return mtd_ioctl_error(mtd, eb, "MEMSETBADBLOCK");
1051         return 0;
1052 }
1053
1054 int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
1055              void *buf, int len)
1056 {
1057         int ret, rd = 0;
1058         off_t seek;
1059
1060         ret = mtd_valid_erase_block(mtd, eb);
1061         if (ret)
1062                 return ret;
1063
1064         if (offs < 0 || offs + len > mtd->eb_size) {
1065                 errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d",
1066                        offs, len, mtd->mtd_num, mtd->eb_size);
1067                 errno = EINVAL;
1068                 return -1;
1069         }
1070
1071         /* Seek to the beginning of the eraseblock */
1072         seek = (off_t)eb * mtd->eb_size + offs;
1073         if (lseek(fd, seek, SEEK_SET) != seek)
1074                 return sys_errmsg("cannot seek mtd%d to offset %"PRIdoff_t,
1075                                   mtd->mtd_num, seek);
1076
1077         while (rd < len) {
1078                 ret = read(fd, buf, len);
1079                 if (ret < 0)
1080                         return sys_errmsg("cannot read %d bytes from mtd%d (eraseblock %d, offset %d)",
1081                                           len, mtd->mtd_num, eb, offs);
1082                 rd += ret;
1083         }
1084
1085         return 0;
1086 }
1087
1088 static int legacy_auto_oob_layout(const struct mtd_dev_info *mtd, int fd,
1089                                   int ooblen, void *oob) {
1090         struct nand_oobinfo old_oobinfo;
1091         int start, len;
1092         uint8_t *tmp_buf;
1093
1094         /* Read the current oob info */
1095         if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo))
1096                 return sys_errmsg("MEMGETOOBSEL failed");
1097
1098         tmp_buf = malloc(ooblen);
1099         memcpy(tmp_buf, oob, ooblen);
1100
1101         /*
1102          * We use autoplacement and have the oobinfo with the autoplacement
1103          * information from the kernel available
1104          */
1105         if (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
1106                 int i, tags_pos = 0;
1107                 for (i = 0; old_oobinfo.oobfree[i][1]; i++) {
1108                         /* Set the reserved bytes to 0xff */
1109                         start = old_oobinfo.oobfree[i][0];
1110                         len = old_oobinfo.oobfree[i][1];
1111                         memcpy(oob + start, tmp_buf + tags_pos, len);
1112                         tags_pos += len;
1113                 }
1114         } else {
1115                 /* Set at least the ecc byte positions to 0xff */
1116                 start = old_oobinfo.eccbytes;
1117                 len = mtd->oob_size - start;
1118                 memcpy(oob + start, tmp_buf + start, len);
1119         }
1120         free(tmp_buf);
1121
1122         return 0;
1123 }
1124
1125 int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb,
1126               int offs, void *data, int len, void *oob, int ooblen,
1127               uint8_t mode)
1128 {
1129         int ret;
1130         off_t seek;
1131         struct mtd_write_req ops;
1132
1133         ret = mtd_valid_erase_block(mtd, eb);
1134         if (ret)
1135                 return ret;
1136
1137         if (offs < 0 || offs + len > mtd->eb_size) {
1138                 errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d",
1139                        offs, len, mtd->mtd_num, mtd->eb_size);
1140                 errno = EINVAL;
1141                 return -1;
1142         }
1143         if (offs % mtd->subpage_size) {
1144                 errmsg("write offset %d is not aligned to mtd%d min. I/O size %d",
1145                        offs, mtd->mtd_num, mtd->subpage_size);
1146                 errno = EINVAL;
1147                 return -1;
1148         }
1149         if (len % mtd->subpage_size) {
1150                 errmsg("write length %d is not aligned to mtd%d min. I/O size %d",
1151                        len, mtd->mtd_num, mtd->subpage_size);
1152                 errno = EINVAL;
1153                 return -1;
1154         }
1155
1156         /* Calculate seek address */
1157         seek = (off_t)eb * mtd->eb_size + offs;
1158
1159         if (oob) {
1160                 ops.start = seek;
1161                 ops.len = len;
1162                 ops.ooblen = ooblen;
1163                 ops.usr_data = (uint64_t)(unsigned long)data;
1164                 ops.usr_oob = (uint64_t)(unsigned long)oob;
1165                 ops.mode = mode;
1166
1167                 ret = ioctl(fd, MEMWRITE, &ops);
1168                 if (ret == 0)
1169                         return 0;
1170                 else if (errno != ENOTTY && errno != EOPNOTSUPP)
1171                         return mtd_ioctl_error(mtd, eb, "MEMWRITE");
1172
1173                 /* Fall back to old OOB ioctl() if necessary */
1174                 if (mode == MTD_OPS_AUTO_OOB)
1175                         if (legacy_auto_oob_layout(mtd, fd, ooblen, oob))
1176                                 return -1;
1177                 if (mtd_write_oob(desc, mtd, fd, seek, ooblen, oob) < 0)
1178                         return sys_errmsg("cannot write to OOB");
1179         }
1180         if (data) {
1181                 /* Seek to the beginning of the eraseblock */
1182                 if (lseek(fd, seek, SEEK_SET) != seek)
1183                         return sys_errmsg("cannot seek mtd%d to offset %"PRIdoff_t,
1184                                         mtd->mtd_num, seek);
1185                 ret = write(fd, data, len);
1186                 if (ret != len)
1187                         return sys_errmsg("cannot write %d bytes to mtd%d "
1188                                           "(eraseblock %d, offset %d)",
1189                                           len, mtd->mtd_num, eb, offs);
1190         }
1191
1192         return 0;
1193 }
1194
1195 static int do_oob_op(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
1196               uint64_t start, uint64_t length, void *data, unsigned int cmd64,
1197               unsigned int cmd)
1198 {
1199         int ret, oob_offs;
1200         struct mtd_oob_buf64 oob64;
1201         struct mtd_oob_buf oob;
1202         unsigned long long max_offs;
1203         const char *cmd64_str, *cmd_str;
1204         struct libmtd *lib = (struct libmtd *)desc;
1205
1206         if (cmd64 ==  MEMREADOOB64) {
1207                 cmd64_str = "MEMREADOOB64";
1208                 cmd_str   = "MEMREADOOB";
1209         } else {
1210                 cmd64_str = "MEMWRITEOOB64";
1211                 cmd_str   = "MEMWRITEOOB";
1212         }
1213
1214         max_offs = (unsigned long long)mtd->eb_cnt * mtd->eb_size;
1215         if (start >= max_offs) {
1216                 errmsg("bad page address %" PRIu64 ", mtd%d has %d eraseblocks (%llu bytes)",
1217                        start, mtd->mtd_num, mtd->eb_cnt, max_offs);
1218                 errno = EINVAL;
1219                 return -1;
1220         }
1221
1222         oob_offs = start & (mtd->min_io_size - 1);
1223         if (oob_offs + length > mtd->oob_size || length == 0) {
1224                 errmsg("Cannot write %" PRIu64 " OOB bytes to address %" PRIu64 " (OOB offset %u) - mtd%d OOB size is only %d bytes",
1225                        length, start, oob_offs, mtd->mtd_num,  mtd->oob_size);
1226                 errno = EINVAL;
1227                 return -1;
1228         }
1229
1230         oob64.start = start;
1231         oob64.length = length;
1232         oob64.usr_ptr = (uint64_t)(unsigned long)data;
1233
1234         if (lib->offs64_ioctls == OFFS64_IOCTLS_SUPPORTED ||
1235             lib->offs64_ioctls == OFFS64_IOCTLS_UNKNOWN) {
1236                 ret = ioctl(fd, cmd64, &oob64);
1237                 if (ret == 0)
1238                         return ret;
1239
1240                 if (errno != ENOTTY ||
1241                     lib->offs64_ioctls != OFFS64_IOCTLS_UNKNOWN) {
1242                         sys_errmsg("%s ioctl failed for mtd%d, offset %" PRIu64 " (eraseblock %" PRIu64 ")",
1243                                    cmd64_str, mtd->mtd_num, start, start / mtd->eb_size);
1244                 }
1245
1246                 /*
1247                  * MEMREADOOB64/MEMWRITEOOB64 support was added in kernel
1248                  * version 2.6.31, so probably we are working with older kernel
1249                  * and these ioctls are not supported.
1250                  */
1251                 lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED;
1252         }
1253
1254         if (oob64.start > 0xFFFFFFFFULL) {
1255                 errmsg("this system can address only up to address %lu",
1256                        0xFFFFFFFFUL);
1257                 errno = EINVAL;
1258                 return -1;
1259         }
1260
1261         oob.start = oob64.start;
1262         oob.length = oob64.length;
1263         oob.ptr = data;
1264
1265         ret = ioctl(fd, cmd, &oob);
1266         if (ret < 0)
1267                 sys_errmsg("%s ioctl failed for mtd%d, offset %" PRIu64 " (eraseblock %" PRIu64 ")",
1268                            cmd_str, mtd->mtd_num, start, start / mtd->eb_size);
1269         return ret;
1270 }
1271
1272 int mtd_read_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
1273                  uint64_t start, uint64_t length, void *data)
1274 {
1275         return do_oob_op(desc, mtd, fd, start, length, data,
1276                          MEMREADOOB64, MEMREADOOB);
1277 }
1278
1279 int mtd_write_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
1280                   uint64_t start, uint64_t length, void *data)
1281 {
1282         return do_oob_op(desc, mtd, fd, start, length, data,
1283                          MEMWRITEOOB64, MEMWRITEOOB);
1284 }
1285
1286 int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
1287                   const char *img_name)
1288 {
1289         int tmp, ret, in_fd, len, written = 0;
1290         off_t seek;
1291         struct stat st;
1292         char *buf;
1293
1294         ret = mtd_valid_erase_block(mtd, eb);
1295         if (ret)
1296                 return ret;
1297
1298         if (offs < 0 || offs >= mtd->eb_size) {
1299                 errmsg("bad offset %d, mtd%d eraseblock size is %d",
1300                        offs, mtd->mtd_num, mtd->eb_size);
1301                 errno = EINVAL;
1302                 return -1;
1303         }
1304         if (offs % mtd->subpage_size) {
1305                 errmsg("write offset %d is not aligned to mtd%d min. I/O size %d",
1306                        offs, mtd->mtd_num, mtd->subpage_size);
1307                 errno = EINVAL;
1308                 return -1;
1309         }
1310
1311         in_fd = open(img_name, O_RDONLY | O_CLOEXEC);
1312         if (in_fd == -1)
1313                 return sys_errmsg("cannot open \"%s\"", img_name);
1314
1315         if (fstat(in_fd, &st)) {
1316                 sys_errmsg("cannot stat %s", img_name);
1317                 goto out_close;
1318         }
1319
1320         len = st.st_size;
1321         if (len % mtd->subpage_size) {
1322                 errmsg("size of \"%s\" is %d byte, which is not aligned to "
1323                        "mtd%d min. I/O size %d", img_name, len, mtd->mtd_num,
1324                        mtd->subpage_size);
1325                 errno = EINVAL;
1326                 goto out_close;
1327         }
1328         tmp = (offs + len + mtd->eb_size - 1) / mtd->eb_size;
1329         if (eb + tmp > mtd->eb_cnt) {
1330                 errmsg("\"%s\" image size is %d bytes, mtd%d size is %d "
1331                        "eraseblocks, the image does not fit if we write it "
1332                        "starting from eraseblock %d, offset %d",
1333                        img_name, len, mtd->mtd_num, mtd->eb_cnt, eb, offs);
1334                 errno = EINVAL;
1335                 goto out_close;
1336         }
1337
1338         /* Seek to the beginning of the eraseblock */
1339         seek = (off_t)eb * mtd->eb_size + offs;
1340         if (lseek(fd, seek, SEEK_SET) != seek) {
1341                 sys_errmsg("cannot seek mtd%d to offset %"PRIdoff_t,
1342                             mtd->mtd_num, seek);
1343                 goto out_close;
1344         }
1345
1346         buf = xmalloc(mtd->eb_size);
1347
1348         while (written < len) {
1349                 int rd = 0;
1350
1351                 do {
1352                         ret = read(in_fd, buf, mtd->eb_size - offs - rd);
1353                         if (ret == -1) {
1354                                 sys_errmsg("cannot read \"%s\"", img_name);
1355                                 goto out_free;
1356                         }
1357                         rd += ret;
1358                 } while (ret && rd < mtd->eb_size - offs);
1359
1360                 ret = write(fd, buf, rd);
1361                 if (ret != rd) {
1362                         sys_errmsg("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)",
1363                                    len, mtd->mtd_num, eb, offs);
1364                         goto out_free;
1365                 }
1366
1367                 offs = 0;
1368                 eb += 1;
1369                 written += rd;
1370         }
1371
1372         free(buf);
1373         close(in_fd);
1374         return 0;
1375
1376 out_free:
1377         free(buf);
1378 out_close:
1379         close(in_fd);
1380         return -1;
1381 }
1382
1383 int mtd_probe_node(libmtd_t desc, const char *node)
1384 {
1385         struct stat st;
1386         struct mtd_info info;
1387         int i, mjr, mnr;
1388         struct libmtd *lib = (struct libmtd *)desc;
1389
1390         if (stat(node, &st))
1391                 return sys_errmsg("cannot get information about \"%s\"", node);
1392
1393         if (!S_ISCHR(st.st_mode)) {
1394                 errmsg("\"%s\" is not a character device", node);
1395                 errno = EINVAL;
1396                 return -1;
1397         }
1398
1399         mjr = major(st.st_rdev);
1400         mnr = minor(st.st_rdev);
1401
1402         if (mtd_get_info((libmtd_t *)lib, &info))
1403                 return -1;
1404
1405         if (!lib->sysfs_supported)
1406                 return 0;
1407
1408         for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) {
1409                 int mjr1, mnr1, ret;
1410
1411                 ret = dev_get_major(lib, i, &mjr1, &mnr1);
1412                 if (ret) {
1413                         if (errno == ENOENT)
1414                                 continue;
1415                         if (!errno)
1416                                 break;
1417                         return -1;
1418                 }
1419
1420                 if (mjr1 == mjr && mnr1 == mnr)
1421                         return 1;
1422         }
1423
1424         errno = 0;
1425         return -1;
1426 }