1 #include <linux/efi.h> 2 #include <linux/module.h> 3 #include <linux/pstore.h> 4 #include <linux/slab.h> 5 #include <linux/ucs2_string.h> 6 7 #define DUMP_NAME_LEN 66 8 9 static bool efivars_pstore_disable = 10 IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE); 11 12 module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644); 13 14 #define PSTORE_EFI_ATTRIBUTES \ 15 (EFI_VARIABLE_NON_VOLATILE | \ 16 EFI_VARIABLE_BOOTSERVICE_ACCESS | \ 17 EFI_VARIABLE_RUNTIME_ACCESS) 18 19 static int efi_pstore_open(struct pstore_info *psi) 20 { 21 psi->data = NULL; 22 return 0; 23 } 24 25 static int efi_pstore_close(struct pstore_info *psi) 26 { 27 psi->data = NULL; 28 return 0; 29 } 30 31 static inline u64 generic_id(u64 timestamp, unsigned int part, int count) 32 { 33 return (timestamp * 100 + part) * 1000 + count; 34 } 35 36 static int efi_pstore_read_func(struct efivar_entry *entry, 37 struct pstore_record *record) 38 { 39 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 40 char name[DUMP_NAME_LEN], data_type; 41 int i; 42 int cnt; 43 unsigned int part; 44 unsigned long size; 45 u64 time; 46 47 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 48 return 0; 49 50 for (i = 0; i < DUMP_NAME_LEN; i++) 51 name[i] = entry->var.VariableName[i]; 52 53 if (sscanf(name, "dump-type%u-%u-%d-%llu-%c", 54 &record->type, &part, &cnt, &time, &data_type) == 5) { 55 record->id = generic_id(time, part, cnt); 56 record->part = part; 57 record->count = cnt; 58 record->time.tv_sec = time; 59 record->time.tv_nsec = 0; 60 if (data_type == 'C') 61 record->compressed = true; 62 else 63 record->compressed = false; 64 record->ecc_notice_size = 0; 65 } else if (sscanf(name, "dump-type%u-%u-%d-%llu", 66 &record->type, &part, &cnt, &time) == 4) { 67 record->id = generic_id(time, part, cnt); 68 record->part = part; 69 record->count = cnt; 70 record->time.tv_sec = time; 71 record->time.tv_nsec = 0; 72 record->compressed = false; 73 record->ecc_notice_size = 0; 74 } else if (sscanf(name, "dump-type%u-%u-%llu", 75 &record->type, &part, &time) == 3) { 76 /* 77 * Check if an old format, 78 * which doesn't support holding 79 * multiple logs, remains. 80 */ 81 record->id = generic_id(time, part, 0); 82 record->part = part; 83 record->count = 0; 84 record->time.tv_sec = time; 85 record->time.tv_nsec = 0; 86 record->compressed = false; 87 record->ecc_notice_size = 0; 88 } else 89 return 0; 90 91 entry->var.DataSize = 1024; 92 __efivar_entry_get(entry, &entry->var.Attributes, 93 &entry->var.DataSize, entry->var.Data); 94 size = entry->var.DataSize; 95 memcpy(record->buf, entry->var.Data, 96 (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size)); 97 98 return size; 99 } 100 101 /** 102 * efi_pstore_scan_sysfs_enter 103 * @pos: scanning entry 104 * @next: next entry 105 * @head: list head 106 */ 107 static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos, 108 struct efivar_entry *next, 109 struct list_head *head) 110 { 111 pos->scanning = true; 112 if (&next->list != head) 113 next->scanning = true; 114 } 115 116 /** 117 * __efi_pstore_scan_sysfs_exit 118 * @entry: deleting entry 119 * @turn_off_scanning: Check if a scanning flag should be turned off 120 */ 121 static inline int __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry, 122 bool turn_off_scanning) 123 { 124 if (entry->deleting) { 125 list_del(&entry->list); 126 efivar_entry_iter_end(); 127 efivar_unregister(entry); 128 if (efivar_entry_iter_begin()) 129 return -EINTR; 130 } else if (turn_off_scanning) 131 entry->scanning = false; 132 133 return 0; 134 } 135 136 /** 137 * efi_pstore_scan_sysfs_exit 138 * @pos: scanning entry 139 * @next: next entry 140 * @head: list head 141 * @stop: a flag checking if scanning will stop 142 */ 143 static int efi_pstore_scan_sysfs_exit(struct efivar_entry *pos, 144 struct efivar_entry *next, 145 struct list_head *head, bool stop) 146 { 147 int ret = __efi_pstore_scan_sysfs_exit(pos, true); 148 149 if (ret) 150 return ret; 151 152 if (stop) 153 ret = __efi_pstore_scan_sysfs_exit(next, &next->list != head); 154 return ret; 155 } 156 157 /** 158 * efi_pstore_sysfs_entry_iter 159 * 160 * @record: pstore record to pass to callback 161 * 162 * You MUST call efivar_enter_iter_begin() before this function, and 163 * efivar_entry_iter_end() afterwards. 164 * 165 */ 166 static int efi_pstore_sysfs_entry_iter(struct pstore_record *record) 167 { 168 struct efivar_entry **pos = (struct efivar_entry **)&record->psi->data; 169 struct efivar_entry *entry, *n; 170 struct list_head *head = &efivar_sysfs_list; 171 int size = 0; 172 int ret; 173 174 if (!*pos) { 175 list_for_each_entry_safe(entry, n, head, list) { 176 efi_pstore_scan_sysfs_enter(entry, n, head); 177 178 size = efi_pstore_read_func(entry, record); 179 ret = efi_pstore_scan_sysfs_exit(entry, n, head, 180 size < 0); 181 if (ret) 182 return ret; 183 if (size) 184 break; 185 } 186 *pos = n; 187 return size; 188 } 189 190 list_for_each_entry_safe_from((*pos), n, head, list) { 191 efi_pstore_scan_sysfs_enter((*pos), n, head); 192 193 size = efi_pstore_read_func((*pos), record); 194 ret = efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0); 195 if (ret) 196 return ret; 197 if (size) 198 break; 199 } 200 *pos = n; 201 return size; 202 } 203 204 /** 205 * efi_pstore_read 206 * 207 * This function returns a size of NVRAM entry logged via efi_pstore_write(). 208 * The meaning and behavior of efi_pstore/pstore are as below. 209 * 210 * size > 0: Got data of an entry logged via efi_pstore_write() successfully, 211 * and pstore filesystem will continue reading subsequent entries. 212 * size == 0: Entry was not logged via efi_pstore_write(), 213 * and efi_pstore driver will continue reading subsequent entries. 214 * size < 0: Failed to get data of entry logging via efi_pstore_write(), 215 * and pstore will stop reading entry. 216 */ 217 static ssize_t efi_pstore_read(struct pstore_record *record) 218 { 219 ssize_t size; 220 221 record->buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL); 222 if (!record->buf) 223 return -ENOMEM; 224 225 if (efivar_entry_iter_begin()) { 226 size = -EINTR; 227 goto out; 228 } 229 size = efi_pstore_sysfs_entry_iter(record); 230 efivar_entry_iter_end(); 231 232 out: 233 if (size <= 0) { 234 kfree(record->buf); 235 record->buf = NULL; 236 } 237 return size; 238 } 239 240 static int efi_pstore_write(struct pstore_record *record) 241 { 242 char name[DUMP_NAME_LEN]; 243 efi_char16_t efi_name[DUMP_NAME_LEN]; 244 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 245 int i, ret = 0; 246 247 record->id = generic_id(record->time.tv_sec, record->part, 248 record->count); 249 250 /* Since we copy the entire length of name, make sure it is wiped. */ 251 memset(name, 0, sizeof(name)); 252 253 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld-%c", 254 record->type, record->part, record->count, 255 (long long)record->time.tv_sec, 256 record->compressed ? 'C' : 'D'); 257 258 for (i = 0; i < DUMP_NAME_LEN; i++) 259 efi_name[i] = name[i]; 260 261 ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES, 262 !pstore_cannot_block_path(record->reason), 263 record->size, record->psi->buf); 264 265 if (record->reason == KMSG_DUMP_OOPS) 266 efivar_run_worker(); 267 268 return ret; 269 }; 270 271 /* 272 * Clean up an entry with the same name 273 */ 274 static int efi_pstore_erase_func(struct efivar_entry *entry, void *data) 275 { 276 efi_char16_t *efi_name = data; 277 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 278 unsigned long ucs2_len = ucs2_strlen(efi_name); 279 280 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 281 return 0; 282 283 if (ucs2_strncmp(entry->var.VariableName, efi_name, (size_t)ucs2_len)) 284 return 0; 285 286 if (entry->scanning) { 287 /* 288 * Skip deletion because this entry will be deleted 289 * after scanning is completed. 290 */ 291 entry->deleting = true; 292 } else 293 list_del(&entry->list); 294 295 /* found */ 296 __efivar_entry_delete(entry); 297 298 return 1; 299 } 300 301 static int efi_pstore_erase_name(const char *name) 302 { 303 struct efivar_entry *entry = NULL; 304 efi_char16_t efi_name[DUMP_NAME_LEN]; 305 int found, i; 306 307 for (i = 0; i < DUMP_NAME_LEN; i++) { 308 efi_name[i] = name[i]; 309 if (name[i] == '\0') 310 break; 311 } 312 313 if (efivar_entry_iter_begin()) 314 return -EINTR; 315 316 found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, 317 efi_name, &entry); 318 efivar_entry_iter_end(); 319 320 if (found && !entry->scanning) 321 efivar_unregister(entry); 322 323 return found ? 0 : -ENOENT; 324 } 325 326 static int efi_pstore_erase(struct pstore_record *record) 327 { 328 char name[DUMP_NAME_LEN]; 329 int ret; 330 331 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld", 332 record->type, record->part, record->count, 333 (long long)record->time.tv_sec); 334 ret = efi_pstore_erase_name(name); 335 if (ret != -ENOENT) 336 return ret; 337 338 snprintf(name, sizeof(name), "dump-type%u-%u-%lld", 339 record->type, record->part, (long long)record->time.tv_sec); 340 ret = efi_pstore_erase_name(name); 341 342 return ret; 343 } 344 345 static struct pstore_info efi_pstore_info = { 346 .owner = THIS_MODULE, 347 .name = "efi", 348 .flags = PSTORE_FLAGS_DMESG, 349 .open = efi_pstore_open, 350 .close = efi_pstore_close, 351 .read = efi_pstore_read, 352 .write = efi_pstore_write, 353 .erase = efi_pstore_erase, 354 }; 355 356 static __init int efivars_pstore_init(void) 357 { 358 if (!efi_enabled(EFI_RUNTIME_SERVICES)) 359 return 0; 360 361 if (!efivars_kobject()) 362 return 0; 363 364 if (efivars_pstore_disable) 365 return 0; 366 367 efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); 368 if (!efi_pstore_info.buf) 369 return -ENOMEM; 370 371 efi_pstore_info.bufsize = 1024; 372 spin_lock_init(&efi_pstore_info.buf_lock); 373 374 if (pstore_register(&efi_pstore_info)) { 375 kfree(efi_pstore_info.buf); 376 efi_pstore_info.buf = NULL; 377 efi_pstore_info.bufsize = 0; 378 } 379 380 return 0; 381 } 382 383 static __exit void efivars_pstore_exit(void) 384 { 385 if (!efi_pstore_info.bufsize) 386 return; 387 388 pstore_unregister(&efi_pstore_info); 389 kfree(efi_pstore_info.buf); 390 efi_pstore_info.buf = NULL; 391 efi_pstore_info.bufsize = 0; 392 } 393 394 module_init(efivars_pstore_init); 395 module_exit(efivars_pstore_exit); 396 397 MODULE_DESCRIPTION("EFI variable backend for pstore"); 398 MODULE_LICENSE("GPL"); 399 MODULE_ALIAS("platform:efivars"); 400