Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #include <linux/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/pstore.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/ucs2_string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #define DUMP_NAME_LEN 66
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #define EFIVARS_DATA_SIZE_MAX 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) static bool efivars_pstore_disable =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 	IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #define PSTORE_EFI_ATTRIBUTES \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	(EFI_VARIABLE_NON_VOLATILE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	 EFI_VARIABLE_BOOTSERVICE_ACCESS | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	 EFI_VARIABLE_RUNTIME_ACCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) static LIST_HEAD(efi_pstore_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) static DECLARE_WORK(efivar_work, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) static int efi_pstore_open(struct pstore_info *psi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	psi->data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static int efi_pstore_close(struct pstore_info *psi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	psi->data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static inline u64 generic_id(u64 timestamp, unsigned int part, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	return (timestamp * 100 + part) * 1000 + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static int efi_pstore_read_func(struct efivar_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 				struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	char name[DUMP_NAME_LEN], data_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	unsigned int part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	u64 time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	if (efi_guidcmp(entry->var.VendorGuid, vendor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	for (i = 0; i < DUMP_NAME_LEN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		name[i] = entry->var.VariableName[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	if (sscanf(name, "dump-type%u-%u-%d-%llu-%c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		   &record->type, &part, &cnt, &time, &data_type) == 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		record->id = generic_id(time, part, cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		record->part = part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		record->count = cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		record->time.tv_sec = time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		if (data_type == 'C')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			record->compressed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			record->compressed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		record->ecc_notice_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	} else if (sscanf(name, "dump-type%u-%u-%d-%llu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		   &record->type, &part, &cnt, &time) == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		record->id = generic_id(time, part, cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		record->part = part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		record->count = cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		record->time.tv_sec = time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		record->compressed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		record->ecc_notice_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	} else if (sscanf(name, "dump-type%u-%u-%llu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			  &record->type, &part, &time) == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		 * Check if an old format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		 * which doesn't support holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		 * multiple logs, remains.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		record->id = generic_id(time, part, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		record->part = part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		record->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		record->time.tv_sec = time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		record->compressed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		record->ecc_notice_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	entry->var.DataSize = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	__efivar_entry_get(entry, &entry->var.Attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			   &entry->var.DataSize, entry->var.Data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	size = entry->var.DataSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	memcpy(record->buf, entry->var.Data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	       (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * efi_pstore_scan_sysfs_enter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  * @pos: scanning entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * @next: next entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * @head: list head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 					struct efivar_entry *next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 					struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	pos->scanning = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	if (&next->list != head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		next->scanning = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * __efi_pstore_scan_sysfs_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * @entry: deleting entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * @turn_off_scanning: Check if a scanning flag should be turned off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static inline int __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 						bool turn_off_scanning)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	if (entry->deleting) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		list_del(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		efivar_entry_iter_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		if (efivar_entry_iter_begin())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	} else if (turn_off_scanning)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		entry->scanning = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  * efi_pstore_scan_sysfs_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  * @pos: scanning entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  * @next: next entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  * @head: list head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * @stop: a flag checking if scanning will stop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 				       struct efivar_entry *next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 				       struct list_head *head, bool stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	int ret = __efi_pstore_scan_sysfs_exit(pos, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		ret = __efi_pstore_scan_sysfs_exit(next, &next->list != head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  * efi_pstore_sysfs_entry_iter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)  * @record: pstore record to pass to callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  * You MUST call efivar_entry_iter_begin() before this function, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  * efivar_entry_iter_end() afterwards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static int efi_pstore_sysfs_entry_iter(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	struct efivar_entry **pos = (struct efivar_entry **)&record->psi->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	struct efivar_entry *entry, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	struct list_head *head = &efi_pstore_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	int size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	if (!*pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		list_for_each_entry_safe(entry, n, head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			efi_pstore_scan_sysfs_enter(entry, n, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			size = efi_pstore_read_func(entry, record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			ret = efi_pstore_scan_sysfs_exit(entry, n, head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 							 size < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 			if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		*pos = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	list_for_each_entry_safe_from((*pos), n, head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		efi_pstore_scan_sysfs_enter((*pos), n, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		size = efi_pstore_read_func((*pos), record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		ret = efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	*pos = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  * efi_pstore_read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  * This function returns a size of NVRAM entry logged via efi_pstore_write().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  * The meaning and behavior of efi_pstore/pstore are as below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  * size > 0: Got data of an entry logged via efi_pstore_write() successfully,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  *           and pstore filesystem will continue reading subsequent entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  * size == 0: Entry was not logged via efi_pstore_write(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  *            and efi_pstore driver will continue reading subsequent entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  * size < 0: Failed to get data of entry logging via efi_pstore_write(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  *           and pstore will stop reading entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static ssize_t efi_pstore_read(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	ssize_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	record->buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	if (!record->buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	if (efivar_entry_iter_begin()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		size = -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	size = efi_pstore_sysfs_entry_iter(record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	efivar_entry_iter_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	if (size <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		kfree(record->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		record->buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int efi_pstore_write(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	char name[DUMP_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	efi_char16_t efi_name[DUMP_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	record->id = generic_id(record->time.tv_sec, record->part,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 				record->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	/* Since we copy the entire length of name, make sure it is wiped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	memset(name, 0, sizeof(name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld-%c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		 record->type, record->part, record->count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		 (long long)record->time.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		 record->compressed ? 'C' : 'D');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	for (i = 0; i < DUMP_NAME_LEN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		efi_name[i] = name[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			      preemptible(), record->size, record->psi->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	if (record->reason == KMSG_DUMP_OOPS && try_module_get(THIS_MODULE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		if (!schedule_work(&efivar_work))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			module_put(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  * Clean up an entry with the same name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	efi_char16_t *efi_name = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	unsigned long ucs2_len = ucs2_strlen(efi_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if (efi_guidcmp(entry->var.VendorGuid, vendor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	if (ucs2_strncmp(entry->var.VariableName, efi_name, (size_t)ucs2_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (entry->scanning) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		 * Skip deletion because this entry will be deleted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		 * after scanning is completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		entry->deleting = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		list_del(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	/* found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	__efivar_entry_delete(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static int efi_pstore_erase_name(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	struct efivar_entry *entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	efi_char16_t efi_name[DUMP_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	int found, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	for (i = 0; i < DUMP_NAME_LEN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		efi_name[i] = name[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		if (name[i] == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	if (efivar_entry_iter_begin())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	found = __efivar_entry_iter(efi_pstore_erase_func, &efi_pstore_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 				    efi_name, &entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	efivar_entry_iter_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	if (found && !entry->scanning)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	return found ? 0 : -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int efi_pstore_erase(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	char name[DUMP_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		 record->type, record->part, record->count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		 (long long)record->time.tv_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	ret = efi_pstore_erase_name(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	if (ret != -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	snprintf(name, sizeof(name), "dump-type%u-%u-%lld",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		record->type, record->part, (long long)record->time.tv_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	ret = efi_pstore_erase_name(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static struct pstore_info efi_pstore_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	.owner		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	.name		= "efi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	.flags		= PSTORE_FLAGS_DMESG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	.open		= efi_pstore_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	.close		= efi_pstore_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	.read		= efi_pstore_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	.write		= efi_pstore_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	.erase		= efi_pstore_erase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int efi_pstore_callback(efi_char16_t *name, efi_guid_t vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			       unsigned long name_size, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	struct efivar_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	memcpy(entry->var.VariableName, name, name_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	entry->var.VendorGuid = vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	ret = efivar_entry_add(entry, &efi_pstore_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static int efi_pstore_update_entry(efi_char16_t *name, efi_guid_t vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 				   unsigned long name_size, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	struct efivar_entry *entry = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (efivar_entry_find(name, vendor, &efi_pstore_list, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	memcpy(entry->var.VariableName, name, name_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static void efi_pstore_update_entries(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	struct efivar_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	/* Add new sysfs entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		err = efivar_init(efi_pstore_update_entry, entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 				  false, &efi_pstore_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		efivar_entry_add(entry, &efi_pstore_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	module_put(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static __init int efivars_pstore_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	if (!efivars_kobject() || !efivar_supports_writes())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	if (efivars_pstore_disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	ret = efivar_init(efi_pstore_callback, NULL, true, &efi_pstore_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	if (!efi_pstore_info.buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	efi_pstore_info.bufsize = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	if (pstore_register(&efi_pstore_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		kfree(efi_pstore_info.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		efi_pstore_info.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		efi_pstore_info.bufsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	INIT_WORK(&efivar_work, efi_pstore_update_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static __exit void efivars_pstore_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	if (!efi_pstore_info.bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	pstore_unregister(&efi_pstore_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	kfree(efi_pstore_info.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	efi_pstore_info.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	efi_pstore_info.bufsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) module_init(efivars_pstore_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) module_exit(efivars_pstore_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) MODULE_DESCRIPTION("EFI variable backend for pstore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) MODULE_ALIAS("platform:efivars");