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