You've already forked edk2-platforms
mirror of
https://github.com/Dasharo/edk2-platforms.git
synced 2026-03-06 14:51:43 -08:00
In theory we should be properly cleaning up all the device drivers before hitting the big reset. The partition manager will issue flush commands to attached disks as it goes down. This assures that devices running in WB mode, which correctly handle flush/sync/etc commands, are persisted to physical media before reset. Without this, there are definitely cases where the relevant specifications don't guarantee persistence of data in their buffers in the face of reset conditions. We can't really do anything about the many devices that don't honor persistence requests, but we can start here. Signed-off-by: Jeremy Linton <jeremy.linton@arm.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
152 lines
3.8 KiB
C
152 lines
3.8 KiB
C
/** @file
|
|
*
|
|
* Support ResetSystem Runtime call using PSCI calls.
|
|
* Signals the gRaspberryPiEventResetGuid event group on reset.
|
|
*
|
|
* Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
|
|
* Copyright (c) 2014, Linaro Ltd. All rights reserved.
|
|
* Copyright (c) 2013-2015, ARM Ltd. All rights reserved.
|
|
* Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
*
|
|
**/
|
|
|
|
#include <PiDxe.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/TimerLib.h>
|
|
#include <Library/EfiResetSystemLib.h>
|
|
#include <Library/ArmSmcLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/UefiRuntimeLib.h>
|
|
|
|
#include <IndustryStandard/ArmStdSmc.h>
|
|
|
|
|
|
/**
|
|
Disconnect everything.
|
|
Modified from the UEFI 2.3 spec (May 2009 version)
|
|
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DisconnectAll (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN HandleIndex;
|
|
|
|
/*
|
|
* Retrieve the list of all handles from the handle database
|
|
*/
|
|
Status = gBS->LocateHandleBuffer (
|
|
AllHandles,
|
|
NULL,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
|
|
gBS->DisconnectController (HandleBuffer[HandleIndex], NULL, NULL);
|
|
}
|
|
|
|
gBS->FreePool(HandleBuffer);
|
|
}
|
|
|
|
|
|
/**
|
|
Resets the entire platform.
|
|
|
|
@param ResetType The type of reset to perform.
|
|
@param ResetStatus The status code for the reset.
|
|
@param DataSize The size, in bytes, of WatchdogData.
|
|
@param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
|
|
EfiResetShutdown the data buffer starts with a Null-terminated
|
|
Unicode string, optionally followed by additional binary data.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LibResetSystem (
|
|
IN EFI_RESET_TYPE ResetType,
|
|
IN EFI_STATUS ResetStatus,
|
|
IN UINTN DataSize,
|
|
IN CHAR16 *ResetData OPTIONAL
|
|
)
|
|
{
|
|
ARM_SMC_ARGS ArmSmcArgs;
|
|
UINT32 Delay;
|
|
|
|
if (!EfiAtRuntime ()) {
|
|
/*
|
|
* Only if still in UEFI.
|
|
*/
|
|
EfiEventGroupSignal (&gRaspberryPiEventResetGuid);
|
|
|
|
DisconnectAll ();
|
|
|
|
Delay = PcdGet32 (PcdPlatformResetDelay);
|
|
if (Delay != 0) {
|
|
DEBUG ((DEBUG_INFO, "Platform will be reset in %d.%d seconds...\n",
|
|
Delay / 1000000, (Delay % 1000000) / 100000));
|
|
MicroSecondDelay (Delay);
|
|
}
|
|
}
|
|
DEBUG ((DEBUG_INFO, "Platform %a.\n",
|
|
(ResetType == EfiResetShutdown) ? "shutdown" : "reset"));
|
|
|
|
switch (ResetType) {
|
|
case EfiResetPlatformSpecific:
|
|
// Map the platform specific reset as reboot
|
|
case EfiResetWarm:
|
|
// Map a warm reset into a cold reset
|
|
case EfiResetCold:
|
|
// Send a PSCI 0.2 SYSTEM_RESET command
|
|
ArmSmcArgs.Arg0 = ARM_SMC_ID_PSCI_SYSTEM_RESET;
|
|
break;
|
|
case EfiResetShutdown:
|
|
// Send a PSCI 0.2 SYSTEM_OFF command
|
|
ArmSmcArgs.Arg0 = ARM_SMC_ID_PSCI_SYSTEM_OFF;
|
|
break;
|
|
default:
|
|
ASSERT (FALSE);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
ArmCallSmc (&ArmSmcArgs);
|
|
|
|
// We should never be here
|
|
DEBUG ((DEBUG_ERROR, "%a: PSCI Reset failed\n", __FUNCTION__));
|
|
CpuDeadLoop ();
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
/**
|
|
Initialize any infrastructure required for LibResetSystem () to function.
|
|
|
|
@param ImageHandle The firmware allocated handle for the EFI image.
|
|
@param SystemTable A pointer to the EFI System Table.
|
|
|
|
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LibInitializeResetSystem (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
return EFI_SUCCESS;
|
|
}
|