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