aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices
diff options
context:
space:
mode:
authorRobert Jarzmik <robert.jarzmik@free.fr>2011-11-19 10:02:58 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-01-09 13:07:30 -0500
commit0f769d3f9e2ef3e88930ff190a20cfbfe6206d3a (patch)
tree7317d7e8beeae37c550a875835dcbf3dc1c7af32 /drivers/mtd/devices
parentc3de8a8a5a28603f8d318245992dbcda2e88a007 (diff)
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@free.fr> Reviewed-by: Ivan Djelic <ivan.djelic@parrot.com> Reviewed-by: Mike Dunn <mikedunn@newsguy.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r--drivers/mtd/devices/docg3.c121
-rw-r--r--drivers/mtd/devices/docg3.h13
2 files changed, 134 insertions, 0 deletions
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 35df3778f8fd..d7df3114aa17 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,
1513 return ret; 1513 return ret;
1514} 1514}
1515 1515
1516static struct docg3 *sysfs_dev2docg3(struct device *dev,
1517 struct device_attribute *attr)
1518{
1519 int floor;
1520 struct platform_device *pdev = to_platform_device(dev);
1521 struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
1522
1523 floor = attr->attr.name[1] - '0';
1524 if (floor < 0 || floor >= DOC_MAX_NBFLOORS)
1525 return NULL;
1526 else
1527 return docg3_floors[floor]->priv;
1528}
1529
1530static ssize_t dps0_is_key_locked(struct device *dev,
1531 struct device_attribute *attr, char *buf)
1532{
1533 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1534 int dps0;
1535
1536 doc_set_device_id(docg3, docg3->device_id);
1537 dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
1538 doc_set_device_id(docg3, 0);
1539
1540 return sprintf(buf, "%d\n", !(dps0 & DOC_DPS_KEY_OK));
1541}
1542
1543static ssize_t dps1_is_key_locked(struct device *dev,
1544 struct device_attribute *attr, char *buf)
1545{
1546 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1547 int dps1;
1548
1549 doc_set_device_id(docg3, docg3->device_id);
1550 dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
1551 doc_set_device_id(docg3, 0);
1552
1553 return sprintf(buf, "%d\n", !(dps1 & DOC_DPS_KEY_OK));
1554}
1555
1556static ssize_t dps0_insert_key(struct device *dev,
1557 struct device_attribute *attr,
1558 const char *buf, size_t count)
1559{
1560 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1561 int i;
1562
1563 if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
1564 return -EINVAL;
1565
1566 doc_set_device_id(docg3, docg3->device_id);
1567 for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
1568 doc_writeb(docg3, buf[i], DOC_DPS0_KEY);
1569 doc_set_device_id(docg3, 0);
1570 return count;
1571}
1572
1573static ssize_t dps1_insert_key(struct device *dev,
1574 struct device_attribute *attr,
1575 const char *buf, size_t count)
1576{
1577 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1578 int i;
1579
1580 if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
1581 return -EINVAL;
1582
1583 doc_set_device_id(docg3, docg3->device_id);
1584 for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
1585 doc_writeb(docg3, buf[i], DOC_DPS1_KEY);
1586 doc_set_device_id(docg3, 0);
1587 return count;
1588}
1589
1590#define FLOOR_SYSFS(id) { \
1591 __ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \
1592 __ATTR(f##id##_dps1_is_keylocked, S_IRUGO, dps1_is_key_locked, NULL), \
1593 __ATTR(f##id##_dps0_protection_key, S_IWUGO, NULL, dps0_insert_key), \
1594 __ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_insert_key), \
1595}
1596
1597static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
1598 FLOOR_SYSFS(0), FLOOR_SYSFS(1), FLOOR_SYSFS(2), FLOOR_SYSFS(3)
1599};
1600
1601static int doc_register_sysfs(struct platform_device *pdev,
1602 struct mtd_info **floors)
1603{
1604 int ret = 0, floor, i = 0;
1605 struct device *dev = &pdev->dev;
1606
1607 for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor];
1608 floor++)
1609 for (i = 0; !ret && i < 4; i++)
1610 ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
1611 if (!ret)
1612 return 0;
1613 do {
1614 while (--i >= 0)
1615 device_remove_file(dev, &doc_sys_attrs[floor][i]);
1616 i = 4;
1617 } while (--floor >= 0);
1618 return ret;
1619}
1620
1621static void doc_unregister_sysfs(struct platform_device *pdev,
1622 struct mtd_info **floors)
1623{
1624 struct device *dev = &pdev->dev;
1625 int floor, i;
1626
1627 for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor];
1628 floor++)
1629 for (i = 0; i < 4; i++)
1630 device_remove_file(dev, &doc_sys_attrs[floor][i]);
1631}
1632
1516/* 1633/*
1517 * Debug sysfs entries 1634 * Debug sysfs entries
1518 */ 1635 */
@@ -1927,6 +2044,9 @@ static int __init docg3_probe(struct platform_device *pdev)
1927 found++; 2044 found++;
1928 } 2045 }
1929 2046
2047 ret = doc_register_sysfs(pdev, docg3_floors);
2048 if (ret)
2049 goto err_probe;
1930 if (!found) 2050 if (!found)
1931 goto notfound; 2051 goto notfound;
1932 2052
@@ -1963,6 +2083,7 @@ static int __exit docg3_release(struct platform_device *pdev)
1963 void __iomem *base = docg3->base; 2083 void __iomem *base = docg3->base;
1964 int floor; 2084 int floor;
1965 2085
2086 doc_unregister_sysfs(pdev, docg3_floors);
1966 doc_dbg_unregister(docg3); 2087 doc_dbg_unregister(docg3);
1967 for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) 2088 for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
1968 if (docg3_floors[floor]) 2089 if (docg3_floors[floor])
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h
index 07182f9d484d..a349915da77d 100644
--- a/drivers/mtd/devices/docg3.h
+++ b/drivers/mtd/devices/docg3.h
@@ -118,6 +118,8 @@
118#define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 0)) 118#define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 0))
119 119
120#define DOC_PROTECTION 0x1056 120#define DOC_PROTECTION 0x1056
121#define DOC_DPS0_KEY 0x105c
122#define DOC_DPS1_KEY 0x105e
121#define DOC_DPS0_ADDRLOW 0x1060 123#define DOC_DPS0_ADDRLOW 0x1060
122#define DOC_DPS0_ADDRHIGH 0x1062 124#define DOC_DPS0_ADDRHIGH 0x1062
123#define DOC_DPS1_ADDRLOW 0x1064 125#define DOC_DPS1_ADDRLOW 0x1064
@@ -252,6 +254,17 @@
252#define DOC_PLANES_STATUS_PLANE0_KO 0x02 254#define DOC_PLANES_STATUS_PLANE0_KO 0x02
253#define DOC_PLANES_STATUS_PLANE1_KO 0x04 255#define DOC_PLANES_STATUS_PLANE1_KO 0x04
254 256
257/*
258 * DPS key management
259 *
260 * Each floor of docg3 has 2 protection areas: DPS0 and DPS1. These areas span
261 * across block boundaries, and define whether these blocks can be read or
262 * written.
263 * The definition is dynamically stored in page 0 of blocks (2,3) for DPS0, and
264 * page 0 of blocks (4,5) for DPS1.
265 */
266#define DOC_LAYOUT_DPS_KEY_LENGTH 8
267
255/** 268/**
256 * struct docg3 - DiskOnChip driver private data 269 * struct docg3 - DiskOnChip driver private data
257 * @dev: the device currently under control 270 * @dev: the device currently under control