1 // SPDX-License-Identifier: GPL-2.0+
4 #include <linux/module.h>
5 #include <linux/pstore.h>
6 #include <linux/slab.h>
7 #include <linux/ucs2_string.h>
9 MODULE_IMPORT_NS("EFIVAR");
11 #define DUMP_NAME_LEN 66
13 static unsigned int record_size
= 1024;
14 module_param(record_size
, uint
, 0444);
15 MODULE_PARM_DESC(record_size
, "size of each pstore UEFI var (in bytes, min/default=1024)");
17 #define PSTORE_EFI_ATTRIBUTES \
18 (EFI_VARIABLE_NON_VOLATILE | \
19 EFI_VARIABLE_BOOTSERVICE_ACCESS | \
20 EFI_VARIABLE_RUNTIME_ACCESS)
22 static bool pstore_disable
= IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE
);
24 static int efivars_pstore_init(void);
25 static void efivars_pstore_exit(void);
27 static int efi_pstore_disable_set(const char *val
, const struct kernel_param
*kp
)
30 bool old_pstore_disable
= pstore_disable
;
32 err
= param_set_bool(val
, kp
);
36 if (old_pstore_disable
!= pstore_disable
) {
38 efivars_pstore_exit();
40 efivars_pstore_init();
46 static const struct kernel_param_ops pstore_disable_ops
= {
47 .set
= efi_pstore_disable_set
,
48 .get
= param_get_bool
,
51 module_param_cb(pstore_disable
, &pstore_disable_ops
, &pstore_disable
, 0644);
52 __MODULE_PARM_TYPE(pstore_disable
, "bool");
54 static int efi_pstore_open(struct pstore_info
*psi
)
62 psi
->data
= kzalloc(record_size
, GFP_KERNEL
);
69 static int efi_pstore_close(struct pstore_info
*psi
)
76 static inline u64
generic_id(u64 timestamp
, unsigned int part
, int count
)
78 return (timestamp
* 100 + part
) * 1000 + count
;
81 static int efi_pstore_read_func(struct pstore_record
*record
,
82 efi_char16_t
*varname
)
84 unsigned long wlen
, size
= record_size
;
85 char name
[DUMP_NAME_LEN
], data_type
;
91 ucs2_as_utf8(name
, varname
, DUMP_NAME_LEN
);
93 if (sscanf(name
, "dump-type%u-%u-%d-%llu-%c",
94 &record
->type
, &part
, &cnt
, &time
, &data_type
) == 5) {
95 record
->id
= generic_id(time
, part
, cnt
);
98 record
->time
.tv_sec
= time
;
99 record
->time
.tv_nsec
= 0;
100 if (data_type
== 'C')
101 record
->compressed
= true;
103 record
->compressed
= false;
104 record
->ecc_notice_size
= 0;
105 } else if (sscanf(name
, "dump-type%u-%u-%d-%llu",
106 &record
->type
, &part
, &cnt
, &time
) == 4) {
107 record
->id
= generic_id(time
, part
, cnt
);
110 record
->time
.tv_sec
= time
;
111 record
->time
.tv_nsec
= 0;
112 record
->compressed
= false;
113 record
->ecc_notice_size
= 0;
114 } else if (sscanf(name
, "dump-type%u-%u-%llu",
115 &record
->type
, &part
, &time
) == 3) {
117 * Check if an old format,
118 * which doesn't support holding
119 * multiple logs, remains.
121 record
->id
= generic_id(time
, part
, 0);
124 record
->time
.tv_sec
= time
;
125 record
->time
.tv_nsec
= 0;
126 record
->compressed
= false;
127 record
->ecc_notice_size
= 0;
131 record
->buf
= kmalloc(size
, GFP_KERNEL
);
135 status
= efivar_get_variable(varname
, &LINUX_EFI_CRASH_GUID
, NULL
,
137 if (status
!= EFI_SUCCESS
) {
139 return efi_status_to_err(status
);
143 * Store the name of the variable in the pstore_record priv field, so
144 * we can reuse it later if we need to delete the EFI variable from the
147 wlen
= (ucs2_strnlen(varname
, DUMP_NAME_LEN
) + 1) * sizeof(efi_char16_t
);
148 record
->priv
= kmemdup(varname
, wlen
, GFP_KERNEL
);
157 static ssize_t
efi_pstore_read(struct pstore_record
*record
)
159 efi_char16_t
*varname
= record
->psi
->data
;
160 efi_guid_t guid
= LINUX_EFI_CRASH_GUID
;
161 unsigned long varname_size
;
166 * A small set of old UEFI implementations reject sizes
167 * above a certain threshold, the lowest seen in the wild
170 * TODO: Commonize with the iteration implementation in
171 * fs/efivarfs to keep all the quirks in one place.
176 * If this is the first read() call in the pstore enumeration,
177 * varname will be the empty string, and the GetNextVariable()
178 * runtime service call will return the first EFI variable in
179 * its own enumeration order, ignoring the guid argument.
181 * Subsequent calls to GetNextVariable() must pass the name and
182 * guid values returned by the previous call, which is why we
183 * store varname in record->psi->data. Given that we only
184 * enumerate variables with the efi-pstore GUID, there is no
185 * need to record the guid return value.
187 status
= efivar_get_next_variable(&varname_size
, varname
, &guid
);
188 if (status
== EFI_NOT_FOUND
)
191 if (status
!= EFI_SUCCESS
)
192 return efi_status_to_err(status
);
194 /* skip variables that don't concern us */
195 if (efi_guidcmp(guid
, LINUX_EFI_CRASH_GUID
))
198 return efi_pstore_read_func(record
, varname
);
202 static int efi_pstore_write(struct pstore_record
*record
)
204 char name
[DUMP_NAME_LEN
];
205 efi_char16_t efi_name
[DUMP_NAME_LEN
];
209 record
->id
= generic_id(record
->time
.tv_sec
, record
->part
,
212 /* Since we copy the entire length of name, make sure it is wiped. */
213 memset(name
, 0, sizeof(name
));
215 snprintf(name
, sizeof(name
), "dump-type%u-%u-%d-%lld-%c",
216 record
->type
, record
->part
, record
->count
,
217 (long long)record
->time
.tv_sec
,
218 record
->compressed
? 'C' : 'D');
220 for (i
= 0; i
< DUMP_NAME_LEN
; i
++)
221 efi_name
[i
] = name
[i
];
223 if (efivar_trylock())
225 status
= efivar_set_variable_locked(efi_name
, &LINUX_EFI_CRASH_GUID
,
226 PSTORE_EFI_ATTRIBUTES
,
227 record
->size
, record
->psi
->buf
,
230 return efi_status_to_err(status
);
233 static int efi_pstore_erase(struct pstore_record
*record
)
237 status
= efivar_set_variable(record
->priv
, &LINUX_EFI_CRASH_GUID
,
238 PSTORE_EFI_ATTRIBUTES
, 0, NULL
);
240 if (status
!= EFI_SUCCESS
&& status
!= EFI_NOT_FOUND
)
241 return efi_status_to_err(status
);
245 static struct pstore_info efi_pstore_info
= {
246 .owner
= THIS_MODULE
,
247 .name
= KBUILD_MODNAME
,
248 .flags
= PSTORE_FLAGS_DMESG
,
249 .open
= efi_pstore_open
,
250 .close
= efi_pstore_close
,
251 .read
= efi_pstore_read
,
252 .write
= efi_pstore_write
,
253 .erase
= efi_pstore_erase
,
256 static int efivars_pstore_init(void)
258 if (!efivar_supports_writes())
265 * Notice that 1024 is the minimum here to prevent issues with
266 * decompression algorithms that were spotted during tests;
267 * even in the case of not using compression, smaller values would
268 * just pollute more the pstore FS with many small collected files.
270 if (record_size
< 1024)
273 efi_pstore_info
.buf
= kmalloc(record_size
, GFP_KERNEL
);
274 if (!efi_pstore_info
.buf
)
277 efi_pstore_info
.bufsize
= record_size
;
279 if (pstore_register(&efi_pstore_info
)) {
280 kfree(efi_pstore_info
.buf
);
281 efi_pstore_info
.buf
= NULL
;
282 efi_pstore_info
.bufsize
= 0;
288 static void efivars_pstore_exit(void)
290 if (!efi_pstore_info
.bufsize
)
293 pstore_unregister(&efi_pstore_info
);
294 kfree(efi_pstore_info
.buf
);
295 efi_pstore_info
.buf
= NULL
;
296 efi_pstore_info
.bufsize
= 0;
299 module_init(efivars_pstore_init
);
300 module_exit(efivars_pstore_exit
);
302 MODULE_DESCRIPTION("EFI variable backend for pstore");
303 MODULE_LICENSE("GPL");
304 MODULE_ALIAS("platform:efivars");