Files
edk2-rk3588/edk2-rockchip/Silicon/Rockchip/Drivers/RkFvbDxe/RkFvbDxe.h
Mario Bălănică 437888c733 Improve SD/eMMC var store detection robustness
The hardware boot order on all platforms is: FSPI->EMMC->SD->USB.

U-Boot SPL (our chainloader), however, is told by its DTB to boot in
this order: SD->EMMC->FSPI. It then populates `RkAtagTypeBootDev` with
the device it decided to boot from. We use this information to determine
the drive we belong to, in order to write the variable store there.

While this behavior is useful for testing, it should generally be
avoided because it bypasses the SPL version we intended to ship with
UEFI, which could lead to all sorts of issues.

One such issue is that some SPL builds (namely Orange Pi's) flashed to
SPI will happily boot from SD card while setting the ATAG to EMMC
instead. Obviously, this leads UEFI to use the wrong device (or none at
all if EMMC is missing) for writing variables. Since SPL only reads the
variable store into memory from the actual boot device (SD card),
settings will not persist.

To address this, we'll no longer rely on that ATAG unless it indicates
FSPI boot, in which case it would most likely be correct due to FSPI
having priority in hardware - well, assuming there no further broken
SPLs in the wild that might set it to FSPI while booting from SD :P.

Instead, we'll look through the SD->EMMC devices (same order as SPL) to
find a FIT image matching our own, indicating that's likely the boot
device.

Signed-off-by: Mario Bălănică <mariobalanica02@gmail.com>
2024-12-19 16:16:23 +02:00

132 lines
4.1 KiB
C

/** @file
*
* Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
* Copyright (c) 2017 Marvell International Ltd.
* Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
* Copyright (c) 2023-2024, Mario Bălănică <mariobalanica02@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/
#ifndef __FVB_FLASH_DXE_H__
#define __FVB_FLASH_DXE_H__
#include <Protocol/BlockIo.h>
#include <Protocol/FirmwareVolumeBlock.h>
#include <Protocol/NorFlashProtocol.h>
#define GET_DATA_OFFSET(BaseAddr, Lba, LbaSize) ((BaseAddr) + (UINTN)((Lba) * (LbaSize)))
#define FVB_FLASH_SIGNATURE SIGNATURE_32('S', 'n', 'o', 'r')
#define INSTANCE_FROM_FVB_THIS(a) CR(a, FVB_DEVICE, FvbProtocol, FVB_FLASH_SIGNATURE)
//
// Define two helper macro to extract the Capability field or Status field in FVB
// bit fields.
//
#define EFI_FVB2_CAPABILITIES (EFI_FVB2_READ_DISABLED_CAP | \
EFI_FVB2_READ_ENABLED_CAP | \
EFI_FVB2_WRITE_DISABLED_CAP | \
EFI_FVB2_WRITE_ENABLED_CAP | \
EFI_FVB2_LOCK_CAP)
#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | \
EFI_FVB2_WRITE_STATUS | \
EFI_FVB2_LOCK_STATUS)
typedef struct {
VENDOR_DEVICE_PATH Vendor;
EFI_DEVICE_PATH_PROTOCOL End;
} FVB_DEVICE_PATH;
typedef struct {
UNI_NOR_FLASH_PROTOCOL *SpiFlashProtocol;
BOOLEAN IsSpiFlashAvailable;
BOOLEAN IsFvbHeaderValid;
EFI_DEVICE_PATH_PROTOCOL *DiskDevice;
UINT32 DiskMediaId;
BOOLEAN DiskDataInvalidated;
EFI_HANDLE Handle;
UINT32 Signature;
UINTN DeviceBaseAddress;
UINTN RegionBaseAddress;
UINTN Size;
UINTN FvbOffset;
UINTN FvbSize;
EFI_LBA StartLba;
EFI_BLOCK_IO_MEDIA Media;
EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
FVB_DEVICE_PATH DevicePath;
} FVB_DEVICE;
typedef struct {
UINT32 AtagBootDevType;
UINT32 ControllerBaseAddress;
} FVB_RK_BOOT_DEVICE;
EFI_STATUS
EFIAPI
FvbGetAttributes(
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
OUT EFI_FVB_ATTRIBUTES_2* Attributes
);
EFI_STATUS
EFIAPI
FvbSetAttributes(
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
IN OUT EFI_FVB_ATTRIBUTES_2* Attributes
);
EFI_STATUS
EFIAPI
FvbGetPhysicalAddress(
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
OUT EFI_PHYSICAL_ADDRESS* Address
);
EFI_STATUS
EFIAPI
FvbGetBlockSize(
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
IN EFI_LBA Lba,
OUT UINTN* BlockSize,
OUT UINTN* NumberOfBlocks
);
EFI_STATUS
EFIAPI
FvbRead(
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN* NumBytes,
IN OUT UINT8* Buffer
);
EFI_STATUS
EFIAPI
FvbWrite(
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN* NumBytes,
IN UINT8* Buffer
);
EFI_STATUS
EFIAPI
FvbEraseBlocks(
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
...
);
#endif /* __FVB_FLASH_DXE_H__ */