Hi all,

I believe this code is following the latest Russel's comments.

Regards,

Anderson Briglia

---> cut here <----
Implement MMC password force erase, remove password, change password,
unlock card and assign password operations. It uses the sysfs mechanism
to send commands to the MMC subsystem. 

Signed-off-by: Carlos Eduardo Aguiar <[EMAIL PROTECTED]>
Signed-off-by: Anderson Lizardo <[EMAIL PROTECTED]>
Signed-off-by: Anderson Briglia <[EMAIL PROTECTED]>

Index: linux-linus-2.6/drivers/mmc/mmc_sysfs.c
===================================================================
--- linux-linus-2.6.orig/drivers/mmc/mmc_sysfs.c        2007-01-03 
07:57:40.000000000 -0400
+++ linux-linus-2.6/drivers/mmc/mmc_sysfs.c     2007-01-03 07:58:14.000000000 
-0400
@@ -17,6 +17,7 @@
 #include <linux/idr.h>
 #include <linux/workqueue.h>
 #include <linux/key.h>
+#include <linux/err.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -65,6 +66,107 @@ static struct device_attribute mmc_dev_a
 
 static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
 
+#ifdef CONFIG_MMC_PASSWORDS
+
+static ssize_t
+mmc_lockable_show(struct device *dev, struct device_attribute *att, char *buf)
+{
+       struct mmc_card *card = dev_to_mmc_card(dev);
+
+       if (!mmc_card_lockable(card))
+               return sprintf(buf, "unsupported\n");
+       else
+               return sprintf(buf, "%slocked\n", mmc_card_locked(card) ?
+                       "" : "un");
+}
+
+/*
+ * implement MMC password functions: force erase, remove password, change
+ * password, unlock card and assign password.
+ */
+static ssize_t
+mmc_lockable_store(struct device *dev, struct device_attribute *att,
+       const char *data, size_t len)
+{
+       struct mmc_card *card = dev_to_mmc_card(dev);
+       int err;
+
+       err = mmc_card_claim_host(card);
+       if (err != MMC_ERR_NONE)
+               return -EINVAL;
+
+       err = mmc_card_lockable(card);
+       if (!err)
+               goto error;
+
+       if (mmc_card_locked(card) && !strncmp(data, "erase", 5)) {
+               /* forced erase only works while card is locked */
+               mmc_lock_unlock(card, NULL, MMC_LOCK_MODE_ERASE);
+               goto out;
+       } else if (!mmc_card_locked(card) && !strncmp(data, "remove", 6)) {
+               /* remove password only works while card is unlocked */
+               struct key *mmc_key = request_key(&mmc_key_type, "mmc:key", 
"remove");
+
+               if (!IS_ERR(mmc_key)) {
+                       int err =  mmc_lock_unlock(card, mmc_key, 
MMC_LOCK_MODE_CLR_PWD);
+                       if (!err)
+                               goto out;
+               } else
+                       goto request_key_error;
+       } else if (!mmc_card_locked(card) && ((!strncmp(data, "assign", 6)) ||
+                                             (!strncmp(data, "change", 6)))) {
+
+                       /* assign or change */
+                       struct key *mmc_key;
+
+                       if(!strncmp(data, "assign", 6))
+                               mmc_key = request_key(&mmc_key_type, "mmc:key", 
"assign");
+                       else
+                               mmc_key = request_key(&mmc_key_type, "mmc:key", 
"change");
+
+                       if (!IS_ERR(mmc_key)) {
+                               int err =  mmc_lock_unlock(card, mmc_key, 
MMC_LOCK_MODE_SET_PWD);
+                               if (!err)
+                                       goto out;
+                       } else
+                               goto request_key_error;
+       } else if (mmc_card_locked(card) && !strncmp(data, "unlock", 6)) {
+                       /* unlock */
+                       struct key *mmc_key = request_key(&mmc_key_type, 
"mmc:key", "unlock");
+                       if (!IS_ERR(mmc_key)) {
+                               int err = mmc_lock_unlock(card, mmc_key, 
MMC_LOCK_MODE_UNLOCK);
+                               if (err) {
+                                       dev_dbg(&card->dev, "Wrong password\n");
+                                       goto error;
+                               }
+                               else {
+                                       mmc_card_release_host(card);
+                                       goto out_unlocked;
+                               }
+                       } else
+                               goto request_key_error;
+       }
+
+request_key_error:
+       dev_dbg(&card->dev, "request_key returned error %ld\n", 
PTR_ERR(mmc_key));
+error:
+       mmc_card_release_host(card);
+       return -EINVAL;
+out:
+       mmc_card_release_host(card);
+       return len;
+
+out_unlocked:
+       device_release_driver(dev);
+       device_attach(dev);
+       return len;
+}
+
+static struct device_attribute mmc_dev_attr_lockable =
+       __ATTR(lockable, S_IWUSR | S_IRUGO,
+                mmc_lockable_show, mmc_lockable_store);
+
+#endif
 
 static void mmc_release_card(struct device *dev)
 {
@@ -234,6 +336,11 @@ int mmc_register_card(struct mmc_card *c
                        if (ret)
                                device_del(&card->dev);
                }
+#ifdef CONFIG_MMC_PASSWORDS
+               ret = device_create_file(&card->dev, &mmc_dev_attr_lockable);
+               if (ret)
+                       device_del(&card->dev);
+#endif
        }
        return ret;
 }
@@ -248,6 +355,9 @@ void mmc_remove_card(struct mmc_card *ca
                if (mmc_card_sd(card))
                        device_remove_file(&card->dev, &mmc_dev_attr_scr);
 
+#ifdef CONFIG_MMC_PASSWORDS
+               device_remove_file(&card->dev, &mmc_dev_attr_lockable);
+#endif
                device_del(&card->dev);
        }
 

Reply via email to