/** @file Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved. Copyright (c) 2020, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "DwEmacSnpDxe.h" #include #include #include #include #include #include STATIC EFI_STATUS EFIAPI DriverSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ); STATIC EFI_STATUS EFIAPI DriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ); STATIC EFI_STATUS EFIAPI DriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ); STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = { DriverSupported, DriverStart, DriverStop, 0xa, NULL, NULL }; STATIC SIMPLE_NETWORK_DEVICE_PATH PathTemplate = { { { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, {(UINT8)(sizeof (MAC_ADDR_DEVICE_PATH)), (UINT8)((sizeof (MAC_ADDR_DEVICE_PATH)) >> 8)} }, {{ 0 }}, 0 }, { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} } }; STATIC EFI_STATUS EFIAPI DriverSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { NON_DISCOVERABLE_DEVICE *Dev; EFI_STATUS Status; // Connect to the non-discoverable device Status = gBS->OpenProtocol (Controller, &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Dev, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER); if (EFI_ERROR (Status)) { return Status; } // Clean up. gBS->CloseProtocol (Controller, &gEdkiiNonDiscoverableDeviceProtocolGuid, This->DriverBindingHandle, Controller); return Status; } STATIC EFI_STATUS EFIAPI DriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; SIMPLE_NETWORK_DRIVER *Snp; EFI_SIMPLE_NETWORK_MODE *SnpMode; SIMPLE_NETWORK_DEVICE_PATH *DevicePath; UINT64 DefaultMacAddress; EFI_MAC_ADDRESS *SwapMacAddressPtr; UINTN DescriptorSize; UINTN BufferSize; UINTN *RxBufferAddr; EFI_PHYSICAL_ADDRESS RxBufferAddrMap; // Allocate Resources Snp = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (SIMPLE_NETWORK_DRIVER))); if (Snp == NULL) { return EFI_OUT_OF_RESOURCES; } Status = gBS->OpenProtocol (Controller, &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Snp->Dev, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER); // Size for descriptor DescriptorSize = EFI_PAGES_TO_SIZE (sizeof (DESIGNWARE_HW_DESCRIPTOR)); // Size for transmit and receive buffer BufferSize = ETH_BUFSIZE; for (int Index=0; Index < DESC_NUM; Index++) { //DMA TxdescRing allocate buffer and map Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (sizeof (DESIGNWARE_HW_DESCRIPTOR)), (VOID *)&Snp->MacDriver.TxdescRing[Index]); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a () for TxdescRing: %r\n", __FUNCTION__, Status)); return Status; } Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp->MacDriver.TxdescRing[Index], &DescriptorSize, &Snp->MacDriver.TxdescRingMap[Index].AddrMap, &Snp->MacDriver.TxdescRingMap[Index].Mapping); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a () for TxdescRing: %r\n", __FUNCTION__, Status)); return Status; } // DMA RxdescRing allocte buffer and map Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (sizeof (DESIGNWARE_HW_DESCRIPTOR)), (VOID *)&Snp->MacDriver.RxdescRing[Index]); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a () for RxdescRing: %r\n", __FUNCTION__, Status)); return Status; } Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp->MacDriver.RxdescRing[Index], &DescriptorSize, &Snp->MacDriver.RxdescRingMap[Index].AddrMap, &Snp->MacDriver.RxdescRingMap[Index].Mapping); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a () for RxdescRing: %r\n", __FUNCTION__, Status)); return Status; } //DMA mapping for receive buffer RxBufferAddr = (UINTN*)((UINTN)Snp->MacDriver.RxBuffer + (Index * BufferSize)); Status = DmaMap (MapOperationBusMasterWrite, (VOID *) RxBufferAddr, &BufferSize, &RxBufferAddrMap, &Snp->MacDriver.RxBufNum[Index].Mapping); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a () for Rxbuffer: %r\n", __FUNCTION__, Status)); return Status; } Snp->MacDriver.RxBufNum[Index].AddrMap= RxBufferAddrMap; } DevicePath = (SIMPLE_NETWORK_DEVICE_PATH*)AllocateCopyPool (sizeof (SIMPLE_NETWORK_DEVICE_PATH), &PathTemplate); if (DevicePath == NULL) { return EFI_OUT_OF_RESOURCES; } // Initialized signature (used by INSTANCE_FROM_SNP_THIS macro) Snp->Signature = SNP_DRIVER_SIGNATURE; EfiInitializeLock (&Snp->Lock, TPL_CALLBACK); // Initialize pointers SnpMode = &Snp->SnpMode; Snp->Snp.Mode = SnpMode; // Get MAC controller base address Snp->MacBase = (UINTN)Snp->Dev->Resources[0].AddrRangeMin; // Assign fields and func pointers Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; Snp->Snp.WaitForPacket = NULL; Snp->Snp.Initialize = SnpInitialize; Snp->Snp.Start = SnpStart; Snp->Snp.Stop = SnpStop; Snp->Snp.Reset = SnpReset; Snp->Snp.Shutdown = SnpShutdown; Snp->Snp.ReceiveFilters = SnpReceiveFilters; Snp->Snp.StationAddress = SnpStationAddress; Snp->Snp.Statistics = SnpStatistics; Snp->Snp.MCastIpToMac = SnpMcastIptoMac; Snp->Snp.NvData = SnpNvData; Snp->Snp.GetStatus = SnpGetStatus; Snp->Snp.Transmit = SnpTransmit; Snp->Snp.Receive = SnpReceive; Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASE); if (Snp->RecycledTxBuf == NULL) { Status = EFI_OUT_OF_RESOURCES; } Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASE; Snp->RecycledTxBufCount = 0; // Start completing simple network mode structure SnpMode->State = EfiSimpleNetworkStopped; SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes SnpMode->MediaHeaderSize = sizeof (ETHER_HEAD); SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes) SnpMode->NvRamSize = 0; // No NVRAM with this device SnpMode->NvRamAccessSize = 0; // No NVRAM with this device // Update network mode information SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; // We do not intend to receive anything for the time being. SnpMode->ReceiveFilterSetting = 0; // EMAC has 64bit hash table, can filter 64 MCast MAC Addresses SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT; SnpMode->MCastFilterCount = 0; ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof (EFI_MAC_ADDRESS)); // Set the interface type (1: Ethernet or 6: IEEE 802 Networks) SnpMode->IfType = NET_IFTYPE_ETHERNET; // Mac address is changeable as it is loaded from erasable memory SnpMode->MacAddressChangeable = TRUE; // Can only transmit one packet at a time SnpMode->MultipleTxSupported = FALSE; // MediaPresent checks for cable connection and partner link SnpMode->MediaPresentSupported = TRUE; SnpMode->MediaPresent = FALSE; // Set broadcast address SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF); //Set current address DefaultMacAddress = Snp->Dev->Resources[1].AddrRangeMin; // Swap PCD human readable form to correct endianess SwapMacAddressPtr = (EFI_MAC_ADDRESS *) &DefaultMacAddress; SnpMode->CurrentAddress.Addr[0] = SwapMacAddressPtr->Addr[5]; SnpMode->CurrentAddress.Addr[1] = SwapMacAddressPtr->Addr[4]; SnpMode->CurrentAddress.Addr[2] = SwapMacAddressPtr->Addr[3]; SnpMode->CurrentAddress.Addr[3] = SwapMacAddressPtr->Addr[2]; SnpMode->CurrentAddress.Addr[4] = SwapMacAddressPtr->Addr[1]; SnpMode->CurrentAddress.Addr[5] = SwapMacAddressPtr->Addr[0]; // Assign fields for device path CopyMem (&DevicePath->MacAddrDP.MacAddress, &Snp->Snp.Mode->CurrentAddress, NET_ETHER_ADDR_LEN); DevicePath->MacAddrDP.IfType = Snp->Snp.Mode->IfType; Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSimpleNetworkProtocolGuid, &(Snp->Snp), &gEfiDevicePathProtocolGuid, DevicePath, NULL ); if (EFI_ERROR(Status)) { gBS->CloseProtocol (Controller, &gEdkiiNonDiscoverableDeviceProtocolGuid, This->DriverBindingHandle, Controller); FreePages (Snp, EFI_SIZE_TO_PAGES (sizeof (SIMPLE_NETWORK_DRIVER))); } else { Snp->ControllerHandle = Controller; } return Status; } STATIC EFI_STATUS EFIAPI DriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol; SIMPLE_NETWORK_DRIVER *Snp; Status = gBS->HandleProtocol ( Controller, &gEfiSimpleNetworkProtocolGuid, (VOID **)&SnpProtocol ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a (): HandleProtocol: %r\n", __FUNCTION__, Status)); return Status; } Snp = INSTANCE_FROM_SNP_THIS(SnpProtocol); Status = gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleNetworkProtocolGuid, &Snp->Snp, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a (): UninstallMultipleProtocolInterfaces: %r\n", __FUNCTION__, Status)); return Status; } FreePool (Snp->RecycledTxBuf); FreePages (Snp, EFI_SIZE_TO_PAGES (sizeof (SIMPLE_NETWORK_DRIVER))); return Status; } /** UEFI Driver Entry Point API @param ImageHandle EFI_HANDLE. @param SystemTable EFI_SYSTEM_TABLE. @return EFI_SUCCESS Success. EFI_DEVICE_ERROR Fail. **/ EFI_STATUS EFIAPI DwEmacSnpDxeEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; Status = EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, &mDriverBinding, ImageHandle, &gSnpComponentName, &gSnpComponentName2 ); return Status; }