1// SPDX-License-Identifier: GPL-2.0+
2
3#include <common.h>
4#include <jffs2/jffs2.h>
5#include <linux/mtd/mtd.h>
6#include <linux/mtd/partitions.h>
7#include <linux/string.h>
8#include <mtd.h>
9
10static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
11	     loff_t *maxsize, int devtype)
12{
13#ifdef CONFIG_CMD_MTDPARTS
14	struct mtd_device *dev;
15	struct part_info *part;
16	u8 pnum;
17	int ret;
18
19	ret = mtdparts_init();
20	if (ret)
21		return ret;
22
23	ret = find_dev_and_part(partname, &dev, &pnum, &part);
24	if (ret)
25		return ret;
26
27	if (dev->id->type != devtype) {
28		printf("not same typ %d != %d\n", dev->id->type, devtype);
29		return -1;
30	}
31
32	*off = part->offset;
33	*size = part->size;
34	*maxsize = part->size;
35	*idx = dev->id->num;
36
37	return 0;
38#else
39	puts("mtdparts support missing.\n");
40	return -1;
41#endif
42}
43
44int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
45		loff_t *maxsize, int devtype, uint64_t chipsize)
46{
47	if (!str2off(arg, off))
48		return get_part(arg, idx, off, size, maxsize, devtype);
49
50	if (*off >= chipsize) {
51		puts("Offset exceeds device limit\n");
52		return -1;
53	}
54
55	*maxsize = chipsize - *off;
56	*size = *maxsize;
57	return 0;
58}
59
60int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
61		     loff_t *size, loff_t *maxsize, int devtype,
62		     uint64_t chipsize)
63{
64	int ret;
65
66	if (argc == 0) {
67		*off = 0;
68		*size = chipsize;
69		*maxsize = *size;
70		goto print;
71	}
72
73	ret = mtd_arg_off(argv[0], idx, off, size, maxsize, devtype,
74			  chipsize);
75	if (ret)
76		return ret;
77
78	if (argc == 1)
79		goto print;
80
81	if (!str2off(argv[1], size)) {
82		printf("'%s' is not a number\n", argv[1]);
83		return -1;
84	}
85
86	if (*size > *maxsize) {
87		puts("Size exceeds partition or device limit\n");
88		return -1;
89	}
90
91	if (*size == 0) {
92		debug("ERROR: Invalid size 0\n");
93		return -1;
94	}
95
96print:
97	printf("device %d ", *idx);
98	if (*size == chipsize)
99		puts("whole chip\n");
100	else
101		printf("offset 0x%llx, size 0x%llx\n",
102		       (unsigned long long)*off, (unsigned long long)*size);
103	return 0;
104}
105