mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-05 12:46:14 +02:00
When SPI Flash is blank (first boot or erased), efi_var_from_storage() returns EFI_DEVICE_ERROR because efi_var_restore() fails on invalid magic/CRC. This prevents the EFI subsystem from initializing. Check the magic value before attempting to restore variables. If the magic does not match EFI_VAR_FILE_MAGIC, treat it as an empty store and return EFI_SUCCESS, matching the behavior of the file-based efi_var_file.c which deliberately returns EFI_SUCCESS on missing or corrupted variable files to avoid blocking the boot process. Similarly, if the magic matches but efi_var_restore() fails (e.g. corrupted CRC), log the error but still return EFI_SUCCESS. Suggested-by: John Toomey <john.toomey@amd.com> Signed-off-by: Michal Simek <michal.simek@amd.com> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
109 lines
2.3 KiB
C
109 lines
2.3 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* SPI Flash interface for UEFI variables
|
|
*
|
|
* Copyright (c) 2023, Shantur Rathore
|
|
* Copyright (C) 2026, Advanced Micro Devices, Inc.
|
|
*/
|
|
|
|
#define LOG_CATEGORY LOGC_EFI
|
|
|
|
#include <efi_loader.h>
|
|
#include <efi_variable.h>
|
|
#include <spi_flash.h>
|
|
#include <dm.h>
|
|
|
|
efi_status_t efi_var_to_storage(void)
|
|
{
|
|
struct efi_var_file *buf;
|
|
struct spi_flash *flash;
|
|
struct udevice *sfdev;
|
|
efi_status_t ret;
|
|
size_t erase_len;
|
|
loff_t len;
|
|
int r;
|
|
|
|
ret = efi_var_collect(&buf, &len, EFI_VARIABLE_NON_VOLATILE);
|
|
if (ret != EFI_SUCCESS)
|
|
goto error;
|
|
|
|
if (len > EFI_VAR_BUF_SIZE) {
|
|
log_debug("EFI var buffer length more than target SPI Flash size\n");
|
|
ret = EFI_OUT_OF_RESOURCES;
|
|
goto error;
|
|
}
|
|
|
|
log_debug("Got buffer to write buf->len: %d\n", buf->length);
|
|
|
|
r = uclass_get_device(UCLASS_SPI_FLASH,
|
|
CONFIG_EFI_VARIABLE_SF_DEVICE_INDEX, &sfdev);
|
|
if (r) {
|
|
ret = EFI_DEVICE_ERROR;
|
|
goto error;
|
|
}
|
|
|
|
flash = dev_get_uclass_priv(sfdev);
|
|
if (!flash) {
|
|
log_debug("Failed to get SPI Flash priv data\n");
|
|
ret = EFI_DEVICE_ERROR;
|
|
goto error;
|
|
}
|
|
erase_len = ALIGN(len, flash->sector_size);
|
|
|
|
r = spi_flash_erase_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET,
|
|
erase_len);
|
|
if (r) {
|
|
log_debug("Failed to erase SPI Flash\n");
|
|
ret = EFI_DEVICE_ERROR;
|
|
goto error;
|
|
}
|
|
|
|
r = spi_flash_write_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET, len, buf);
|
|
if (r) {
|
|
log_debug("Failed to write to SPI Flash: %d\n", r);
|
|
ret = EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
error:
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
efi_status_t efi_var_from_storage(void)
|
|
{
|
|
struct efi_var_file *buf;
|
|
struct udevice *sfdev;
|
|
efi_status_t ret;
|
|
int r;
|
|
|
|
buf = calloc(1, EFI_VAR_BUF_SIZE);
|
|
if (!buf) {
|
|
log_err("Unable to allocate buffer\n");
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
r = uclass_get_device(UCLASS_SPI_FLASH,
|
|
CONFIG_EFI_VARIABLE_SF_DEVICE_INDEX, &sfdev);
|
|
if (r) {
|
|
log_err("Failed to get SPI Flash device: %d\n", r);
|
|
ret = EFI_DEVICE_ERROR;
|
|
goto error;
|
|
}
|
|
|
|
r = spi_flash_read_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET,
|
|
EFI_VAR_BUF_SIZE, buf);
|
|
if (r) {
|
|
log_err("Failed to read from SPI Flash: %d\n", r);
|
|
ret = EFI_DEVICE_ERROR;
|
|
goto error;
|
|
}
|
|
|
|
if (efi_var_restore(buf, false) != EFI_SUCCESS)
|
|
log_err("No valid EFI variables in SPI Flash\n");
|
|
|
|
ret = EFI_SUCCESS;
|
|
error:
|
|
free(buf);
|
|
return ret;
|
|
}
|