From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- roms/edk2/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c | 303 ++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 roms/edk2/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c (limited to 'roms/edk2/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c') diff --git a/roms/edk2/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c b/roms/edk2/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c new file mode 100644 index 000000000..d1e3ecfa5 --- /dev/null +++ b/roms/edk2/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c @@ -0,0 +1,303 @@ +/** @file + + Helper functions used by at least two Simple Network Protocol methods. + + Copyright (C) 2013, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include "VirtioNet.h" + +// +// The user structure for the ordered collection that will track the mapping +// info of the packets queued in TxRing +// +typedef struct { + VOID *Buffer; + EFI_PHYSICAL_ADDRESS DeviceAddress; // lookup key for reverse mapping + VOID *BufMap; +} TX_BUF_MAP_INFO; + +/** + Release RX and TX resources on the boundary of the + EfiSimpleNetworkInitialized state. + + These functions contribute to rolling back a partial, failed initialization + of the virtio-net SNP driver instance, or to shutting down a fully + initialized, running instance. + + They are only callable by the VirtioNetInitialize() and the + VirtioNetShutdown() SNP methods. See the state diagram in "VirtioNet.h". + + @param[in,out] Dev The VNET_DEV driver instance being shut down, or whose + partial, failed initialization is being rolled back. +*/ + +VOID +EFIAPI +VirtioNetShutdownRx ( + IN OUT VNET_DEV *Dev + ) +{ + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap); + Dev->VirtIo->FreeSharedPages ( + Dev->VirtIo, + Dev->RxBufNrPages, + Dev->RxBuf + ); +} + + +VOID +EFIAPI +VirtioNetShutdownTx ( + IN OUT VNET_DEV *Dev + ) +{ + ORDERED_COLLECTION_ENTRY *Entry, *Entry2; + TX_BUF_MAP_INFO *TxBufMapInfo; + VOID *UserStruct; + + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap); + Dev->VirtIo->FreeSharedPages ( + Dev->VirtIo, + EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)), + Dev->TxSharedReq + ); + + for (Entry = OrderedCollectionMin (Dev->TxBufCollection); + Entry != NULL; + Entry = Entry2) { + Entry2 = OrderedCollectionNext (Entry); + OrderedCollectionDelete (Dev->TxBufCollection, Entry, &UserStruct); + TxBufMapInfo = UserStruct; + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap); + FreePool (TxBufMapInfo); + } + OrderedCollectionUninit (Dev->TxBufCollection); + + FreePool (Dev->TxFreeStack); +} + +/** + Release TX and RX VRING resources. + + @param[in,out] Dev The VNET_DEV driver instance which was using + the ring. + @param[in,out] Ring The virtio ring to clean up. + @param[in] RingMap A token return from the VirtioRingMap() +*/ +VOID +EFIAPI +VirtioNetUninitRing ( + IN OUT VNET_DEV *Dev, + IN OUT VRING *Ring, + IN VOID *RingMap + ) +{ + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RingMap); + VirtioRingUninit (Dev->VirtIo, Ring); +} + + +/** + Map Caller-supplied TxBuf buffer to the device-mapped address + + @param[in] Dev The VNET_DEV driver instance which wants to + map the Tx packet. + @param[in] Buffer The system physical address of TxBuf + @param[in] NumberOfBytes Number of bytes to map + @param[out] DeviceAddress The resulting device address for the bus + master access. + + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to + a lack of resources. + @return Status codes from + VirtioMapAllBytesInSharedBuffer() + @retval EFI_SUCCESS Caller-supplied buffer is successfully mapped. +*/ +EFI_STATUS +EFIAPI +VirtioNetMapTxBuf ( + IN VNET_DEV *Dev, + IN VOID *Buffer, + IN UINTN NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress + ) +{ + EFI_STATUS Status; + TX_BUF_MAP_INFO *TxBufMapInfo; + EFI_PHYSICAL_ADDRESS Address; + VOID *Mapping; + + TxBufMapInfo = AllocatePool (sizeof (*TxBufMapInfo)); + if (TxBufMapInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = VirtioMapAllBytesInSharedBuffer ( + Dev->VirtIo, + VirtioOperationBusMasterRead, + Buffer, + NumberOfBytes, + &Address, + &Mapping + ); + if (EFI_ERROR (Status)) { + goto FreeTxBufMapInfo; + } + + TxBufMapInfo->Buffer = Buffer; + TxBufMapInfo->DeviceAddress = Address; + TxBufMapInfo->BufMap = Mapping; + + Status = OrderedCollectionInsert ( + Dev->TxBufCollection, + NULL, + TxBufMapInfo + ); + switch (Status) { + case EFI_OUT_OF_RESOURCES: + goto UnmapTxBuf; + case EFI_ALREADY_STARTED: + // + // This should never happen: it implies + // + // - an identity-mapping VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer() + // implementation -- which is fine, + // + // - and an SNP client that queues multiple instances of the exact same + // buffer address with SNP.Transmit() -- which is undefined behavior, + // based on the TxBuf language in UEFI-2.7, + // EFI_SIMPLE_NETWORK.GetStatus(). + // + ASSERT (FALSE); + Status = EFI_INVALID_PARAMETER; + goto UnmapTxBuf; + default: + ASSERT_EFI_ERROR (Status); + break; + } + + *DeviceAddress = Address; + return EFI_SUCCESS; + +UnmapTxBuf: + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping); + +FreeTxBufMapInfo: + FreePool (TxBufMapInfo); + return Status; +} + +/** + Unmap (aka reverse mapping) device mapped TxBuf buffer to the system + physical address + + @param[in] Dev The VNET_DEV driver instance which wants to + reverse- and unmap the Tx packet. + @param[out] Buffer The system physical address of TxBuf + @param[in] DeviceAddress The device address for the TxBuf + + @retval EFI_INVALID_PARAMETER The DeviceAddress is not mapped + @retval EFI_SUCCESS The TxBuf at DeviceAddress has been unmapped, + and Buffer has been set to TxBuf's system + physical address. + +*/ +EFI_STATUS +EFIAPI +VirtioNetUnmapTxBuf ( + IN VNET_DEV *Dev, + OUT VOID **Buffer, + IN EFI_PHYSICAL_ADDRESS DeviceAddress + ) +{ + ORDERED_COLLECTION_ENTRY *Entry; + TX_BUF_MAP_INFO *TxBufMapInfo; + VOID *UserStruct; + + Entry = OrderedCollectionFind (Dev->TxBufCollection, &DeviceAddress); + if (Entry == NULL) { + return EFI_INVALID_PARAMETER; + } + + OrderedCollectionDelete (Dev->TxBufCollection, Entry, &UserStruct); + + TxBufMapInfo = UserStruct; + + *Buffer = TxBufMapInfo->Buffer; + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap); + FreePool (TxBufMapInfo); + + return EFI_SUCCESS; +} + +/** + Comparator function for two TX_BUF_MAP_INFO objects. + + @param[in] UserStruct1 Pointer to the first TX_BUF_MAP_INFO object. + + @param[in] UserStruct2 Pointer to the second TX_BUF_MAP_INFO object. + + @retval <0 If UserStruct1 compares less than UserStruct2. + + @retval 0 If UserStruct1 compares equal to UserStruct2. + + @retval >0 If UserStruct1 compares greater than UserStruct2. +*/ +INTN +EFIAPI +VirtioNetTxBufMapInfoCompare ( + IN CONST VOID *UserStruct1, + IN CONST VOID *UserStruct2 + ) +{ + CONST TX_BUF_MAP_INFO *MapInfo1; + CONST TX_BUF_MAP_INFO *MapInfo2; + + MapInfo1 = UserStruct1; + MapInfo2 = UserStruct2; + + return MapInfo1->DeviceAddress < MapInfo2->DeviceAddress ? -1 : + MapInfo1->DeviceAddress > MapInfo2->DeviceAddress ? 1 : + 0; +} + +/** + Compare a standalone DeviceAddress against a TX_BUF_MAP_INFO object + containing an embedded DeviceAddress. + + @param[in] StandaloneKey Pointer to DeviceAddress, which has type + EFI_PHYSICAL_ADDRESS. + + @param[in] UserStruct Pointer to the TX_BUF_MAP_INFO object with the + embedded DeviceAddress. + + @retval <0 If StandaloneKey compares less than UserStruct's key. + + @retval 0 If StandaloneKey compares equal to UserStruct's key. + + @retval >0 If StandaloneKey compares greater than UserStruct's key. +**/ +INTN +EFIAPI +VirtioNetTxBufDeviceAddressCompare ( + IN CONST VOID *StandaloneKey, + IN CONST VOID *UserStruct + ) +{ + CONST EFI_PHYSICAL_ADDRESS *DeviceAddress; + CONST TX_BUF_MAP_INFO *MapInfo; + + DeviceAddress = StandaloneKey; + MapInfo = UserStruct; + + return *DeviceAddress < MapInfo->DeviceAddress ? -1 : + *DeviceAddress > MapInfo->DeviceAddress ? 1 : + 0; +} -- cgit 1.2.3-korg