1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
/** @file
Arm Ffa library code for Dxe Driver
Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Glossary:
- FF-A - Firmware Framework for Arm A-profile
@par Reference(s):
- Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
**/
#include <Uefi.h>
#include <Pi/PiMultiPhase.h>
#include <Library/ArmLib.h>
#include <Library/ArmSmcLib.h>
#include <Library/ArmFfaLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <IndustryStandard/ArmFfaSvc.h>
#include <Guid/ArmFfaRxTxBufferInfo.h>
#include "ArmFfaCommon.h"
#include "ArmFfaRxTxMap.h"
STATIC EFI_EVENT mFfaExitBootServiceEvent;
/**
Unmap RX/TX buffer on Exit Boot Service.
@param [in] Event Registered exit boot service event.
@param [in] Context Additional data.
**/
STATIC
VOID
EFIAPI
ArmFfaLibExitBootServiceEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
ArmFfaLibRxTxUnmap ();
}
/**
ArmFfaLib Constructor.
@param [in] ImageHandle Image Handle
@param [in] SystemTable System Table
@retval EFI_SUCCESS Success
@retval EFI_INVALID_PARAMETER Invalid alignment of Rx/Tx buffer
@retval EFI_OUT_OF_RESOURCES Out of memory
@retval Others Error
**/
EFI_STATUS
EFIAPI
ArmFfaDxeLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HOB_GUID_TYPE *RxTxBufferHob;
ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo;
Status = ArmFfaLibCommonInit ();
if (EFI_ERROR (Status)) {
if (Status == EFI_UNSUPPORTED) {
/*
* EFI_UNSUPPORTED return from ArmFfaLibCommonInit() means
* FF-A interface doesn't support.
* However, It doesn't make failure of loading driver/library instance
* (i.e) ArmPkg's MmCommunication Dxe/PEI Driver uses as well as SpmMm.
* So If FF-A is not supported the the MmCommunication Dxe/PEI falls
* back to SpmMm.
* For this case, return EFI_SUCCESS.
*/
return EFI_SUCCESS;
}
return Status;
}
if (PcdGetBool (PcdFfaExitBootEventRegistered)) {
return EFI_SUCCESS;
}
RxTxBufferHob = GetFirstGuidHob (&gArmFfaRxTxBufferInfoGuid);
if (RxTxBufferHob != NULL) {
BufferInfo = GET_GUID_HOB_DATA (RxTxBufferHob);
if (!BufferInfo->RemapRequired) {
/*
* ArmFfaPeiLib handles the Rx/Tx buffer Remap and update the
* BufferInfo with permanant memory. So use it as it is.
*/
PcdSet64S (PcdFfaTxBuffer, (UINTN)BufferInfo->TxBufferAddr);
PcdSet64S (PcdFfaRxBuffer, (UINTN)BufferInfo->RxBufferAddr);
} else {
/*
* SEC maps Rx/Tx buffer, But no PEIM module doesn't use
* ArmFfaPeiLib. In this case, the BufferInfo includes
* temporary Rx/Tx buffer address.
*
* Therefore, remap Rx/Tx buffer with migrated address again.
*/
Status = RemapFfaRxTxBuffer (BufferInfo);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to remap Rx/Tx buffer... Status: %r\n", __func__, Status));
return Status;
}
BufferInfo->RemapRequired = FALSE;
}
} else {
Status = ArmFfaLibRxTxMap ();
/*
* When first Dxe instance (library or driver) which uses ArmFfaLib loaded,
* It already maps Rx/Tx buffer.
* From Next Dxe instance which uses ArmFfaLib it doesn't need to map Rx/Tx
* buffer again but it uses the mapped one.
* ArmFfaLibRxTxMap() returns EFI_ALREADY_STARTED when the Rx/Tx buffers
* already maps.
*/
if ((Status != EFI_SUCCESS) && (Status != EFI_ALREADY_STARTED)) {
DEBUG ((
DEBUG_ERROR,
"%a: Failed to Map Rx/Tx buffer. Status: %r\n",
__func__,
Status
));
return Status;
}
}
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
ArmFfaLibExitBootServiceEvent,
NULL,
&gEfiEventExitBootServicesGuid,
&mFfaExitBootServiceEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"%a: Failed to register ExitBootService event. Status: %r\n",
__func__,
Status
));
goto ErrorHandler;
}
PcdSetBoolS (PcdFfaExitBootEventRegistered, TRUE);
return EFI_SUCCESS;
ErrorHandler:
if (RxTxBufferHob != NULL) {
ArmFfaLibRxTxUnmap ();
}
return Status;
}
|