@@ -16,6 +16,7 @@
static DEFINE_SPINLOCK(mktme_lock);
static unsigned int mktme_available_keyids; /* Free Hardware KeyIDs */
+static struct kmem_cache *mktme_prog_cache; /* Hardware programming cache */
enum mktme_keyid_state {
KEYID_AVAILABLE, /* Available to be assigned */
@@ -79,6 +80,25 @@ static const match_table_t mktme_token = {
{OPT_ERROR, NULL}
};
+/* Copy the payload to the HW programming structure and program this KeyID */
+static int mktme_program_keyid(int keyid, u32 payload)
+{
+ struct mktme_key_program *kprog = NULL;
+ int ret;
+
+ kprog = kmem_cache_zalloc(mktme_prog_cache, GFP_KERNEL);
+ if (!kprog)
+ return -ENOMEM;
+
+ /* Hardware programming requires cached aligned struct */
+ kprog->keyid = keyid;
+ kprog->keyid_ctrl = payload;
+
+ ret = MKTME_PROG_SUCCESS; /* Future programming call */
+ kmem_cache_free(mktme_prog_cache, kprog);
+ return ret;
+}
+
/* Key Service Method called when a Userspace Key is garbage collected. */
static void mktme_destroy_key(struct key *key)
{
@@ -93,6 +113,7 @@ static void mktme_destroy_key(struct key *key)
/* Key Service Method to create a new key. Payload is preparsed. */
int mktme_instantiate_key(struct key *key, struct key_preparsed_payload *prep)
{
+ u32 *payload = prep->payload.data[0];
unsigned long flags;
int keyid;
@@ -101,7 +122,14 @@ int mktme_instantiate_key(struct key *key, struct key_preparsed_payload *prep)
spin_unlock_irqrestore(&mktme_lock, flags);
if (!keyid)
return -ENOKEY;
- return 0;
+
+ if (!mktme_program_keyid(keyid, *payload))
+ return MKTME_PROG_SUCCESS;
+
+ spin_lock_irqsave(&mktme_lock, flags);
+ mktme_release_keyid(keyid);
+ spin_unlock_irqrestore(&mktme_lock, flags);
+ return -ENOKEY;
}
/* Make sure arguments are correct for the TYPE of key requested */
@@ -245,10 +273,15 @@ static int __init init_mktme(void)
if (!mktme_map)
return -ENOMEM;
+ /* Used to program the hardware key tables */
+ mktme_prog_cache = KMEM_CACHE(mktme_key_program, SLAB_PANIC);
+ if (!mktme_prog_cache)
+ goto free_map;
+
ret = register_key_type(&key_type_mktme);
if (!ret)
return ret; /* SUCCESS */
-
+free_map:
kvfree(mktme_map);
return -ENOMEM;