root/drivers/acpi/acpi_configfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acpi_table_aml_write
  2. get_header
  3. acpi_table_aml_read
  4. acpi_table_signature_show
  5. acpi_table_length_show
  6. acpi_table_revision_show
  7. acpi_table_oem_id_show
  8. acpi_table_oem_table_id_show
  9. acpi_table_oem_revision_show
  10. acpi_table_asl_compiler_id_show
  11. acpi_table_asl_compiler_revision_show
  12. acpi_table_make_item
  13. acpi_table_drop_item
  14. acpi_configfs_init
  15. acpi_configfs_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * ACPI configfs support
   4  *
   5  * Copyright (c) 2016 Intel Corporation
   6  */
   7 
   8 #define pr_fmt(fmt) "ACPI configfs: " fmt
   9 
  10 #include <linux/init.h>
  11 #include <linux/module.h>
  12 #include <linux/configfs.h>
  13 #include <linux/acpi.h>
  14 
  15 #include "acpica/accommon.h"
  16 #include "acpica/actables.h"
  17 
  18 static struct config_group *acpi_table_group;
  19 
  20 struct acpi_table {
  21         struct config_item cfg;
  22         struct acpi_table_header *header;
  23         u32 index;
  24 };
  25 
  26 static ssize_t acpi_table_aml_write(struct config_item *cfg,
  27                                     const void *data, size_t size)
  28 {
  29         const struct acpi_table_header *header = data;
  30         struct acpi_table *table;
  31         int ret;
  32 
  33         table = container_of(cfg, struct acpi_table, cfg);
  34 
  35         if (table->header) {
  36                 pr_err("table already loaded\n");
  37                 return -EBUSY;
  38         }
  39 
  40         if (header->length != size) {
  41                 pr_err("invalid table length\n");
  42                 return -EINVAL;
  43         }
  44 
  45         if (memcmp(header->signature, ACPI_SIG_SSDT, 4)) {
  46                 pr_err("invalid table signature\n");
  47                 return -EINVAL;
  48         }
  49 
  50         table = container_of(cfg, struct acpi_table, cfg);
  51 
  52         table->header = kmemdup(header, header->length, GFP_KERNEL);
  53         if (!table->header)
  54                 return -ENOMEM;
  55 
  56         ret = acpi_load_table(table->header);
  57         if (ret) {
  58                 kfree(table->header);
  59                 table->header = NULL;
  60         }
  61 
  62         return ret;
  63 }
  64 
  65 static inline struct acpi_table_header *get_header(struct config_item *cfg)
  66 {
  67         struct acpi_table *table = container_of(cfg, struct acpi_table, cfg);
  68 
  69         if (!table->header)
  70                 pr_err("table not loaded\n");
  71 
  72         return table->header;
  73 }
  74 
  75 static ssize_t acpi_table_aml_read(struct config_item *cfg,
  76                                    void *data, size_t size)
  77 {
  78         struct acpi_table_header *h = get_header(cfg);
  79 
  80         if (!h)
  81                 return -EINVAL;
  82 
  83         if (data)
  84                 memcpy(data, h, h->length);
  85 
  86         return h->length;
  87 }
  88 
  89 #define MAX_ACPI_TABLE_SIZE (128 * 1024)
  90 
  91 CONFIGFS_BIN_ATTR(acpi_table_, aml, NULL, MAX_ACPI_TABLE_SIZE);
  92 
  93 static struct configfs_bin_attribute *acpi_table_bin_attrs[] = {
  94         &acpi_table_attr_aml,
  95         NULL,
  96 };
  97 
  98 static ssize_t acpi_table_signature_show(struct config_item *cfg, char *str)
  99 {
 100         struct acpi_table_header *h = get_header(cfg);
 101 
 102         if (!h)
 103                 return -EINVAL;
 104 
 105         return sprintf(str, "%.*s\n", ACPI_NAMESEG_SIZE, h->signature);
 106 }
 107 
 108 static ssize_t acpi_table_length_show(struct config_item *cfg, char *str)
 109 {
 110         struct acpi_table_header *h = get_header(cfg);
 111 
 112         if (!h)
 113                 return -EINVAL;
 114 
 115         return sprintf(str, "%d\n", h->length);
 116 }
 117 
 118 static ssize_t acpi_table_revision_show(struct config_item *cfg, char *str)
 119 {
 120         struct acpi_table_header *h = get_header(cfg);
 121 
 122         if (!h)
 123                 return -EINVAL;
 124 
 125         return sprintf(str, "%d\n", h->revision);
 126 }
 127 
 128 static ssize_t acpi_table_oem_id_show(struct config_item *cfg, char *str)
 129 {
 130         struct acpi_table_header *h = get_header(cfg);
 131 
 132         if (!h)
 133                 return -EINVAL;
 134 
 135         return sprintf(str, "%.*s\n", ACPI_OEM_ID_SIZE, h->oem_id);
 136 }
 137 
 138 static ssize_t acpi_table_oem_table_id_show(struct config_item *cfg, char *str)
 139 {
 140         struct acpi_table_header *h = get_header(cfg);
 141 
 142         if (!h)
 143                 return -EINVAL;
 144 
 145         return sprintf(str, "%.*s\n", ACPI_OEM_TABLE_ID_SIZE, h->oem_table_id);
 146 }
 147 
 148 static ssize_t acpi_table_oem_revision_show(struct config_item *cfg, char *str)
 149 {
 150         struct acpi_table_header *h = get_header(cfg);
 151 
 152         if (!h)
 153                 return -EINVAL;
 154 
 155         return sprintf(str, "%d\n", h->oem_revision);
 156 }
 157 
 158 static ssize_t acpi_table_asl_compiler_id_show(struct config_item *cfg,
 159                                                char *str)
 160 {
 161         struct acpi_table_header *h = get_header(cfg);
 162 
 163         if (!h)
 164                 return -EINVAL;
 165 
 166         return sprintf(str, "%.*s\n", ACPI_NAMESEG_SIZE, h->asl_compiler_id);
 167 }
 168 
 169 static ssize_t acpi_table_asl_compiler_revision_show(struct config_item *cfg,
 170                                                      char *str)
 171 {
 172         struct acpi_table_header *h = get_header(cfg);
 173 
 174         if (!h)
 175                 return -EINVAL;
 176 
 177         return sprintf(str, "%d\n", h->asl_compiler_revision);
 178 }
 179 
 180 CONFIGFS_ATTR_RO(acpi_table_, signature);
 181 CONFIGFS_ATTR_RO(acpi_table_, length);
 182 CONFIGFS_ATTR_RO(acpi_table_, revision);
 183 CONFIGFS_ATTR_RO(acpi_table_, oem_id);
 184 CONFIGFS_ATTR_RO(acpi_table_, oem_table_id);
 185 CONFIGFS_ATTR_RO(acpi_table_, oem_revision);
 186 CONFIGFS_ATTR_RO(acpi_table_, asl_compiler_id);
 187 CONFIGFS_ATTR_RO(acpi_table_, asl_compiler_revision);
 188 
 189 static struct configfs_attribute *acpi_table_attrs[] = {
 190         &acpi_table_attr_signature,
 191         &acpi_table_attr_length,
 192         &acpi_table_attr_revision,
 193         &acpi_table_attr_oem_id,
 194         &acpi_table_attr_oem_table_id,
 195         &acpi_table_attr_oem_revision,
 196         &acpi_table_attr_asl_compiler_id,
 197         &acpi_table_attr_asl_compiler_revision,
 198         NULL,
 199 };
 200 
 201 static const struct config_item_type acpi_table_type = {
 202         .ct_owner = THIS_MODULE,
 203         .ct_bin_attrs = acpi_table_bin_attrs,
 204         .ct_attrs = acpi_table_attrs,
 205 };
 206 
 207 static struct config_item *acpi_table_make_item(struct config_group *group,
 208                                                 const char *name)
 209 {
 210         struct acpi_table *table;
 211 
 212         table = kzalloc(sizeof(*table), GFP_KERNEL);
 213         if (!table)
 214                 return ERR_PTR(-ENOMEM);
 215 
 216         config_item_init_type_name(&table->cfg, name, &acpi_table_type);
 217         return &table->cfg;
 218 }
 219 
 220 static void acpi_table_drop_item(struct config_group *group,
 221                                  struct config_item *cfg)
 222 {
 223         struct acpi_table *table = container_of(cfg, struct acpi_table, cfg);
 224 
 225         ACPI_INFO(("Host-directed Dynamic ACPI Table Unload"));
 226         acpi_tb_unload_table(table->index);
 227 }
 228 
 229 static struct configfs_group_operations acpi_table_group_ops = {
 230         .make_item = acpi_table_make_item,
 231         .drop_item = acpi_table_drop_item,
 232 };
 233 
 234 static const struct config_item_type acpi_tables_type = {
 235         .ct_owner = THIS_MODULE,
 236         .ct_group_ops = &acpi_table_group_ops,
 237 };
 238 
 239 static const struct config_item_type acpi_root_group_type = {
 240         .ct_owner = THIS_MODULE,
 241 };
 242 
 243 static struct configfs_subsystem acpi_configfs = {
 244         .su_group = {
 245                 .cg_item = {
 246                         .ci_namebuf = "acpi",
 247                         .ci_type = &acpi_root_group_type,
 248                 },
 249         },
 250         .su_mutex = __MUTEX_INITIALIZER(acpi_configfs.su_mutex),
 251 };
 252 
 253 static int __init acpi_configfs_init(void)
 254 {
 255         int ret;
 256         struct config_group *root = &acpi_configfs.su_group;
 257 
 258         config_group_init(root);
 259 
 260         ret = configfs_register_subsystem(&acpi_configfs);
 261         if (ret)
 262                 return ret;
 263 
 264         acpi_table_group = configfs_register_default_group(root, "table",
 265                                                            &acpi_tables_type);
 266         return PTR_ERR_OR_ZERO(acpi_table_group);
 267 }
 268 module_init(acpi_configfs_init);
 269 
 270 static void __exit acpi_configfs_exit(void)
 271 {
 272         configfs_unregister_default_group(acpi_table_group);
 273         configfs_unregister_subsystem(&acpi_configfs);
 274 }
 275 module_exit(acpi_configfs_exit);
 276 
 277 MODULE_AUTHOR("Octavian Purdila <octavian.purdila@intel.com>");
 278 MODULE_DESCRIPTION("ACPI configfs support");
 279 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */