1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include <linux/efi.h> 4 #include <linux/module.h> 5 #include <linux/pstore.h> 6 #include <linux/slab.h> 7 #include <linux/ucs2_string.h> 8 9 MODULE_IMPORT_NS(EFIVAR); 10 11 #define DUMP_NAME_LEN 66 12 13 static unsigned int record_size = 1024; 14 module_param(record_size, uint, 0444); 15 MODULE_PARM_DESC(record_size, "size of each pstore UEFI var (in bytes, min/default=1024)"); 16 17 static bool efivars_pstore_disable = 18 IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE); 19 20 module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644); 21 22 #define PSTORE_EFI_ATTRIBUTES \ 23 (EFI_VARIABLE_NON_VOLATILE | \ 24 EFI_VARIABLE_BOOTSERVICE_ACCESS | \ 25 EFI_VARIABLE_RUNTIME_ACCESS) 26 27 static int efi_pstore_open(struct pstore_info *psi) 28 { 29 int err; 30 31 err = efivar_lock(); 32 if (err) 33 return err; 34 35 psi->data = kzalloc(record_size, GFP_KERNEL); 36 if (!psi->data) 37 return -ENOMEM; 38 39 return 0; 40 } 41 42 static int efi_pstore_close(struct pstore_info *psi) 43 { 44 efivar_unlock(); 45 kfree(psi->data); 46 return 0; 47 } 48 49 static inline u64 generic_id(u64 timestamp, unsigned int part, int count) 50 { 51 return (timestamp * 100 + part) * 1000 + count; 52 } 53 54 static int efi_pstore_read_func(struct pstore_record *record, 55 efi_char16_t *varname) 56 { 57 unsigned long wlen, size = record_size; 58 char name[DUMP_NAME_LEN], data_type; 59 efi_status_t status; 60 int cnt; 61 unsigned int part; 62 u64 time; 63 64 ucs2_as_utf8(name, varname, DUMP_NAME_LEN); 65 66 if (sscanf(name, "dump-type%u-%u-%d-%llu-%c", 67 &record->type, &part, &cnt, &time, &data_type) == 5) { 68 record->id = generic_id(time, part, cnt); 69 record->part = part; 70 record->count = cnt; 71 record->time.tv_sec = time; 72 record->time.tv_nsec = 0; 73 if (data_type == 'C') 74 record->compressed = true; 75 else 76 record->compressed = false; 77 record->ecc_notice_size = 0; 78 } else if (sscanf(name, "dump-type%u-%u-%d-%llu", 79 &record->type, &part, &cnt, &time) == 4) { 80 record->id = generic_id(time, part, cnt); 81 record->part = part; 82 record->count = cnt; 83 record->time.tv_sec = time; 84 record->time.tv_nsec = 0; 85 record->compressed = false; 86 record->ecc_notice_size = 0; 87 } else if (sscanf(name, "dump-type%u-%u-%llu", 88 &record->type, &part, &time) == 3) { 89 /* 90 * Check if an old format, 91 * which doesn't support holding 92 * multiple logs, remains. 93 */ 94 record->id = generic_id(time, part, 0); 95 record->part = part; 96 record->count = 0; 97 record->time.tv_sec = time; 98 record->time.tv_nsec = 0; 99 record->compressed = false; 100 record->ecc_notice_size = 0; 101 } else 102 return 0; 103 104 record->buf = kmalloc(size, GFP_KERNEL); 105 if (!record->buf) 106 return -ENOMEM; 107 108 status = efivar_get_variable(varname, &LINUX_EFI_CRASH_GUID, NULL, 109 &size, record->buf); 110 if (status != EFI_SUCCESS) { 111 kfree(record->buf); 112 return -EIO; 113 } 114 115 /* 116 * Store the name of the variable in the pstore_record priv field, so 117 * we can reuse it later if we need to delete the EFI variable from the 118 * variable store. 119 */ 120 wlen = (ucs2_strnlen(varname, DUMP_NAME_LEN) + 1) * sizeof(efi_char16_t); 121 record->priv = kmemdup(varname, wlen, GFP_KERNEL); 122 if (!record->priv) { 123 kfree(record->buf); 124 return -ENOMEM; 125 } 126 127 return size; 128 } 129 130 static ssize_t efi_pstore_read(struct pstore_record *record) 131 { 132 efi_char16_t *varname = record->psi->data; 133 efi_guid_t guid = LINUX_EFI_CRASH_GUID; 134 unsigned long varname_size; 135 efi_status_t status; 136 137 for (;;) { 138 varname_size = 1024; 139 140 /* 141 * If this is the first read() call in the pstore enumeration, 142 * varname will be the empty string, and the GetNextVariable() 143 * runtime service call will return the first EFI variable in 144 * its own enumeration order, ignoring the guid argument. 145 * 146 * Subsequent calls to GetNextVariable() must pass the name and 147 * guid values returned by the previous call, which is why we 148 * store varname in record->psi->data. Given that we only 149 * enumerate variables with the efi-pstore GUID, there is no 150 * need to record the guid return value. 151 */ 152 status = efivar_get_next_variable(&varname_size, varname, &guid); 153 if (status == EFI_NOT_FOUND) 154 return 0; 155 156 if (status != EFI_SUCCESS) 157 return -EIO; 158 159 /* skip variables that don't concern us */ 160 if (efi_guidcmp(guid, LINUX_EFI_CRASH_GUID)) 161 continue; 162 163 return efi_pstore_read_func(record, varname); 164 } 165 } 166 167 static int efi_pstore_write(struct pstore_record *record) 168 { 169 char name[DUMP_NAME_LEN]; 170 efi_char16_t efi_name[DUMP_NAME_LEN]; 171 efi_status_t status; 172 int i; 173 174 record->id = generic_id(record->time.tv_sec, record->part, 175 record->count); 176 177 /* Since we copy the entire length of name, make sure it is wiped. */ 178 memset(name, 0, sizeof(name)); 179 180 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld-%c", 181 record->type, record->part, record->count, 182 (long long)record->time.tv_sec, 183 record->compressed ? 'C' : 'D'); 184 185 for (i = 0; i < DUMP_NAME_LEN; i++) 186 efi_name[i] = name[i]; 187 188 if (efivar_trylock()) 189 return -EBUSY; 190 status = efivar_set_variable_locked(efi_name, &LINUX_EFI_CRASH_GUID, 191 PSTORE_EFI_ATTRIBUTES, 192 record->size, record->psi->buf, 193 true); 194 efivar_unlock(); 195 return status == EFI_SUCCESS ? 0 : -EIO; 196 }; 197 198 static int efi_pstore_erase(struct pstore_record *record) 199 { 200 efi_status_t status; 201 202 status = efivar_set_variable(record->priv, &LINUX_EFI_CRASH_GUID, 203 PSTORE_EFI_ATTRIBUTES, 0, NULL); 204 205 if (status != EFI_SUCCESS && status != EFI_NOT_FOUND) 206 return -EIO; 207 return 0; 208 } 209 210 static struct pstore_info efi_pstore_info = { 211 .owner = THIS_MODULE, 212 .name = KBUILD_MODNAME, 213 .flags = PSTORE_FLAGS_DMESG, 214 .open = efi_pstore_open, 215 .close = efi_pstore_close, 216 .read = efi_pstore_read, 217 .write = efi_pstore_write, 218 .erase = efi_pstore_erase, 219 }; 220 221 static __init int efivars_pstore_init(void) 222 { 223 if (!efivar_supports_writes()) 224 return 0; 225 226 if (efivars_pstore_disable) 227 return 0; 228 229 /* 230 * Notice that 1024 is the minimum here to prevent issues with 231 * decompression algorithms that were spotted during tests; 232 * even in the case of not using compression, smaller values would 233 * just pollute more the pstore FS with many small collected files. 234 */ 235 if (record_size < 1024) 236 record_size = 1024; 237 238 efi_pstore_info.buf = kmalloc(record_size, GFP_KERNEL); 239 if (!efi_pstore_info.buf) 240 return -ENOMEM; 241 242 efi_pstore_info.bufsize = record_size; 243 244 if (pstore_register(&efi_pstore_info)) { 245 kfree(efi_pstore_info.buf); 246 efi_pstore_info.buf = NULL; 247 efi_pstore_info.bufsize = 0; 248 } 249 250 return 0; 251 } 252 253 static __exit void efivars_pstore_exit(void) 254 { 255 if (!efi_pstore_info.bufsize) 256 return; 257 258 pstore_unregister(&efi_pstore_info); 259 kfree(efi_pstore_info.buf); 260 efi_pstore_info.buf = NULL; 261 efi_pstore_info.bufsize = 0; 262 } 263 264 module_init(efivars_pstore_init); 265 module_exit(efivars_pstore_exit); 266 267 MODULE_DESCRIPTION("EFI variable backend for pstore"); 268 MODULE_LICENSE("GPL"); 269 MODULE_ALIAS("platform:efivars"); 270