summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Library/DxeNetLib
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-24 08:06:37 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-24 08:06:37 +0000
commit8a67d61da4d5a8f08a656cbeea2d902d0ad9042a (patch)
tree6618049196a9f4a206b8d6e42fb8b67a71558503 /MdeModulePkg/Library/DxeNetLib
parentf9bef4b3ac2bf3bd5f79313f772519800761f104 (diff)
downloadedk2-platforms-8a67d61da4d5a8f08a656cbeea2d902d0ad9042a.tar.xz
Import SnpDxe, Tcp4Dxe, Udp4Dxe and MnpDxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3416 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Library/DxeNetLib')
-rw-r--r--MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf27
-rw-r--r--MdeModulePkg/Library/DxeNetLib/NetDebug.c536
2 files changed, 545 insertions, 18 deletions
diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
index be9ff1b379..3ae0a04ee4 100644
--- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
+++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
@@ -35,6 +35,7 @@
[Sources.common]
DxeNetLib.c
NetBuffer.c
+ NetDebug.c
[Packages]
MdePkg/MdePkg.dec
@@ -42,25 +43,15 @@
[LibraryClasses]
- MemoryAllocationLib
- UefiLib
- BaseLib
- UefiBootServicesTableLib
- UefiRuntimeServicesTableLib
- BaseMemoryLib
- DebugLib
- PrintLib
-
+ NetLib
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+ MemoryAllocationLib
[Protocols]
- gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
- gEfiDriverDiagnosticsProtocolGuid # PROTOCOL ALWAYS_CONSUMED
- gEfiUdp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
- gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
- gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
- gEfiDriverConfigurationProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
- gEfiDriverBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
- gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
- gEfiComponentNameProtocolGuid # PROTOCOL ALWAYS_CONSUMED
diff --git a/MdeModulePkg/Library/DxeNetLib/NetDebug.c b/MdeModulePkg/Library/DxeNetLib/NetDebug.c
new file mode 100644
index 0000000000..afcc1b3b42
--- /dev/null
+++ b/MdeModulePkg/Library/DxeNetLib/NetDebug.c
@@ -0,0 +1,536 @@
+/** @file
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ NetDebug.c
+
+Abstract:
+
+ Network debug facility. The debug information is wrapped in
+ SYSLOG packets, then sent over SNP. This debug facility can't
+ be used by SNP. Apply caution when used in MNP and non-network
+ module because SNP is most likely not "thread safe". We assume
+ that the SNP supports the EHTERNET.
+
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Protocol/SimpleNetwork.h>
+
+#include <Library/BaseLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PrintLib.h>
+
+
+//
+// Any error level digitally larger than mNetDebugLevelMax
+// will be silently discarded.
+//
+UINTN mNetDebugLevelMax = NETDEBUG_LEVEL_ERROR;
+UINT32 mSyslogPacketSeq = 0xDEADBEEF;
+
+//
+// You can change mSyslogDstMac mSyslogDstIp and mSyslogSrcIp
+// here to direct the syslog packets to the syslog deamon. The
+// default is broadcast to both the ethernet and IP.
+//
+UINT8 mSyslogDstMac [NET_ETHER_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+UINT32 mSyslogDstIp = 0xffffffff;
+UINT32 mSyslogSrcIp = 0;
+
+UINT8 *
+MonthName[] = {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+};
+
+
+/**
+ Locate the handles that support SNP, then open one of them
+ to send the syslog packets. The caller isn't required to close
+ the SNP after use because the SNP is opened by HandleProtocol.
+
+ None
+
+ @return The point to SNP if one is properly openned. Otherwise NULL
+
+**/
+EFI_SIMPLE_NETWORK_PROTOCOL *
+SyslogLocateSnp (
+ VOID
+ )
+{
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ UINTN HandleCount;
+ UINTN Index;
+
+ //
+ // Locate the handles which has SNP installed.
+ //
+ Handles = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleNetworkProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+
+ if (EFI_ERROR (Status) || (HandleCount == 0)) {
+ return NULL;
+ }
+
+ //
+ // Try to open one of the ethernet SNP protocol to send packet
+ //
+ Snp = NULL;
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiSimpleNetworkProtocolGuid,
+ (VOID **) &Snp
+ );
+
+ if ((Status == EFI_SUCCESS) && (Snp != NULL) &&
+ (Snp->Mode->IfType == NET_IFTYPE_ETHERNET) &&
+ (Snp->Mode->MaxPacketSize >= NET_SYSLOG_PACKET_LEN)) {
+
+ break;
+ }
+
+ Snp = NULL;
+ }
+
+ gBS->FreePool (Handles);
+ return Snp;
+}
+
+
+/**
+ Transmit a syslog packet synchronously through SNP. The Packet
+ already has the ethernet header prepended. This function should
+ fill in the source MAC because it will try to locate a SNP each
+ time it is called to avoid the problem if SNP is unloaded.
+ This code snip is copied from MNP.
+
+ @param Packet The Syslog packet
+ @param Length The length of the packet
+
+ @retval EFI_DEVICE_ERROR Failed to locate a usable SNP protocol
+ @retval EFI_TIMEOUT Timeout happened to send the packet.
+ @retval EFI_SUCCESS Packet is sent.
+
+**/
+EFI_STATUS
+SyslogSendPacket (
+ IN UINT8 *Packet,
+ IN UINT32 Length
+ )
+{
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
+ ETHER_HEAD *Ether;
+ EFI_STATUS Status;
+ EFI_EVENT TimeoutEvent;
+ UINT8 *TxBuf;
+
+ Snp = SyslogLocateSnp ();
+
+ if (Snp == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Ether = (ETHER_HEAD *) Packet;
+ CopyMem (Ether->SrcMac, Snp->Mode->CurrentAddress.Addr, NET_ETHER_ADDR_LEN);
+
+ //
+ // Start the timeout event.
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_NOTIFY,
+ NULL,
+ NULL,
+ &TimeoutEvent
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->SetTimer (TimeoutEvent, TimerRelative, NET_SYSLOG_TX_TIMEOUT);
+
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ for (;;) {
+ //
+ // Transmit the packet through SNP.
+ //
+ Status = Snp->Transmit (Snp, 0, Length, Packet, NULL, NULL, NULL);
+
+ if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ //
+ // If Status is EFI_SUCCESS, the packet is put in the transmit queue.
+ // if Status is EFI_NOT_READY, the transmit engine of the network
+ // interface is busy. Both need to sync SNP.
+ //
+ TxBuf = NULL;
+
+ do {
+ //
+ // Get the recycled transmit buffer status.
+ //
+ Snp->GetStatus (Snp, NULL, &TxBuf);
+
+ if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
+ Status = EFI_TIMEOUT;
+ break;
+ }
+
+ } while (TxBuf == NULL);
+
+ if ((Status == EFI_SUCCESS) || (Status == EFI_TIMEOUT)) {
+ break;
+ }
+
+ //
+ // Status is EFI_NOT_READY. Restart the timer event and
+ // call Snp->Transmit again.
+ //
+ gBS->SetTimer (TimeoutEvent, TimerRelative, NET_SYSLOG_TX_TIMEOUT);
+ }
+
+ gBS->SetTimer (TimeoutEvent, TimerCancel, 0);
+
+ON_EXIT:
+ gBS->CloseEvent (TimeoutEvent);
+ return Status;
+}
+
+
+/**
+ Compute checksum for a bulk of data. This code is copied from the
+ Netbuffer library.
+
+ @param Bulk Pointer to the data.
+ @param Len Length of the data, in bytes.
+
+ @retval UINT16 The computed checksum.
+
+**/
+UINT16
+SyslogChecksum (
+ IN UINT8 *Bulk,
+ IN UINT32 Len
+ )
+{
+ register UINT32 Sum;
+
+ Sum = 0;
+
+ while (Len > 1) {
+ Sum += *(UINT16 *) Bulk;
+ Bulk += 2;
+ Len -= 2;
+ }
+
+ //
+ // Add left-over byte, if any
+ //
+ if (Len > 0) {
+ Sum += *(UINT8 *) Bulk;
+ }
+
+ //
+ // Fold 32-bit sum to 16 bits
+ //
+ while (Sum >> 16) {
+ Sum = (Sum & 0xffff) + (Sum >> 16);
+ }
+
+ return (UINT16) ~Sum;
+}
+
+
+/**
+ Build a syslog packet, including the Ethernet/Ip/Udp headers
+ and user's message.
+
+ @param Buf The buffer to put the packet data
+ @param BufLen The lenght of the Buf
+ @param Level Syslog servity level
+ @param Module The module that generates the log
+ @param File The file that contains the current log
+ @param Line The line of code in the File that contains the
+ current log
+ @param Message The log message
+
+ @return The length of the syslog packet built.
+
+**/
+UINT32
+SyslogBuildPacket (
+ UINT8 *Buf,
+ UINT32 BufLen,
+ UINT32 Level,
+ UINT8 *Module,
+ UINT8 *File,
+ UINT32 Line,
+ UINT8 *Message
+ )
+{
+ ETHER_HEAD *Ether;
+ IP4_HEAD *Ip4;
+ EFI_UDP4_HEADER *Udp4;
+ EFI_TIME Time;
+ UINT32 Pri;
+ UINT32 Len;
+
+ //
+ // Fill in the Ethernet header. Leave alone the source MAC.
+ // SyslogSendPacket will fill in the address for us.
+ //
+ Ether = (ETHER_HEAD *) Buf;
+ CopyMem (Ether->DstMac, mSyslogDstMac, NET_ETHER_ADDR_LEN);
+ ZeroMem (Ether->SrcMac, NET_ETHER_ADDR_LEN);
+
+ Ether->EtherType = HTONS (0x0800); // IP protocol
+
+ Buf += sizeof (ETHER_HEAD);
+ BufLen -= sizeof (ETHER_HEAD);
+
+ //
+ // Fill in the IP header
+ //
+ Ip4 = (IP4_HEAD *) Buf;
+ Ip4->HeadLen = 5;
+ Ip4->Ver = 4;
+ Ip4->Tos = 0;
+ Ip4->TotalLen = 0;
+ Ip4->Id = (UINT16) mSyslogPacketSeq;
+ Ip4->Fragment = 0;
+ Ip4->Ttl = 16;
+ Ip4->Protocol = 0x11;
+ Ip4->Checksum = 0;
+ Ip4->Src = mSyslogSrcIp;
+ Ip4->Dst = mSyslogDstIp;
+
+ Buf += sizeof (IP4_HEAD);
+ BufLen -= sizeof (IP4_HEAD);
+
+ //
+ // Fill in the UDP header, Udp checksum is optional. Leave it zero.
+ //
+ Udp4 = (EFI_UDP4_HEADER*) Buf;
+ Udp4->SrcPort = HTONS (514);
+ Udp4->DstPort = HTONS (514);
+ Udp4->Length = 0;
+ Udp4->Checksum = 0;
+
+ Buf += sizeof (EFI_UDP4_HEADER);
+ BufLen -= sizeof (EFI_UDP4_HEADER);
+
+ //
+ // Build the syslog message body with <PRI> Timestamp machine module Message
+ //
+ Pri = ((NET_SYSLOG_FACILITY & 31) << 3) | (Level & 7);
+ gRT->GetTime (&Time, NULL);
+
+ //
+ // Use %a to format the ASCII strings, %s to format UNICODE strings
+ //
+ Len = 0;
+ Len += (UINT32) AsciiSPrint (
+ Buf,
+ BufLen,
+ "<%d> %a %d %d:%d:%d ",
+ Pri,
+ MonthName [Time.Month-1],
+ Time.Day,
+ Time.Hour,
+ Time.Minute,
+ Time.Second
+ );
+ Len--;
+
+ Len += (UINT32) AsciiSPrint (
+ Buf + Len,
+ BufLen - Len,
+ "Tiano %a: %a (Line: %d File: %a)",
+ Module,
+ Message,
+ Line,
+ File
+ );
+ Len--;
+
+ //
+ // OK, patch the IP length/checksum and UDP length fields.
+ //
+ Len += sizeof (EFI_UDP4_HEADER);
+ Udp4->Length = HTONS ((UINT16) Len);
+
+ Len += sizeof (IP4_HEAD);
+ Ip4->TotalLen = HTONS ((UINT16) Len);
+ Ip4->Checksum = SyslogChecksum ((UINT8 *) Ip4, sizeof (IP4_HEAD));
+
+ return Len + sizeof (ETHER_HEAD);
+}
+
+
+/**
+ Allocate a buffer, then format the message to it. This is a
+ help function for the NET_DEBUG_XXX macros. The PrintArg of
+ these macros treats the variable length print parameters as a
+ single parameter, and pass it to the NetDebugASPrint. For
+ example, NET_DEBUG_TRACE ("Tcp", ("State transit to %a\n", Name))
+ if extracted to:
+ NetDebugOutput (
+ NETDEBUG_LEVEL_TRACE,
+ "Tcp",
+ __FILE__,
+ __LINE__,
+ NetDebugASPrint ("State transit to %a\n", Name)
+ )
+ This is exactly what we want.
+
+ @param Format The ASCII format string.
+ @param ... The variable length parameter whose format is
+ determined by the Format string.
+
+ @return The buffer containing the formatted message, or NULL if failed to
+ @return allocate memory.
+
+**/
+UINT8 *
+NetDebugASPrint (
+ UINT8 *Format,
+ ...
+ )
+{
+ VA_LIST Marker;
+ UINT8 *Buf;
+
+ Buf = AllocatePool (NET_DEBUG_MSG_LEN);
+
+ if (Buf == NULL) {
+ return NULL;
+ }
+
+ VA_START (Marker, Format);
+ AsciiVSPrint (Buf, NET_DEBUG_MSG_LEN, Format, Marker);
+ VA_END (Marker);
+
+ return Buf;
+}
+
+
+/**
+ Output a debug message to syslog. This function will locate a
+ instance of SNP then send the message through it. Because it
+ isn't open the SNP BY_DRIVER, apply caution when using it.
+
+ @param Level The servity level of the message.
+ @param Module The Moudle that generates the log.
+ @param File The file that contains the log.
+ @param Line The exact line that contains the log.
+ @param Message The user message to log.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet
+ @retval EFI_SUCCESS The log is discard because that it is more verbose
+ than the mNetDebugLevelMax. Or, it has been sent
+ out.
+
+**/
+EFI_STATUS
+NetDebugOutput (
+ UINT32 Level,
+ UINT8 *Module,
+ UINT8 *File,
+ UINT32 Line,
+ UINT8 *Message
+ )
+{
+ UINT8 *Packet;
+ UINT32 Len;
+ EFI_STATUS Status;
+
+ //
+ // Check whether the message should be sent out
+ //
+ if (Message == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (Level > mNetDebugLevelMax) {
+ Status = EFI_SUCCESS;
+ goto ON_EXIT;
+ }
+
+ //
+ // Allocate a maxium of 1024 bytes, the caller should ensure
+ // that the message plus the ethernet/ip/udp header is shorter
+ // than this
+ //
+ Packet = AllocatePool (NET_SYSLOG_PACKET_LEN);
+
+ if (Packet == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ //
+ // Build the message: Ethernet header + IP header + Udp Header + user data
+ //
+ Len = SyslogBuildPacket (
+ Packet,
+ NET_SYSLOG_PACKET_LEN,
+ Level,
+ Module,
+ File,
+ Line,
+ Message
+ );
+
+ mSyslogPacketSeq++;
+ Status = SyslogSendPacket (Packet, Len);
+ gBS->FreePool (Packet);
+
+ON_EXIT:
+ gBS->FreePool (Message);
+ return Status;
+}