X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Ffirmware%2Fefivars.c;h=bee14cc47c034a64fd752b835f254630469b1e70;hb=d58541d25d4f1bd980ce40dd307d1f20dca7d237;hp=d10c9873dd9a8684d7137e49245afc9b40d13d60;hpb=1ea4f4f8405cc1ceec23f2d261bc3775785e6712;p=karo-tx-linux.git diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index d10c9873dd9a..bee14cc47c03 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -707,12 +707,29 @@ static int efi_pstore_write(enum pstore_type_id type, struct efivars *efivars = psi->data; struct efivar_entry *entry, *found = NULL; int i, ret = 0; + u64 storage_space, remaining_space, max_variable_size; + efi_status_t status = EFI_NOT_FOUND; sprintf(stub_name, "dump-type%u-%u-", type, part); sprintf(name, "%s%lu", stub_name, get_seconds()); spin_lock(&efivars->lock); + /* + * Check if there is a space enough to log. + * size: a size of logging data + * DUMP_NAME_LEN * 2: a maximum size of variable name + */ + status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES, + &storage_space, + &remaining_space, + &max_variable_size); + if (status || remaining_space < size + DUMP_NAME_LEN * 2) { + spin_unlock(&efivars->lock); + *id = part; + return -ENOSPC; + } + for (i = 0; i < DUMP_NAME_LEN; i++) efi_name[i] = stub_name[i]; @@ -767,7 +784,51 @@ static int efi_pstore_write(enum pstore_type_id type, static int efi_pstore_erase(enum pstore_type_id type, u64 id, struct pstore_info *psi) { - efi_pstore_write(type, 0, &id, (unsigned int)id, 0, psi); + char stub_name[DUMP_NAME_LEN]; + efi_char16_t efi_name[DUMP_NAME_LEN]; + efi_guid_t vendor = LINUX_EFI_CRASH_GUID; + struct efivars *efivars = psi->data; + struct efivar_entry *entry, *found = NULL; + int i; + + sprintf(stub_name, "dump-type%u-%u-", type, (unsigned int)id); + + spin_lock(&efivars->lock); + + for (i = 0; i < DUMP_NAME_LEN; i++) + efi_name[i] = stub_name[i]; + + /* + * Clean up any entries with the same name + */ + + list_for_each_entry(entry, &efivars->list, list) { + get_var_data_locked(efivars, &entry->var); + + if (efi_guidcmp(entry->var.VendorGuid, vendor)) + continue; + if (utf16_strncmp(entry->var.VariableName, efi_name, + utf16_strlen(efi_name))) + continue; + /* Needs to be a prefix */ + if (entry->var.VariableName[utf16_strlen(efi_name)] == 0) + continue; + + /* found */ + found = entry; + efivars->ops->set_variable(entry->var.VariableName, + &entry->var.VendorGuid, + PSTORE_EFI_ATTRIBUTES, + 0, NULL); + } + + if (found) + list_del(&found->list); + + spin_unlock(&efivars->lock); + + if (found) + efivar_unregister(found); return 0; } @@ -1237,6 +1298,7 @@ efivars_init(void) ops.get_variable = efi.get_variable; ops.set_variable = efi.set_variable; ops.get_next_variable = efi.get_next_variable; + ops.query_variable_info = efi.query_variable_info; error = register_efivars(&__efivars, &ops, efi_kobj); if (error) goto err_put;