^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * esrt.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This module exports EFI System Resource Table (ESRT) entries into userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * through the sysfs file system. The ESRT provides a read-only catalog of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * system components for which the system accepts firmware upgrades via UEFI's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * "Capsule Update" feature. This module allows userland utilities to evaluate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * what firmware updates can be applied to this system, and potentially arrange
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * for those updates to occur.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Data is currently found below /sys/firmware/efi/esrt/...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define pr_fmt(fmt) "esrt: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/early_ioremap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct efi_system_resource_entry_v1 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) efi_guid_t fw_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u32 fw_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u32 fw_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u32 lowest_supported_fw_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u32 capsule_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u32 last_attempt_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 last_attempt_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * _count and _version are what they seem like. _max is actually just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * accounting info for the firmware when creating the table; it should never
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * have been exposed to us. To wit, the spec says:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * The maximum number of resource array entries that can be within the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * table without reallocating the table, must not be zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Since there's no guidance about what that means in terms of memory layout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * it means nothing to us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct efi_system_resource_table {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 fw_resource_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u32 fw_resource_count_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u64 fw_resource_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u8 entries[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static phys_addr_t esrt_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static size_t esrt_data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static struct efi_system_resource_table *esrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct esre_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct efi_system_resource_entry_v1 *esre1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) } esre;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct kobject kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* global list of esre_entry. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static LIST_HEAD(entry_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* entry attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct esre_attribute {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ssize_t (*show)(struct esre_entry *entry, char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ssize_t (*store)(struct esre_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) const char *buf, size_t count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static struct esre_entry *to_entry(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return container_of(kobj, struct esre_entry, kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static struct esre_attribute *to_attr(struct attribute *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return container_of(attr, struct esre_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static ssize_t esre_attr_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct attribute *_attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct esre_entry *entry = to_entry(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct esre_attribute *attr = to_attr(_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* Don't tell normal users what firmware versions we've got... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return attr->show(entry, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static const struct sysfs_ops esre_attr_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .show = esre_attr_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Generic ESRT Entry ("ESRE") support. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static ssize_t fw_class_show(struct esre_entry *entry, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) char *str = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) efi_guid_to_str(&entry->esre.esre1->fw_class, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) str += strlen(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) str += sprintf(str, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return str - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static struct esre_attribute esre_fw_class = __ATTR_RO_MODE(fw_class, 0400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define esre_attr_decl(name, size, fmt) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static ssize_t name##_show(struct esre_entry *entry, char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return sprintf(buf, fmt "\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) le##size##_to_cpu(entry->esre.esre1->name)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static struct esre_attribute esre_##name = __ATTR_RO_MODE(name, 0400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) esre_attr_decl(fw_type, 32, "%u");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) esre_attr_decl(fw_version, 32, "%u");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) esre_attr_decl(lowest_supported_fw_version, 32, "%u");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) esre_attr_decl(capsule_flags, 32, "0x%x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) esre_attr_decl(last_attempt_version, 32, "%u");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) esre_attr_decl(last_attempt_status, 32, "%u");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static struct attribute *esre1_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) &esre_fw_class.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) &esre_fw_type.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) &esre_fw_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) &esre_lowest_supported_fw_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) &esre_capsule_flags.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) &esre_last_attempt_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) &esre_last_attempt_status.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static void esre_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct esre_entry *entry = to_entry(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) list_del(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static struct kobj_type esre1_ktype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .release = esre_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .sysfs_ops = &esre_attr_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .default_attrs = esre1_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static struct kobject *esrt_kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static struct kset *esrt_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int esre_create_sysfs_entry(void *esre, int entry_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct esre_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) entry = kzalloc(sizeof(*entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) entry->kobj.kset = esrt_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (esrt->fw_resource_version == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) entry->esre.esre1 = esre;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) "entry%d", entry_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) kobject_put(&entry->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) list_add_tail(&entry->list, &entry_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* support for displaying ESRT fields at the top level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define esrt_attr_decl(name, size, fmt) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static ssize_t name##_show(struct kobject *kobj, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct kobj_attribute *attr, char *buf)\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return sprintf(buf, fmt "\n", le##size##_to_cpu(esrt->name)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static struct kobj_attribute esrt_##name = __ATTR_RO_MODE(name, 0400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) esrt_attr_decl(fw_resource_count, 32, "%u");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) esrt_attr_decl(fw_resource_count_max, 32, "%u");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) esrt_attr_decl(fw_resource_version, 64, "%llu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static struct attribute *esrt_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) &esrt_fw_resource_count.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) &esrt_fw_resource_count_max.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) &esrt_fw_resource_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static inline int esrt_table_exists(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!efi_enabled(EFI_CONFIG_TABLES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (efi.esrt == EFI_INVALID_TABLE_ADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static umode_t esrt_attr_is_visible(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct attribute *attr, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (!esrt_table_exists())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return attr->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static const struct attribute_group esrt_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .attrs = esrt_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .is_visible = esrt_attr_is_visible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * remap the table, validate it, mark it reserved and unmap it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) void __init efi_esrt_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) void *va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct efi_system_resource_table tmpesrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) size_t size, max, entry_size, entries_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) efi_memory_desc_t md;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) phys_addr_t end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!efi_enabled(EFI_MEMMAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) pr_debug("esrt-init: loading.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!esrt_table_exists())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) rc = efi_mem_desc_lookup(efi.esrt, &md);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (rc < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) (!(md.attribute & EFI_MEMORY_RUNTIME) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) md.type != EFI_BOOT_SERVICES_DATA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) md.type != EFI_RUNTIME_SERVICES_DATA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) pr_warn("ESRT header is not in the memory map.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) max = efi_mem_desc_end(&md);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (max < efi.esrt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) pr_err("EFI memory descriptor is invalid. (esrt: %p max: %p)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) (void *)efi.esrt, (void *)max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) size = sizeof(*esrt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) max -= efi.esrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (max < size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pr_err("ESRT header doesn't fit on single memory map entry. (size: %zu max: %zu)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) size, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) va = early_memremap(efi.esrt, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!va) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) memcpy(&tmpesrt, va, sizeof(tmpesrt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) early_memunmap(va, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (tmpesrt.fw_resource_version != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) pr_err("Unsupported ESRT version %lld.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) tmpesrt.fw_resource_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) entry_size = sizeof(struct efi_system_resource_entry_v1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (tmpesrt.fw_resource_count > 0 && max - size < entry_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) pr_err("ESRT memory map entry can only hold the header. (max: %zu size: %zu)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) max - size, entry_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * The format doesn't really give us any boundary to test here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * so I'm making up 128 as the max number of individually updatable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * components we support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * 128 should be pretty excessive, but there's still some chance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * somebody will do that someday and we'll need to raise this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (tmpesrt.fw_resource_count > 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) pr_err("ESRT says fw_resource_count has very large value %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) tmpesrt.fw_resource_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * We know it can't be larger than N * sizeof() here, and N is limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * by the previous test to a small number, so there's no overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) entries_size = tmpesrt.fw_resource_count * entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (max < size + entries_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) pr_err("ESRT does not fit on single memory map entry (size: %zu max: %zu)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) size, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) size += entries_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) esrt_data = (phys_addr_t)efi.esrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) esrt_data_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) end = esrt_data + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) pr_info("Reserving ESRT space from %pa to %pa.\n", &esrt_data, &end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (md.type == EFI_BOOT_SERVICES_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) efi_mem_reserve(esrt_data, esrt_data_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) pr_debug("esrt-init: loaded.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static int __init register_entries(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct efi_system_resource_entry_v1 *v1_entries = (void *)esrt->entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (!esrt_table_exists())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) for (i = 0; i < le32_to_cpu(esrt->fw_resource_count); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) void *esre = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (esrt->fw_resource_version == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) esre = &v1_entries[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) pr_err("Unsupported ESRT version %lld.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) esrt->fw_resource_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) rc = esre_create_sysfs_entry(esre, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) pr_err("ESRT entry creation failed with error %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static void cleanup_entry_list(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct esre_entry *entry, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) list_for_each_entry_safe(entry, next, &entry_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) kobject_put(&entry->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static int __init esrt_sysfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) pr_debug("esrt-sysfs: loading.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (!esrt_data || !esrt_data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) esrt = memremap(esrt_data, esrt_data_size, MEMREMAP_WB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (!esrt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) pr_err("memremap(%pa, %zu) failed.\n", &esrt_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) esrt_data_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) esrt_kobj = kobject_create_and_add("esrt", efi_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!esrt_kobj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) pr_err("Firmware table registration failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) error = sysfs_create_group(esrt_kobj, &esrt_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) pr_err("Sysfs attribute export failed with error %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) goto err_remove_esrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) esrt_kset = kset_create_and_add("entries", NULL, esrt_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (!esrt_kset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) pr_err("kset creation failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) goto err_remove_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) error = register_entries();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) goto err_cleanup_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) pr_debug("esrt-sysfs: loaded.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) err_cleanup_list:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) cleanup_entry_list();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) kset_unregister(esrt_kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) err_remove_group:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) sysfs_remove_group(esrt_kobj, &esrt_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) err_remove_esrt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) kobject_put(esrt_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) memunmap(esrt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) esrt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) device_initcall(esrt_sysfs_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) MODULE_AUTHOR("Peter Jones <pjones@redhat.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) MODULE_DESCRIPTION("EFI System Resource Table support");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) */