Skip to content

Commit

Permalink
smc things
Browse files Browse the repository at this point in the history
  • Loading branch information
WhatAmISupposedToPutHere committed Nov 4, 2022
1 parent 78b40dc commit 0eb7513
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 1 deletion.
171 changes: 170 additions & 1 deletion drivers/platform/apple/smc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
#include <linux/notifier.h>
#include "smc.h"

struct apple_smc;

struct smc_key_kobj {
struct kobject kobj;
struct apple_smc *smc;
smc_key key;
};

struct apple_smc {
struct device *dev;

Expand All @@ -23,6 +31,8 @@ struct apple_smc {
smc_key last_key;

struct blocking_notifier_head event_handlers;
struct kset *key_kset;
struct smc_key_kobj **key_kobjects;
};

static const struct mfd_cell apple_smc_devs[] = {
Expand Down Expand Up @@ -188,10 +198,127 @@ void *apple_smc_get_cookie(struct apple_smc *smc)
}
EXPORT_SYMBOL(apple_smc_get_cookie);

struct smc_key_attribute {
struct attribute attr;
ssize_t (*show)(struct smc_key_kobj *kobj, struct smc_key_attribute *attr, char *buf);
ssize_t (*store)(struct smc_key_kobj *kobj, struct smc_key_attribute *attr, const char *buf, size_t count);
};

static ssize_t smc_key_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct smc_key_attribute *attribute;
struct smc_key_kobj *key;

attribute = container_of(attr, struct smc_key_attribute, attr);
key = container_of(kobj, struct smc_key_kobj, kobj);

if (!attribute->show)
return -EIO;

return attribute->show(key, attribute, buf);
}

static ssize_t smc_key_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len)
{
struct smc_key_attribute *attribute;
struct smc_key_kobj *key;

attribute = container_of(attr, struct smc_key_attribute, attr);
key = container_of(kobj, struct smc_key_kobj, kobj);

if (!attribute->show)
return -EIO;

return attribute->store(key, attribute, buf, len);
}

static struct sysfs_ops smc_key_ops = {
.show = smc_key_attr_show,
.store = smc_key_attr_store,
};

static void smc_key_release(struct kobject *kobj)
{
struct smc_key_kobj *obj;

obj = container_of(kobj, struct smc_key_kobj, kobj);
kfree(obj);
}

static ssize_t value_attr_show(struct smc_key_kobj *kobj, struct smc_key_attribute *attr, char *buf)
{
int ret;
struct apple_smc_key_info info;
ret = apple_smc_get_key_info(kobj->smc, kobj->key, &info);
if (ret < 0)
return ret;

ret = apple_smc_read(kobj->smc, kobj->key, buf, info.size); //u8 can't be larger than PAGE_SIZE
if (ret < 0)
return ret;

switch (info.type_code) {
case 'ui64':
case 'ioft':
return sysfs_emit(buf, "%llu\n", *(u64*)buf);
case 'ui32':
return sysfs_emit(buf, "%u\n", *(u32*)buf);
case 'ui16':
return sysfs_emit(buf, "%u\n", *(u16*)buf);
case 'ui8 ':
case 'flag':
return sysfs_emit(buf, "%u\n", *(u8*)buf);
case 'si64':
return sysfs_emit(buf, "%lld\n", *(s64*)buf);
case 'si32':
return sysfs_emit(buf, "%d\n", *(s32*)buf);
case 'si16':
return sysfs_emit(buf, "%d\n", *(s16*)buf);
case 'si8 ':
return sysfs_emit(buf, "%d\n", *(s8*)buf);
default:
return info.size;
}
}


static ssize_t type_attr_show(struct smc_key_kobj *kobj, struct smc_key_attribute *attr, char *buf)
{
int ret;
struct apple_smc_key_info info;
ret = apple_smc_get_key_info(kobj->smc, kobj->key, &info);
if (ret < 0)
return ret;

info.type_code = swab32(info.type_code);
return sysfs_emit(buf, "%.4s\n", (char *)&info.type_code);
}

static struct smc_key_attribute value_attribute =
__ATTR(value, 0444, value_attr_show, NULL);

static struct smc_key_attribute type_attribute =
__ATTR(type, 0444, type_attr_show, NULL);

static struct attribute *smc_key_default_attrs[] = {
&type_attribute.attr,
&value_attribute.attr,
NULL,
};
ATTRIBUTE_GROUPS(smc_key_default);

static struct kobj_type smc_key_ktype = {
.sysfs_ops = &smc_key_ops,
.release = smc_key_release,
.default_groups = smc_key_default_groups,
};

struct apple_smc *apple_smc_probe(struct device *dev, const struct apple_smc_backend_ops *ops, void *cookie)
{
struct apple_smc *smc;
u32 count;
struct smc_key_kobj *key_obj;
smc_key key, swapped_key;
u32 count, i;
int ret;

smc = devm_kzalloc(dev, sizeof(*smc), GFP_KERNEL);
Expand Down Expand Up @@ -229,7 +356,48 @@ struct apple_smc *apple_smc_probe(struct device *dev, const struct apple_smc_bac
if (ret)
return ERR_PTR(dev_err_probe(dev, ret, "Subdevice initialization failed"));

smc->key_kobjects = devm_kzalloc(dev, sizeof(struct smc_key_kobj *) * smc->key_count, GFP_KERNEL);
if (!smc->key_kobjects)
return ERR_PTR(-ENOMEM);

smc->key_kset = kset_create_and_add("keys", NULL, &dev->kobj);
if (!smc->key_kset)
return ERR_PTR(-ENOMEM);

for (i = 0; i < smc->key_count; i++) {
key_obj = kzalloc(sizeof(*key_obj), GFP_KERNEL);
if (!key_obj) {
ret = -ENOMEM;
goto put_kobjs;
}

ret = apple_smc_get_key_by_index(smc, i, &key);
if (ret) {
kfree(key_obj);
ret = dev_err_probe(dev, ret, "Failed to get key");
goto put_kobjs;
}
key_obj->key = key;
key_obj->smc = smc;

key_obj->kobj.kset = smc->key_kset;
smc->key_kobjects[i] = key_obj;
swapped_key = swab32(key);
ret = kobject_init_and_add(&key_obj->kobj, &smc_key_ktype, NULL, "%.4s", (char *)&swapped_key);
if (ret)
goto put_kobjs;

kobject_uevent(&key_obj->kobj, KOBJ_ADD);
}
return smc;

put_kobjs:
for (i = 0; i < smc->key_count; i++) {
if (smc->key_kobjects[i])
kobject_put(&smc->key_kobjects[i]->kobj);
}
return ERR_PTR(ret);

}
EXPORT_SYMBOL(apple_smc_probe);

Expand All @@ -239,6 +407,7 @@ int apple_smc_remove(struct apple_smc *smc)

/* Disable notifications */
apple_smc_write_flag(smc, SMC_KEY(NTAP), 1);
kset_unregister(smc->key_kset);

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/platform/apple/smc_rtkit.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ static int apple_smc_rtkit_get_key_info(void *cookie, smc_key key, struct apple_

ret = apple_smc_cmd(smc, SMC_MSG_GET_KEY_INFO, key, 0, 0, NULL);
if (ret >= 0 && info) {
memcpy_fromio(key_info, smc->shmem.iomem, sizeof(key_info));
info->size = key_info[0];
info->type_code = get_unaligned_be32(&key_info[1]);
info->flags = key_info[5];
Expand Down

0 comments on commit 0eb7513

Please sign in to comment.