[][OpenWrt Dev][Add option for NMBM to support running in read-only mode]

[Description]
Add an option to allow NMBM running in read-only where only read operation
is accepted, and write/erase operation will be rejected.

With this option turned on, NMBM will write no signature block nor any
information table into NAND flash, which allows lower write/erase API
not being provided.

[Release-log]
N/A

Change-Id: Ia6931b073d2d56f722284c0b894e30551cd7c359
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/4672347
diff --git a/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c b/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
index 009b82e..18dfb6a 100644
--- a/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
+++ b/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
@@ -238,6 +238,11 @@
 {
 	int tries, ret;
 
+	if (ni->lower.flags & NMBM_F_READ_ONLY) {
+		nlog_err(ni, "%s called with NMBM_F_READ_ONLY set\n", addr);
+		return false;
+	}
+
 	for (tries = 0; tries < NMBM_TRY_COUNT; tries++) {
 		ret = ni->lower.write_page(ni->lower.arg, addr, data, oob, mode);
 		if (!ret)
@@ -262,6 +267,11 @@
 {
 	int tries, ret;
 
+	if (ni->lower.flags & NMBM_F_READ_ONLY) {
+		nlog_err(ni, "%s called with NMBM_F_READ_ONLY set\n", addr);
+		return false;
+	}
+
 	for (tries = 0; tries < NMBM_TRY_COUNT; tries++) {
 		ret = ni->lower.erase_block(ni->lower.arg, addr);
 		if (!ret)
@@ -309,6 +319,11 @@
 	enum nmbm_log_category level;
 	uint32_t off;
 
+	if (ni->lower.flags & NMBM_F_READ_ONLY) {
+		nlog_err(ni, "%s called with NMBM_F_READ_ONLY set\n", addr);
+		return false;
+	}
+
 	nlog_info(ni, "Block %u [0x%08llx] will be marked bad\n", ba, addr);
 
 	if (ni->lower.mark_bad_block)
@@ -1684,6 +1699,11 @@
 	ni->signature.max_try_count = NMBM_TRY_COUNT;
 	nmbm_update_checksum(&ni->signature.header);
 
+	if (ni->lower.flags & NMBM_F_READ_ONLY) {
+		nlog_info(ni, "NMBM has been initialized in read-only mode\n");
+		return true;
+	}
+
 	success = nmbm_write_signature(ni, ni->mgmt_start_ba,
 				       &ni->signature, &ni->signature_ba);
 	if (!success) {
@@ -1985,6 +2005,9 @@
 	/* Regenerate the info table cache from the final selected info table */
 	nmbm_generate_info_table_cache(ni);
 
+	if (ni->lower.flags & NMBM_F_READ_ONLY)
+		return true;
+
 	/*
 	 * If only one table exists, try to write another table.
 	 * If two tables have different write count, try to update info table
@@ -2037,7 +2060,8 @@
 	success = nmbm_load_info_table(ni, ni->mgmt_start_ba,
 		ni->signature_ba);
 	if (success) {
-		nlog_info(ni, "NMBM has been successfully attached\n");
+		nlog_info(ni, "NMBM has been successfully attached %s\n",
+			  (ni->lower.flags & NMBM_F_READ_ONLY) ? "in read-only mode" : "");
 		return true;
 	}
 
@@ -2048,6 +2072,11 @@
 	nmbm_scan_badblocks(ni);
 	nmbm_build_mapping_table(ni);
 
+	if (ni->lower.flags & NMBM_F_READ_ONLY) {
+		nlog_info(ni, "NMBM has been initialized in read-only mode\n");
+		return true;
+	}
+
 	/* Write info table(s) */
 	success = nmbm_create_info_table(ni);
 	if (success) {
@@ -2166,9 +2195,14 @@
 		return false;
 	}
 
+	if (!nld->read_page) {
+		nmbm_log_lower(nld, NMBM_LOG_ERR, "read_page() is required\n");
+		return false;
+	}
+
-	if (!nld->read_page || !nld->write_page || !nld->erase_block) {
+	if (!(nld->flags & NMBM_F_READ_ONLY) && (!nld->write_page || !nld->erase_block)) {
 		nmbm_log_lower(nld, NMBM_LOG_ERR,
-			       "read_page(), write_page() and erase_block() are required\n");
+			       "write_page() and erase_block() are required\n");
 		return false;
 	}
 
@@ -2355,7 +2389,8 @@
 	if (!ni)
 		return -EINVAL;
 
-	nmbm_update_info_table(ni);
+	if (!(ni->lower.flags & NMBM_F_READ_ONLY))
+		nmbm_update_info_table(ni);
 
 	nmbm_mark_block_color_normal(ni, 0, ni->block_count - 1);
 
@@ -2443,7 +2478,7 @@
 		return -EINVAL;
 
 	/* Sanity check */
-	if (ni->protected) {
+	if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) {
 		nlog_debug(ni, "Device is forced read-only\n");
 		return -EROFS;
 	}
@@ -2710,7 +2745,7 @@
 		return -EINVAL;
 
 	/* Sanity check */
-	if (ni->protected) {
+	if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) {
 		nlog_debug(ni, "Device is forced read-only\n");
 		return -EROFS;
 	}
@@ -2745,7 +2780,7 @@
 		return -EINVAL;
 
 	/* Sanity check */
-	if (ni->protected) {
+	if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) {
 		nlog_debug(ni, "Device is forced read-only\n");
 		return -EROFS;
 	}
@@ -2843,6 +2878,12 @@
 	if (!ni)
 		return -EINVAL;
 
+	/* Sanity check */
+	if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) {
+		nlog_debug(ni, "Device is forced read-only\n");
+		return -EROFS;
+	}
+
 	if (addr >= ba2addr(ni, ni->data_block_count)) {
 		nlog_err(ni, "Address 0x%llx is invalid\n", addr);
 		return -EINVAL;