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(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->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-%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 /* 271 * Clean up an entry with the same name 272 */ 273 static int efi_pstore_erase_func(struct efivar_entry *entry, void *data) 274 { 275 efi_char16_t *efi_name = data; 276 efi_guid_t vendor = LINUX_EFI_CRASH_GUID; 277 unsigned long ucs2_len = ucs2_strlen(efi_name); 278 279 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 280 return 0; 281 282 if (ucs2_strncmp(entry->var.VariableName, efi_name, (size_t)ucs2_len)) 283 return 0; 284 285 if (entry->scanning) { 286 /* 287 * Skip deletion because this entry will be deleted 288 * after scanning is completed. 289 */ 290 entry->deleting = true; 291 } else 292 list_del(&entry->list); 293 294 /* found */ 295 __efivar_entry_delete(entry); 296 297 return 1; 298 } 299 300 static int efi_pstore_erase_name(const char *name) 301 { 302 struct efivar_entry *entry = NULL; 303 efi_char16_t efi_name[DUMP_NAME_LEN]; 304 int found, i; 305 306 for (i = 0; i < DUMP_NAME_LEN; i++) { 307 efi_name[i] = name[i]; 308 if (name[i] == '\0') 309 break; 310 } 311 312 if (efivar_entry_iter_begin()) 313 return -EINTR; 314 315 found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, 316 efi_name, &entry); 317 efivar_entry_iter_end(); 318 319 if (found && !entry->scanning) 320 efivar_unregister(entry); 321 322 return found ? 0 : -ENOENT; 323 } 324 325 static int efi_pstore_erase(struct pstore_record *record) 326 { 327 char name[DUMP_NAME_LEN]; 328 int ret; 329 330 snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu", 331 record->type, record->part, record->count, 332 record->time.tv_sec); 333 ret = efi_pstore_erase_name(name); 334 if (ret != -ENOENT) 335 return ret; 336 337 snprintf(name, sizeof(name), "dump-type%u-%u-%lu", 338 record->type, record->part, record->time.tv_sec); 339 ret = efi_pstore_erase_name(name); 340 341 return ret; 342 } 343 344 static struct pstore_info efi_pstore_info = { 345 .owner = THIS_MODULE, 346 .name = "efi", 347 .flags = PSTORE_FLAGS_DMESG, 348 .open = efi_pstore_open, 349 .close = efi_pstore_close, 350 .read = efi_pstore_read, 351 .write = efi_pstore_write, 352 .erase = efi_pstore_erase, 353 }; 354 355 static __init int efivars_pstore_init(void) 356 { 357 if (!efi_enabled(EFI_RUNTIME_SERVICES)) 358 return 0; 359 360 if (!efivars_kobject()) 361 return 0; 362 363 if (efivars_pstore_disable) 364 return 0; 365 366 efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); 367 if (!efi_pstore_info.buf) 368 return -ENOMEM; 369 370 efi_pstore_info.bufsize = 1024; 371 spin_lock_init(&efi_pstore_info.buf_lock); 372 373 if (pstore_register(&efi_pstore_info)) { 374 kfree(efi_pstore_info.buf); 375 efi_pstore_info.buf = NULL; 376 efi_pstore_info.bufsize = 0; 377 } 378 379 return 0; 380 } 381 382 static __exit void efivars_pstore_exit(void) 383 { 384 if (!efi_pstore_info.bufsize) 385 return; 386 387 pstore_unregister(&efi_pstore_info); 388 kfree(efi_pstore_info.buf); 389 efi_pstore_info.buf = NULL; 390 efi_pstore_info.bufsize = 0; 391 } 392 393 module_init(efivars_pstore_init); 394 module_exit(efivars_pstore_exit); 395 396 MODULE_DESCRIPTION("EFI variable backend for pstore"); 397 MODULE_LICENSE("GPL"); 398 MODULE_ALIAS("platform:efivars"); 399