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 * 159 * You MUST call efivar_enter_iter_begin() before this function, and 160 * efivar_entry_iter_end() afterwards. 161 * 162 */ 163 static int efi_pstore_sysfs_entry_iter(struct pstore_record *record) 164 { 165 struct efivar_entry **pos = (struct efivar_entry **)&record->psi->data; 166 struct efivar_entry *entry, *n; 167 struct list_head *head = &efivar_sysfs_list; 168 int size = 0; 169 int ret; 170 171 if (!*pos) { 172 list_for_each_entry_safe(entry, n, head, list) { 173 efi_pstore_scan_sysfs_enter(entry, n, head); 174 175 size = efi_pstore_read_func(entry, record); 176 ret = efi_pstore_scan_sysfs_exit(entry, n, head, 177 size < 0); 178 if (ret) 179 return ret; 180 if (size) 181 break; 182 } 183 *pos = n; 184 return size; 185 } 186 187 list_for_each_entry_safe_from((*pos), n, head, list) { 188 efi_pstore_scan_sysfs_enter((*pos), n, head); 189 190 size = efi_pstore_read_func((*pos), record); 191 ret = efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0); 192 if (ret) 193 return ret; 194 if (size) 195 break; 196 } 197 *pos = n; 198 return size; 199 } 200 201 /** 202 * efi_pstore_read 203 * 204 * This function returns a size of NVRAM entry logged via efi_pstore_write(). 205 * The meaning and behavior of efi_pstore/pstore are as below. 206 * 207 * size > 0: Got data of an entry logged via efi_pstore_write() successfully, 208 * and pstore filesystem will continue reading subsequent entries. 209 * size == 0: Entry was not logged via efi_pstore_write(), 210 * and efi_pstore driver will continue reading subsequent entries. 211 * size < 0: Failed to get data of entry logging via efi_pstore_write(), 212 * and pstore will stop reading entry. 213 */ 214 static ssize_t efi_pstore_read(struct pstore_record *record) 215 { 216 ssize_t size; 217 218 record->buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL); 219 if (!record->buf) 220 return -ENOMEM; 221 222 if (efivar_entry_iter_begin()) { 223 size = -EINTR; 224 goto out; 225 } 226 size = efi_pstore_sysfs_entry_iter(record); 227 efivar_entry_iter_end(); 228 229 out: 230 if (size <= 0) { 231 kfree(record->buf); 232 record->buf = NULL; 233 } 234 return size; 235 } 236 237 static int efi_pstore_write(struct pstore_record *record) 238 { 239 char name[DUMP_NAME_LEN]; 240 efi_char16_t efi_name[DUMP_NAME_LEN]; 241 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 242 int i, ret = 0; 243 244 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c", 245 record->type, record->part, record->count, 246 get_seconds(), record->compressed ? 'C' : 'D'); 247 248 for (i = 0; i < DUMP_NAME_LEN; i++) 249 efi_name[i] = name[i]; 250 251 ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES, 252 !pstore_cannot_block_path(record->reason), 253 record->size, record->psi->buf); 254 255 if (record->reason == KMSG_DUMP_OOPS) 256 efivar_run_worker(); 257 258 record->id = record->part; 259 return ret; 260 }; 261 262 struct pstore_erase_data { 263 struct pstore_record *record; 264 efi_char16_t *name; 265 }; 266 267 /* 268 * Clean up an entry with the same name 269 */ 270 static int efi_pstore_erase_func(struct efivar_entry *entry, void *data) 271 { 272 struct pstore_erase_data *ed = data; 273 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 274 efi_char16_t efi_name_old[DUMP_NAME_LEN]; 275 efi_char16_t *efi_name = ed->name; 276 unsigned long ucs2_len = ucs2_strlen(ed->name); 277 char name_old[DUMP_NAME_LEN]; 278 int i; 279 280 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 281 return 0; 282 283 if (ucs2_strncmp(entry->var.VariableName, 284 efi_name, (size_t)ucs2_len)) { 285 /* 286 * Check if an old format, which doesn't support 287 * holding multiple logs, remains. 288 */ 289 snprintf(name_old, sizeof(name_old), "dump-type%u-%u-%lu", 290 ed->record->type, (unsigned int)ed->record->id, 291 ed->record->time.tv_sec); 292 293 for (i = 0; i < DUMP_NAME_LEN; i++) 294 efi_name_old[i] = name_old[i]; 295 296 if (ucs2_strncmp(entry->var.VariableName, efi_name_old, 297 ucs2_strlen(efi_name_old))) 298 return 0; 299 } 300 301 if (entry->scanning) { 302 /* 303 * Skip deletion because this entry will be deleted 304 * after scanning is completed. 305 */ 306 entry->deleting = true; 307 } else 308 list_del(&entry->list); 309 310 /* found */ 311 __efivar_entry_delete(entry); 312 313 return 1; 314 } 315 316 static int efi_pstore_erase(struct pstore_record *record) 317 { 318 struct pstore_erase_data edata; 319 struct efivar_entry *entry = NULL; 320 char name[DUMP_NAME_LEN]; 321 efi_char16_t efi_name[DUMP_NAME_LEN]; 322 int found, i; 323 unsigned int part; 324 325 do_div(record->id, 1000); 326 part = do_div(record->id, 100); 327 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu", 328 record->type, record->part, record->count, 329 record->time.tv_sec); 330 331 for (i = 0; i < DUMP_NAME_LEN; i++) 332 efi_name[i] = name[i]; 333 334 edata.record = record; 335 edata.name = efi_name; 336 337 if (efivar_entry_iter_begin()) 338 return -EINTR; 339 found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry); 340 341 if (found && !entry->scanning) { 342 efivar_entry_iter_end(); 343 efivar_unregister(entry); 344 } else 345 efivar_entry_iter_end(); 346 347 return 0; 348 } 349 350 static struct pstore_info efi_pstore_info = { 351 .owner = THIS_MODULE, 352 .name = "efi", 353 .flags = PSTORE_FLAGS_DMESG, 354 .open = efi_pstore_open, 355 .close = efi_pstore_close, 356 .read = efi_pstore_read, 357 .write = efi_pstore_write, 358 .erase = efi_pstore_erase, 359 }; 360 361 static __init int efivars_pstore_init(void) 362 { 363 if (!efi_enabled(EFI_RUNTIME_SERVICES)) 364 return 0; 365 366 if (!efivars_kobject()) 367 return 0; 368 369 if (efivars_pstore_disable) 370 return 0; 371 372 efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); 373 if (!efi_pstore_info.buf) 374 return -ENOMEM; 375 376 efi_pstore_info.bufsize = 1024; 377 spin_lock_init(&efi_pstore_info.buf_lock); 378 379 if (pstore_register(&efi_pstore_info)) { 380 kfree(efi_pstore_info.buf); 381 efi_pstore_info.buf = NULL; 382 efi_pstore_info.bufsize = 0; 383 } 384 385 return 0; 386 } 387 388 static __exit void efivars_pstore_exit(void) 389 { 390 if (!efi_pstore_info.bufsize) 391 return; 392 393 pstore_unregister(&efi_pstore_info); 394 kfree(efi_pstore_info.buf); 395 efi_pstore_info.buf = NULL; 396 efi_pstore_info.bufsize = 0; 397 } 398 399 module_init(efivars_pstore_init); 400 module_exit(efivars_pstore_exit); 401 402 MODULE_DESCRIPTION("EFI variable backend for pstore"); 403 MODULE_LICENSE("GPL"); 404 MODULE_ALIAS("platform:efivars"); 405