0001
0002
0003
0004
0005
0006
0007 #include <linux/string.h>
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/types.h>
0011 #include <linux/efi.h>
0012 #include <linux/slab.h>
0013
0014 #include <asm/setup.h>
0015
0016 struct efi_runtime_map_entry {
0017 efi_memory_desc_t md;
0018 struct kobject kobj;
0019 };
0020
0021 static struct efi_runtime_map_entry **map_entries;
0022
0023 struct map_attribute {
0024 struct attribute attr;
0025 ssize_t (*show)(struct efi_runtime_map_entry *entry, char *buf);
0026 };
0027
0028 static inline struct map_attribute *to_map_attr(struct attribute *attr)
0029 {
0030 return container_of(attr, struct map_attribute, attr);
0031 }
0032
0033 static ssize_t type_show(struct efi_runtime_map_entry *entry, char *buf)
0034 {
0035 return snprintf(buf, PAGE_SIZE, "0x%x\n", entry->md.type);
0036 }
0037
0038 #define EFI_RUNTIME_FIELD(var) entry->md.var
0039
0040 #define EFI_RUNTIME_U64_ATTR_SHOW(name) \
0041 static ssize_t name##_show(struct efi_runtime_map_entry *entry, char *buf) \
0042 { \
0043 return snprintf(buf, PAGE_SIZE, "0x%llx\n", EFI_RUNTIME_FIELD(name)); \
0044 }
0045
0046 EFI_RUNTIME_U64_ATTR_SHOW(phys_addr);
0047 EFI_RUNTIME_U64_ATTR_SHOW(virt_addr);
0048 EFI_RUNTIME_U64_ATTR_SHOW(num_pages);
0049 EFI_RUNTIME_U64_ATTR_SHOW(attribute);
0050
0051 static inline struct efi_runtime_map_entry *to_map_entry(struct kobject *kobj)
0052 {
0053 return container_of(kobj, struct efi_runtime_map_entry, kobj);
0054 }
0055
0056 static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr,
0057 char *buf)
0058 {
0059 struct efi_runtime_map_entry *entry = to_map_entry(kobj);
0060 struct map_attribute *map_attr = to_map_attr(attr);
0061
0062 return map_attr->show(entry, buf);
0063 }
0064
0065 static struct map_attribute map_type_attr = __ATTR_RO_MODE(type, 0400);
0066 static struct map_attribute map_phys_addr_attr = __ATTR_RO_MODE(phys_addr, 0400);
0067 static struct map_attribute map_virt_addr_attr = __ATTR_RO_MODE(virt_addr, 0400);
0068 static struct map_attribute map_num_pages_attr = __ATTR_RO_MODE(num_pages, 0400);
0069 static struct map_attribute map_attribute_attr = __ATTR_RO_MODE(attribute, 0400);
0070
0071
0072
0073
0074 static struct attribute *def_attrs[] = {
0075 &map_type_attr.attr,
0076 &map_phys_addr_attr.attr,
0077 &map_virt_addr_attr.attr,
0078 &map_num_pages_attr.attr,
0079 &map_attribute_attr.attr,
0080 NULL
0081 };
0082 ATTRIBUTE_GROUPS(def);
0083
0084 static const struct sysfs_ops map_attr_ops = {
0085 .show = map_attr_show,
0086 };
0087
0088 static void map_release(struct kobject *kobj)
0089 {
0090 struct efi_runtime_map_entry *entry;
0091
0092 entry = to_map_entry(kobj);
0093 kfree(entry);
0094 }
0095
0096 static struct kobj_type __refdata map_ktype = {
0097 .sysfs_ops = &map_attr_ops,
0098 .default_groups = def_groups,
0099 .release = map_release,
0100 };
0101
0102 static struct kset *map_kset;
0103
0104 static struct efi_runtime_map_entry *
0105 add_sysfs_runtime_map_entry(struct kobject *kobj, int nr,
0106 efi_memory_desc_t *md)
0107 {
0108 int ret;
0109 struct efi_runtime_map_entry *entry;
0110
0111 if (!map_kset) {
0112 map_kset = kset_create_and_add("runtime-map", NULL, kobj);
0113 if (!map_kset)
0114 return ERR_PTR(-ENOMEM);
0115 }
0116
0117 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
0118 if (!entry) {
0119 kset_unregister(map_kset);
0120 map_kset = NULL;
0121 return ERR_PTR(-ENOMEM);
0122 }
0123
0124 memcpy(&entry->md, md, sizeof(efi_memory_desc_t));
0125
0126 kobject_init(&entry->kobj, &map_ktype);
0127 entry->kobj.kset = map_kset;
0128 ret = kobject_add(&entry->kobj, NULL, "%d", nr);
0129 if (ret) {
0130 kobject_put(&entry->kobj);
0131 kset_unregister(map_kset);
0132 map_kset = NULL;
0133 return ERR_PTR(ret);
0134 }
0135
0136 return entry;
0137 }
0138
0139 int efi_get_runtime_map_size(void)
0140 {
0141 return efi.memmap.nr_map * efi.memmap.desc_size;
0142 }
0143
0144 int efi_get_runtime_map_desc_size(void)
0145 {
0146 return efi.memmap.desc_size;
0147 }
0148
0149 int efi_runtime_map_copy(void *buf, size_t bufsz)
0150 {
0151 size_t sz = efi_get_runtime_map_size();
0152
0153 if (sz > bufsz)
0154 sz = bufsz;
0155
0156 memcpy(buf, efi.memmap.map, sz);
0157 return 0;
0158 }
0159
0160 int __init efi_runtime_map_init(struct kobject *efi_kobj)
0161 {
0162 int i, j, ret = 0;
0163 struct efi_runtime_map_entry *entry;
0164 efi_memory_desc_t *md;
0165
0166 if (!efi_enabled(EFI_MEMMAP))
0167 return 0;
0168
0169 map_entries = kcalloc(efi.memmap.nr_map, sizeof(entry), GFP_KERNEL);
0170 if (!map_entries) {
0171 ret = -ENOMEM;
0172 goto out;
0173 }
0174
0175 i = 0;
0176 for_each_efi_memory_desc(md) {
0177 entry = add_sysfs_runtime_map_entry(efi_kobj, i, md);
0178 if (IS_ERR(entry)) {
0179 ret = PTR_ERR(entry);
0180 goto out_add_entry;
0181 }
0182 *(map_entries + i++) = entry;
0183 }
0184
0185 return 0;
0186 out_add_entry:
0187 for (j = i - 1; j >= 0; j--) {
0188 entry = *(map_entries + j);
0189 kobject_put(&entry->kobj);
0190 }
0191 out:
0192 return ret;
0193 }