1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include <linux/efi.h> 4 #include <linux/module.h> 5 #include <linux/pstore.h> 6 #include <linux/slab.h> 7 #include <linux/ucs2_string.h> 8 9 MODULE_IMPORT_NS(EFIVAR); 10 11 #define DUMP_NAME_LEN 66 12 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)"); 16 17 #define PSTORE_EFI_ATTRIBUTES \ 18 (EFI_VARIABLE_NON_VOLATILE | \ 19 EFI_VARIABLE_BOOTSERVICE_ACCESS | \ 20 EFI_VARIABLE_RUNTIME_ACCESS) 21 22 static bool pstore_disable = IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE); 23 24 static int efivars_pstore_init(void); 25 static void efivars_pstore_exit(void); 26 27 static int efi_pstore_disable_set(const char *val, const struct kernel_param *kp) 28 { 29 int err; 30 bool old_pstore_disable = pstore_disable; 31 32 err = param_set_bool(val, kp); 33 if (err) 34 return err; 35 36 if (old_pstore_disable != pstore_disable) { 37 if (pstore_disable) 38 efivars_pstore_exit(); 39 else 40 efivars_pstore_init(); 41 } 42 43 return 0; 44 } 45 46 static const struct kernel_param_ops pstore_disable_ops = { 47 .set = efi_pstore_disable_set, 48 .get = param_get_bool, 49 }; 50 51 module_param_cb(pstore_disable, &pstore_disable_ops, &pstore_disable, 0644); 52 __MODULE_PARM_TYPE(pstore_disable, "bool"); 53 54 static int efi_pstore_open(struct pstore_info *psi) 55 { 56 int err; 57 58 err = efivar_lock(); 59 if (err) 60 return err; 61 62 psi->data = kzalloc(record_size, GFP_KERNEL); 63 if (!psi->data) 64 return -ENOMEM; 65 66 return 0; 67 } 68 69 static int efi_pstore_close(struct pstore_info *psi) 70 { 71 efivar_unlock(); 72 kfree(psi->data); 73 return 0; 74 } 75 76 static inline u64 generic_id(u64 timestamp, unsigned int part, int count) 77 { 78 return (timestamp * 100 + part) * 1000 + count; 79 } 80 81 static int efi_pstore_read_func(struct pstore_record *record, 82 efi_char16_t *varname) 83 { 84 unsigned long wlen, size = record_size; 85 char name[DUMP_NAME_LEN], data_type; 86 efi_status_t status; 87 int cnt; 88 unsigned int part; 89 u64 time; 90 91 ucs2_as_utf8(name, varname, DUMP_NAME_LEN); 92 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); 96 record->part = part; 97 record->count = cnt; 98 record->time.tv_sec = time; 99 record->time.tv_nsec = 0; 100 if (data_type == 'C') 101 record->compressed = true; 102 else 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); 108 record->part = part; 109 record->count = 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) { 116 /* 117 * Check if an old format, 118 * which doesn't support holding 119 * multiple logs, remains. 120 */ 121 record->id = generic_id(time, part, 0); 122 record->part = part; 123 record->count = 0; 124 record->time.tv_sec = time; 125 record->time.tv_nsec = 0; 126 record->compressed = false; 127 record->ecc_notice_size = 0; 128 } else 129 return 0; 130 131 record->buf = kmalloc(size, GFP_KERNEL); 132 if (!record->buf) 133 return -ENOMEM; 134 135 status = efivar_get_variable(varname, &LINUX_EFI_CRASH_GUID, NULL, 136 &size, record->buf); 137 if (status != EFI_SUCCESS) { 138 kfree(record->buf); 139 return efi_status_to_err(status); 140 } 141 142 /* 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 145 * variable store. 146 */ 147 wlen = (ucs2_strnlen(varname, DUMP_NAME_LEN) + 1) * sizeof(efi_char16_t); 148 record->priv = kmemdup(varname, wlen, GFP_KERNEL); 149 if (!record->priv) { 150 kfree(record->buf); 151 return -ENOMEM; 152 } 153 154 return size; 155 } 156 157 static ssize_t efi_pstore_read(struct pstore_record *record) 158 { 159 efi_char16_t *varname = record->psi->data; 160 efi_guid_t guid = LINUX_EFI_CRASH_GUID; 161 unsigned long varname_size; 162 efi_status_t status; 163 164 for (;;) { 165 /* 166 * A small set of old UEFI implementations reject sizes 167 * above a certain threshold, the lowest seen in the wild 168 * is 512. 169 * 170 * TODO: Commonize with the iteration implementation in 171 * fs/efivarfs to keep all the quirks in one place. 172 */ 173 varname_size = 512; 174 175 /* 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. 180 * 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. 186 */ 187 status = efivar_get_next_variable(&varname_size, varname, &guid); 188 if (status == EFI_NOT_FOUND) 189 return 0; 190 191 if (status != EFI_SUCCESS) 192 return efi_status_to_err(status); 193 194 /* skip variables that don't concern us */ 195 if (efi_guidcmp(guid, LINUX_EFI_CRASH_GUID)) 196 continue; 197 198 return efi_pstore_read_func(record, varname); 199 } 200 } 201 202 static int efi_pstore_write(struct pstore_record *record) 203 { 204 char name[DUMP_NAME_LEN]; 205 efi_char16_t efi_name[DUMP_NAME_LEN]; 206 efi_status_t status; 207 int i; 208 209 record->id = generic_id(record->time.tv_sec, record->part, 210 record->count); 211 212 /* Since we copy the entire length of name, make sure it is wiped. */ 213 memset(name, 0, sizeof(name)); 214 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'); 219 220 for (i = 0; i < DUMP_NAME_LEN; i++) 221 efi_name[i] = name[i]; 222 223 if (efivar_trylock()) 224 return -EBUSY; 225 status = efivar_set_variable_locked(efi_name, &LINUX_EFI_CRASH_GUID, 226 PSTORE_EFI_ATTRIBUTES, 227 record->size, record->psi->buf, 228 true); 229 efivar_unlock(); 230 return efi_status_to_err(status); 231 }; 232 233 static int efi_pstore_erase(struct pstore_record *record) 234 { 235 efi_status_t status; 236 237 status = efivar_set_variable(record->priv, &LINUX_EFI_CRASH_GUID, 238 PSTORE_EFI_ATTRIBUTES, 0, NULL); 239 240 if (status != EFI_SUCCESS && status != EFI_NOT_FOUND) 241 return efi_status_to_err(status); 242 return 0; 243 } 244 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, 254 }; 255 256 static int efivars_pstore_init(void) 257 { 258 if (!efivar_supports_writes()) 259 return 0; 260 261 if (pstore_disable) 262 return 0; 263 264 /* 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. 269 */ 270 if (record_size < 1024) 271 record_size = 1024; 272 273 efi_pstore_info.buf = kmalloc(record_size, GFP_KERNEL); 274 if (!efi_pstore_info.buf) 275 return -ENOMEM; 276 277 efi_pstore_info.bufsize = record_size; 278 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; 283 } 284 285 return 0; 286 } 287 288 static void efivars_pstore_exit(void) 289 { 290 if (!efi_pstore_info.bufsize) 291 return; 292 293 pstore_unregister(&efi_pstore_info); 294 kfree(efi_pstore_info.buf); 295 efi_pstore_info.buf = NULL; 296 efi_pstore_info.bufsize = 0; 297 } 298 299 module_init(efivars_pstore_init); 300 module_exit(efivars_pstore_exit); 301 302 MODULE_DESCRIPTION("EFI variable backend for pstore"); 303 MODULE_LICENSE("GPL"); 304 MODULE_ALIAS("platform:efivars"); 305