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->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-%lu", 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-%lu", 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->time.tv_sec = get_seconds(); 248 record->time.tv_nsec = 0; 249 250 record->id = generic_id(record->time.tv_sec, record->part, 251 record->count); 252 253 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c", 254 record->type, record->part, record->count, 255 record->time.tv_sec, record->compressed ? 'C' : 'D'); 256 257 for (i = 0; i < DUMP_NAME_LEN; i++) 258 efi_name[i] = name[i]; 259 260 ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES, 261 !pstore_cannot_block_path(record->reason), 262 record->size, record->psi->buf); 263 264 if (record->reason == KMSG_DUMP_OOPS) 265 efivar_run_worker(); 266 267 return ret; 268 }; 269 270 struct pstore_erase_data { 271 struct pstore_record *record; 272 efi_char16_t *name; 273 }; 274 275 /* 276 * Clean up an entry with the same name 277 */ 278 static int efi_pstore_erase_func(struct efivar_entry *entry, void *data) 279 { 280 struct pstore_erase_data *ed = data; 281 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 282 efi_char16_t efi_name_old[DUMP_NAME_LEN]; 283 efi_char16_t *efi_name = ed->name; 284 unsigned long ucs2_len = ucs2_strlen(ed->name); 285 char name_old[DUMP_NAME_LEN]; 286 int i; 287 288 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 289 return 0; 290 291 if (ucs2_strncmp(entry->var.VariableName, 292 efi_name, (size_t)ucs2_len)) { 293 /* 294 * Check if an old format, which doesn't support 295 * holding multiple logs, remains. 296 */ 297 snprintf(name_old, sizeof(name_old), "dump-type%u-%u-%lu", 298 ed->record->type, ed->record->part, 299 ed->record->time.tv_sec); 300 301 for (i = 0; i < DUMP_NAME_LEN; i++) 302 efi_name_old[i] = name_old[i]; 303 304 if (ucs2_strncmp(entry->var.VariableName, efi_name_old, 305 ucs2_strlen(efi_name_old))) 306 return 0; 307 } 308 309 if (entry->scanning) { 310 /* 311 * Skip deletion because this entry will be deleted 312 * after scanning is completed. 313 */ 314 entry->deleting = true; 315 } else 316 list_del(&entry->list); 317 318 /* found */ 319 __efivar_entry_delete(entry); 320 321 return 1; 322 } 323 324 static int efi_pstore_erase(struct pstore_record *record) 325 { 326 struct pstore_erase_data edata; 327 struct efivar_entry *entry = NULL; 328 char name[DUMP_NAME_LEN]; 329 efi_char16_t efi_name[DUMP_NAME_LEN]; 330 int found, i; 331 332 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu", 333 record->type, record->part, record->count, 334 record->time.tv_sec); 335 336 for (i = 0; i < DUMP_NAME_LEN; i++) 337 efi_name[i] = name[i]; 338 339 edata.record = record; 340 edata.name = efi_name; 341 342 if (efivar_entry_iter_begin()) 343 return -EINTR; 344 found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry); 345 346 if (found && !entry->scanning) { 347 efivar_entry_iter_end(); 348 efivar_unregister(entry); 349 } else 350 efivar_entry_iter_end(); 351 352 return 0; 353 } 354 355 static struct pstore_info efi_pstore_info = { 356 .owner = THIS_MODULE, 357 .name = "efi", 358 .flags = PSTORE_FLAGS_DMESG, 359 .open = efi_pstore_open, 360 .close = efi_pstore_close, 361 .read = efi_pstore_read, 362 .write = efi_pstore_write, 363 .erase = efi_pstore_erase, 364 }; 365 366 static __init int efivars_pstore_init(void) 367 { 368 if (!efi_enabled(EFI_RUNTIME_SERVICES)) 369 return 0; 370 371 if (!efivars_kobject()) 372 return 0; 373 374 if (efivars_pstore_disable) 375 return 0; 376 377 efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); 378 if (!efi_pstore_info.buf) 379 return -ENOMEM; 380 381 efi_pstore_info.bufsize = 1024; 382 spin_lock_init(&efi_pstore_info.buf_lock); 383 384 if (pstore_register(&efi_pstore_info)) { 385 kfree(efi_pstore_info.buf); 386 efi_pstore_info.buf = NULL; 387 efi_pstore_info.bufsize = 0; 388 } 389 390 return 0; 391 } 392 393 static __exit void efivars_pstore_exit(void) 394 { 395 if (!efi_pstore_info.bufsize) 396 return; 397 398 pstore_unregister(&efi_pstore_info); 399 kfree(efi_pstore_info.buf); 400 efi_pstore_info.buf = NULL; 401 efi_pstore_info.bufsize = 0; 402 } 403 404 module_init(efivars_pstore_init); 405 module_exit(efivars_pstore_exit); 406 407 MODULE_DESCRIPTION("EFI variable backend for pstore"); 408 MODULE_LICENSE("GPL"); 409 MODULE_ALIAS("platform:efivars"); 410