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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
/** @file
Arm Ffa library code for PEI 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 <PiPei.h>
#include <Pi/PiPeiCis.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 <IndustryStandard/ArmFfaSvc.h>
#include <Guid/ArmFfaRxTxBufferInfo.h>
#include "ArmFfaCommon.h"
#include "ArmFfaRxTxMap.h"
/**
Notification service to be called when gEfiPeiMemoryDiscoveredPpiGuid is installed.
This function change reamp Rx/Tx buffer with permanent memory from
temporary Rx/Tx buffer.
Since, the Rx/Tx buffer is chanaged after gEfiPeiMemoryDiscoveredPpiGuid is installed,
the Rx/Tx buffer should be gotten in each PEIM entrypoint
via "ArmFfaGetRxTxBuffers()" for PEIM registered as shadow and
call that function always then, it always gets proper Rx/Tx buffer.
@param PeiServices Indirect reference to the PEI Services Table.
@param NotifyDescriptor Address of the notification descriptor data structure.
Type EFI_PEI_NOTIFY_DESCRIPTOR is defined above.
@param Ppi Address of the PPI that was installed.
@retval EFI_STATUS This function will install a PPI to PPI database.
The status code will be the code for (*PeiServices)->InstallPpi.
**/
STATIC
EFI_STATUS
EFIAPI
PeiServicesMemoryDiscoveredNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
EFI_HOB_GUID_TYPE *RxTxBufferHob;
ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo;
RxTxBufferHob = GetFirstGuidHob (&gArmFfaRxTxBufferInfoGuid);
ASSERT (RxTxBufferHob != NULL);
BufferInfo = GET_GUID_HOB_DATA (RxTxBufferHob);
return RemapFfaRxTxBuffer (BufferInfo);
}
STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnPeiMemoryDiscovered = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiMemoryDiscoveredPpiGuid,
PeiServicesMemoryDiscoveredNotifyCallback
};
/**
ArmFfaLib Constructor.
@param [in] FileHandle File Handle
@param [in] PeiServices Pei Service Table
@retval EFI_SUCCESS Success
@retval Others Error
**/
EFI_STATUS
EFIAPI
ArmFfaPeiLibConstructor (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
EFI_HOB_GUID_TYPE *RxTxBufferHob;
ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo;
VOID *Dummy;
EFI_HOB_MEMORY_ALLOCATION *RxTxBufferAllocationHob;
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;
}
RxTxBufferHob = GetFirstGuidHob (&gArmFfaRxTxBufferInfoGuid);
if (RxTxBufferHob == NULL) {
Status = ArmFfaLibRxTxMap ();
if (EFI_ERROR (Status)) {
return Status;
}
BufferInfo = BuildGuidHob (
&gArmFfaRxTxBufferInfoGuid,
sizeof (ARM_FFA_RX_TX_BUFFER_INFO)
);
if (BufferInfo == NULL) {
ArmFfaLibRxTxUnmap ();
return EFI_OUT_OF_RESOURCES;
}
UpdateRxTxBufferInfo (BufferInfo);
/*
* When permanent memory is used, gEfiPeiMemoryDiscoveredPpiGuid
* is installed. If gEfiPeiMemoryDiscoveredPpiGuid is found,
* It doesn't need to remap Rx/Tx buffer.
*/
Status = (*PeiServices)->LocatePpi (
PeiServices,
&gEfiPeiMemoryDiscoveredPpiGuid,
0,
NULL,
&Dummy
);
BufferInfo->RemapRequired = EFI_ERROR (Status);
} else {
BufferInfo = GET_GUID_HOB_DATA (RxTxBufferHob);
}
if (BufferInfo->RemapRequired) {
/*
* If RxTxBufferAllocationHob can be found with gArmFfaRxTxBufferInfoGuid,
* This Rx/Tx buffer is mapped by ArmFfaSecLib.
*/
RxTxBufferAllocationHob = FindRxTxBufferAllocationHob (TRUE);
/*
* Below case Rx/Tx buffer mapped by ArmPeiLib but in temporary memory.
*/
if (RxTxBufferAllocationHob == NULL) {
RxTxBufferAllocationHob = FindRxTxBufferAllocationHob (FALSE);
ASSERT (RxTxBufferAllocationHob != NULL);
BufferInfo->RemapOffset =
(UINTN)(BufferInfo->TxBufferAddr -
RxTxBufferAllocationHob->AllocDescriptor.MemoryBaseAddress);
CopyGuid (
&RxTxBufferAllocationHob->AllocDescriptor.Name,
&gArmFfaRxTxBufferInfoGuid
);
}
Status = (*PeiServices)->NotifyPpi (PeiServices, &mNotifyOnPeiMemoryDiscovered);
/*
* Failed to register NotifyPpi.
* In this case, return ERROR to make failure of load for PPI
* and postpone to remap to other PEIM.
*/
if (EFI_ERROR (Status)) {
return Status;
}
/*
* Change RemapRequired to FALSE here to prevent other PEIM from
* registering notification again.
*/
BufferInfo->RemapRequired = FALSE;
}
return EFI_SUCCESS;
}
|