mtd: docg3: add protection areas sysfs access

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Mon Jan 9 13:59:04 EST 2012


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=0f769d3f9e2ef3e88930ff190a20cfbfe6206d3a
Commit:     0f769d3f9e2ef3e88930ff190a20cfbfe6206d3a
Parent:     c3de8a8a5a28603f8d318245992dbcda2e88a007
Author:     Robert Jarzmik <robert.jarzmik at free.fr>
AuthorDate: Sat Nov 19 16:02:58 2011 +0100
Committer:  David Woodhouse <David.Woodhouse at intel.com>
CommitDate: Mon Jan 9 18:07:30 2012 +0000

    mtd: docg3: add protection areas sysfs access
    
    As each docg3 chip has 2 protection areas (DPS0 and DPS1),
    and because theses areas can prevent user access to the chip
    data, add for each floor the sysfs entries which insert the
    protection key into the right DPS.
    
    Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
    Reviewed-by: Ivan Djelic <ivan.djelic at parrot.com>
    Reviewed-by: Mike Dunn <mikedunn at newsguy.com>
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
 drivers/mtd/devices/docg3.c |  121 +++++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/devices/docg3.h |   13 +++++
 2 files changed, 134 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 35df377..d7df311 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -1513,6 +1513,123 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
 	return ret;
 }
 
+static struct docg3 *sysfs_dev2docg3(struct device *dev,
+				     struct device_attribute *attr)
+{
+	int floor;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
+
+	floor = attr->attr.name[1] - '0';
+	if (floor < 0 || floor >= DOC_MAX_NBFLOORS)
+		return NULL;
+	else
+		return docg3_floors[floor]->priv;
+}
+
+static ssize_t dps0_is_key_locked(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
+	int dps0;
+
+	doc_set_device_id(docg3, docg3->device_id);
+	dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
+	doc_set_device_id(docg3, 0);
+
+	return sprintf(buf, "%d\n", !(dps0 & DOC_DPS_KEY_OK));
+}
+
+static ssize_t dps1_is_key_locked(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
+	int dps1;
+
+	doc_set_device_id(docg3, docg3->device_id);
+	dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
+	doc_set_device_id(docg3, 0);
+
+	return sprintf(buf, "%d\n", !(dps1 & DOC_DPS_KEY_OK));
+}
+
+static ssize_t dps0_insert_key(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
+	int i;
+
+	if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
+		return -EINVAL;
+
+	doc_set_device_id(docg3, docg3->device_id);
+	for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
+		doc_writeb(docg3, buf[i], DOC_DPS0_KEY);
+	doc_set_device_id(docg3, 0);
+	return count;
+}
+
+static ssize_t dps1_insert_key(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
+	int i;
+
+	if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
+		return -EINVAL;
+
+	doc_set_device_id(docg3, docg3->device_id);
+	for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
+		doc_writeb(docg3, buf[i], DOC_DPS1_KEY);
+	doc_set_device_id(docg3, 0);
+	return count;
+}
+
+#define FLOOR_SYSFS(id) { \
+	__ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \
+	__ATTR(f##id##_dps1_is_keylocked, S_IRUGO, dps1_is_key_locked, NULL), \
+	__ATTR(f##id##_dps0_protection_key, S_IWUGO, NULL, dps0_insert_key), \
+	__ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_insert_key), \
+}
+
+static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
+	FLOOR_SYSFS(0), FLOOR_SYSFS(1), FLOOR_SYSFS(2), FLOOR_SYSFS(3)
+};
+
+static int doc_register_sysfs(struct platform_device *pdev,
+			      struct mtd_info **floors)
+{
+	int ret = 0, floor, i = 0;
+	struct device *dev = &pdev->dev;
+
+	for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor];
+	     floor++)
+		for (i = 0; !ret && i < 4; i++)
+			ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
+	if (!ret)
+		return 0;
+	do {
+		while (--i >= 0)
+			device_remove_file(dev, &doc_sys_attrs[floor][i]);
+		i = 4;
+	} while (--floor >= 0);
+	return ret;
+}
+
+static void doc_unregister_sysfs(struct platform_device *pdev,
+				 struct mtd_info **floors)
+{
+	struct device *dev = &pdev->dev;
+	int floor, i;
+
+	for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor];
+	     floor++)
+		for (i = 0; i < 4; i++)
+			device_remove_file(dev, &doc_sys_attrs[floor][i]);
+}
+
 /*
  * Debug sysfs entries
  */
@@ -1927,6 +2044,9 @@ static int __init docg3_probe(struct platform_device *pdev)
 			found++;
 	}
 
+	ret = doc_register_sysfs(pdev, docg3_floors);
+	if (ret)
+		goto err_probe;
 	if (!found)
 		goto notfound;
 
@@ -1963,6 +2083,7 @@ static int __exit docg3_release(struct platform_device *pdev)
 	void __iomem *base = docg3->base;
 	int floor;
 
+	doc_unregister_sysfs(pdev, docg3_floors);
 	doc_dbg_unregister(docg3);
 	for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
 		if (docg3_floors[floor])
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h
index 07182f9..a349915 100644
--- a/drivers/mtd/devices/docg3.h
+++ b/drivers/mtd/devices/docg3.h
@@ -118,6 +118,8 @@
 #define DOC_BCH_SYNDROM(idx)		(0x1048 + (idx << 0))
 
 #define DOC_PROTECTION			0x1056
+#define DOC_DPS0_KEY			0x105c
+#define DOC_DPS1_KEY			0x105e
 #define DOC_DPS0_ADDRLOW		0x1060
 #define DOC_DPS0_ADDRHIGH		0x1062
 #define DOC_DPS1_ADDRLOW		0x1064
@@ -252,6 +254,17 @@
 #define DOC_PLANES_STATUS_PLANE0_KO	0x02
 #define DOC_PLANES_STATUS_PLANE1_KO	0x04
 
+/*
+ * DPS key management
+ *
+ * Each floor of docg3 has 2 protection areas: DPS0 and DPS1. These areas span
+ * across block boundaries, and define whether these blocks can be read or
+ * written.
+ * The definition is dynamically stored in page 0 of blocks (2,3) for DPS0, and
+ * page 0 of blocks (4,5) for DPS1.
+ */
+#define DOC_LAYOUT_DPS_KEY_LENGTH	8
+
 /**
  * struct docg3 - DiskOnChip driver private data
  * @dev: the device currently under control



More information about the linux-mtd-cvs mailing list