[PATCH 4/4] Add support for bad and weak blocks/pages

Daniel Walter dwalter at sigma-star.at
Wed Aug 31 00:32:44 PDT 2016


Added new flag to support the creation
of badblocks, weakblocks, weakpages, and gravepages.

example:
./nandsimctl -B 0x100,0x200 -W 0x101:100,0x202:1200 -r

Signed-off-by: Daniel Walter <dwalter at sigma-star.at>
---
 nand-utils/nandsimctl.c | 159 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 136 insertions(+), 23 deletions(-)

diff --git a/nand-utils/nandsimctl.c b/nand-utils/nandsimctl.c
index 78ef1ff..e6043d5 100644
--- a/nand-utils/nandsimctl.c
+++ b/nand-utils/nandsimctl.c
@@ -23,13 +23,18 @@ enum action {
 
 static const struct option long_options[] = {
 	/* ordering of these is important, do not change */
-	{ .name = "version",	.has_arg = 0, .flag = NULL, .val = 0},
-	{ .name = "backend",	.has_arg = 1, .flag = NULL, .val = 'b' },
-	{ .name = "id",		.has_arg = 1, .flag = NULL, .val = 'i' },
-	{ .name = "detach",	.has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "detach-all",	.has_arg = 0, .flag = NULL, .val = 'D' },
-	{ .name = "no-oob",	.has_arg = 0, .flag = NULL, .val = 'n' },
-	{ .name = "help",	.has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",		.has_arg = 0, .flag = NULL, .val = 0},
+	{ .name = "backend",		.has_arg = 1, .flag = NULL, .val = 'b' },
+	{ .name = "id",			.has_arg = 1, .flag = NULL, .val = 'i' },
+	{ .name = "detach",		.has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "detach-all",		.has_arg = 0, .flag = NULL, .val = 'D' },
+	{ .name = "no-oob",		.has_arg = 0, .flag = NULL, .val = 'n' },
+	{ .name = "bad-blocks",		.has_arg = 1, .flag = NULL, .val = 'B' },
+	{ .name = "weak-blocks",	.has_arg = 1, .flag = NULL, .val = 'W' },
+	{ .name = "grave-pages",	.has_arg = 1, .flag = NULL, .val = 'G' },
+	{ .name = "weak-pages",		.has_arg = 1, .flag = NULL, .val = 'P' },
+	{ .name = "help",		.has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "wide-addr",		.has_arg = 0, .flag = NULL, .val = 'w' },
 	{ NULL, 0, NULL, 0},
 };
 
@@ -44,6 +49,14 @@ static struct {
 	enum action act;
 	int detach;
 	bool detach_all;
+	struct ns_simelement_prop *bad_blocks;
+	struct ns_simelement_prop *weak_blocks;
+	struct ns_simelement_prop *weak_pages;
+	struct ns_simelement_prop *grave_pages;
+	size_t len_bad_blocks;
+	size_t len_weak_blocks;
+	size_t len_weak_pages;
+	size_t len_grave_pages;
 } args = {
 	.backend = -1,
 	.detach = -1,
@@ -55,6 +68,14 @@ static struct {
 	},
 	.backing_file = NULL,
 	.no_oob = false,
+	.bad_blocks = NULL,
+	.weak_blocks = NULL,
+	.weak_pages = NULL,
+	.grave_pages = NULL,
+	.len_bad_blocks = 0,
+	.len_weak_blocks = 0,
+	.len_weak_pages = 0,
+	.len_grave_pages = 0,
 };
 
 static int do_help(int status)
@@ -70,6 +91,11 @@ static int do_help(int status)
 "  -c, --backend=cache               Use cached backend\n"
 "  -f, --backend=file                Use file backend\n"
 "  -n, --no-oob                      Disable OOB data\n"
+"  -w, --wide-addr                   Use wide addressing\n"
+"  -B, --bad-blocks=id,...           List of Bad Block IDs\n"
+"  -W, --weak-blocks=id:erases,...   List of Weak Block IDs and the number of maximum erases\n"
+"  -G, --grave-pages=id:reads,...    List of Grave Page IDs and the number of maximum reads\n"
+"  -P, --weak-pages=id:writes,...    List of Weak Page IDs and the number of maximum writes\n"
 "  -q, --quiet                       Don't display progress messages\n"
 "  -h, --help                        Display this help and exit\n"
 "      --version                     Output version information and exit\n"
@@ -97,7 +123,7 @@ static int parse_args(int argc, char *argv[])
 	int option_index;
 
 	for (;;) {
-		key = getopt_long(argc, argv, "b:i:h?rcfwod:Dn", long_options, &option_index);
+		key = getopt_long(argc, argv, "b:i:h?rcfwod:DnW:B:P:G:", long_options, &option_index);
 		if (key == -1)
 			break;
 
@@ -167,6 +193,60 @@ static int parse_args(int argc, char *argv[])
 			if (args.detach < 0 || args.detach >= NANDSIM_MAX_DEVICES)
 				return errmsg("bad instance number to detach");
 		break;
+		case 'B':
+		case 'W':
+		case 'P':
+		case 'G':
+		{
+			char *tmparg = xstrdup(optarg);
+			char *tmp = xstrdup(optarg);
+			char *t = NULL;
+			int ctr = 0;
+			size_t arr_size = 0;
+			uint32_t id = 0;
+			int32_t elem_type;
+			struct ns_simelement_prop *ids = NULL;
+
+			for (arr_size=0; tmp[arr_size]; tmp[arr_size]==',' ? arr_size++ : *tmp++);
+			arr_size++;
+			ids = xcalloc(arr_size, sizeof(struct ns_simelement_prop));
+
+			if (key == 'B') {
+				elem_type = NANDSIM_SIMELEM_BADBLOCK;
+				args.bad_blocks = ids;
+				args.len_bad_blocks = arr_size;
+			} else if (key == 'W') {
+				elem_type = NANDSIM_SIMELEM_WEAKBLOCK;
+				args.weak_blocks = ids;
+				args.len_weak_blocks = arr_size;
+			} else if (key == 'P') {
+				elem_type = NANDSIM_SIMELEM_WEAKPAGE;
+				args.weak_pages = ids;
+				args.len_weak_pages = arr_size;
+			} else {
+				elem_type = NANDSIM_SIMELEM_GRAVEPAGE;
+				args.grave_pages = ids;
+				args.len_grave_pages = arr_size;
+			}
+
+			tmp = strtok(tmparg, ",");
+			while (tmp) {
+				if (ctr >= arr_size)
+					break;
+				t = strchr(tmp, ':');
+				if (t) {
+					*t = '\0';
+					t++;
+					ids[ctr].elem_attr = strtoul(t, NULL, 10);
+				}
+				id = strtoul(tmp, NULL, 16);
+				ids[ctr].elem_id = id;
+				ids[ctr].elem_type = elem_type;
+				tmp = strtok(NULL, ",");
+				ctr++;
+			}
+		}
+		break;
 		case 'D':
 			args.detach_all = true;
 		break;
@@ -262,36 +342,69 @@ static int get_temp_file_fd(void)
 
 static int do_attach(void)
 {
-	struct ns_new_instance_req req;
-	int i, ret, fd = 0;
+	uint8_t *tmp_ptr = NULL;
+	struct ns_new_instance_req *req;
+	int i, ret = -1, fd = 0;
+	size_t tmp_sz = 0;
+	size_t sim_elem = args.len_bad_blocks + args.len_weak_blocks + args.len_weak_pages + args.len_grave_pages;
+	size_t req_size = sizeof(*req) + (sizeof(struct ns_simelement_prop) * sim_elem);
+	req = xmalloc(req_size);
 
 	if (args.backend == NANDSIM_BACKEND_CACHEFILE) {
 		fd = get_temp_file_fd();
 		if (fd < 0)
-			return fd;
+			goto out;
 	} else if (args.backend == NANDSIM_BACKEND_FILE) {
 		fd = open(args.backing_file, O_RDWR | O_LARGEFILE | O_CLOEXEC);
-		if (fd == -1)
-			return sys_errmsg("unable to open \"%s\"", args.backing_file);
+		if (fd == -1) {
+			sys_errmsg("unable to open \"%s\"", args.backing_file);
+			ret = -1;
+			goto out;
+		}
 	} else
 		args.backend = NANDSIM_BACKEND_RAM;
 
-	memset(&req, 0, sizeof(req));
+	memset(req, 0, req_size);
 
-	req.backend = args.backend;
-	req.bus_width = args.wide_addr ? 16 : 8;
-	req.no_oob = !!args.no_oob;
+	req->backend = args.backend;
+	req->bus_width = args.wide_addr ? 16 : 8;
+	req->no_oob = !!args.no_oob;
 	for (i = 0; i < 8; i++)
-		req.id_bytes[i] = args.id[i] & 0xff;
-	req.file_fd = fd;
+		req->id_bytes[i] = args.id[i] & 0xff;
+	req->file_fd = fd;
+	req->simelem_num = sim_elem;
+
+	tmp_ptr = (uint8_t*)req;
+	tmp_ptr += sizeof(*req);
+	if (args.len_bad_blocks) {
+		tmp_sz = args.len_bad_blocks * sizeof(struct ns_simelement_prop);
+		memcpy(tmp_ptr, args.bad_blocks, tmp_sz);
+		tmp_ptr += tmp_sz;
+	}
+	if (args.len_weak_blocks) {
+		tmp_sz = args.len_weak_blocks * sizeof(struct ns_simelement_prop);
+		memcpy(tmp_ptr, args.weak_blocks, tmp_sz);
+		tmp_ptr += tmp_sz;
+	}
+	if (args.len_weak_pages) {
+		tmp_sz = args.len_weak_pages * sizeof(struct ns_simelement_prop);
+		memcpy(tmp_ptr, args.weak_pages, tmp_sz);
+		tmp_ptr += tmp_sz;
+	}
+	if (args.len_grave_pages) {
+		tmp_sz = args.len_grave_pages * sizeof(struct ns_simelement_prop);
+		memcpy(tmp_ptr, args.grave_pages, tmp_sz);
+		tmp_ptr += tmp_sz;
+	}
 
-	ret = ioctl(ctrl_fd, NANDSIM_IOC_NEW_INSTANCE, &req);
+	ret = ioctl(ctrl_fd, NANDSIM_IOC_NEW_INSTANCE, req);
 	if (ret < 0) {
 		sys_errmsg("unable to create new nandsim instance");
-		return ret;
+		goto out;
 	}
-
-	return 0;
+out:
+	free(req);
+	return ret;
 }
 
 static int do_info(int id)
-- 
2.8.3




More information about the linux-mtd mailing list