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