Newer
Older
AMI-Aptio-BIOS-Reversed / Build / SnpDxe / SnpDxe.c
@Ajax Dong Ajax Dong 2 days ago 100 KB Restructure the repo
/** @file
  SnpDxe.c - Simple Network Protocol DXE Driver Implementation

  AMI SNP DXE driver implementing EFI_SIMPLE_NETWORK_PROTOCOL over
  an UNDI3.1 network interface.

  Source structure matches AMI NetworkPkg files:
    Snp.c, Start.c, Stop.c, Initialize.c, Reset.c,
    Shutdown.c, Receive_filters.c, Station_address.c,
    Statistics.c, Get_status.c, Transmit.c, Receive.c,
    Mcast_ip_to_mac.c, Nvdata.c, ComponentName.c
  plus library wrappers and ACPI I/O helpers compiled into the same module.

  Decompiled from: SnpDxe.efi
  Build path: e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\Build\\SnpDxe\\DEBUG\\SnpDxe.pdb

  Copyright (c) AMI Corporation. All rights reserved.
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include "SnpDxe.h"

//
// Global variable definitions
//
EFI_HANDLE                     gImageHandle = NULL;
EFI_SYSTEM_TABLE               *gSystemTable = NULL;
EFI_BOOT_SERVICES              *gBootServices = NULL;
EFI_RUNTIME_SERVICES           *gRuntimeServices = NULL;
SNP_DRIVER                     *gSnpDriver = NULL;
VOID                           *gHobList = NULL;

//
// ============================================================================
// Internal Memory Operations (replacement for BaseMemoryLib)
// ============================================================================

/**
  Fills a buffer with zeros using 8-byte aligned stores.

  @param  Buffer  Pointer to the buffer to zero.
  @param  Length  Size of the buffer in bytes.

  @return Pointer to Buffer.
**/
VOID *
EFIAPI
InternalZeroMem (
  VOID    *Buffer,
  UINTN   Length
  )
{
  // Zero out 8 bytes at a time for alignment
  SetMem (Buffer, Length, 0);
  return Buffer;
}

/**
  Copies memory from source to destination with overlap handling.

  @param  Destination  Pointer to the destination buffer.
  @param  Source       Pointer to the source buffer.
  @param  Length       Number of bytes to copy.

  @return Pointer to Destination.
**/
VOID *
EFIAPI
InternalCopyMem (
  VOID    *Destination,
  CONST VOID *Source,
  UINTN   Length
  )
{
  return CopyMem (Destination, Source, Length);
}

/**
  Fills a buffer with a specified value.

  @param  Buffer  Pointer to the buffer to fill.
  @param  Count   Number of bytes to fill.
  @param  Value   Value to fill.

  @return Pointer to Buffer.
**/
VOID *
EFIAPI
InternalSetMem (
  VOID    *Buffer,
  UINTN   Count,
  UINT8   Value
  )
{
  return SetMem (Buffer, Count, Value);
}

/**
  Compares two memory buffers.

  @param  Buffer1  Pointer to the first buffer.
  @param  Buffer2  Pointer to the second buffer.
  @param  Length   Number of bytes to compare.

  @return 0 if equal, non-zero if different.
**/
INTN
EFIAPI
InternalCompareMem (
  CONST VOID  *Buffer1,
  CONST VOID  *Buffer2,
  UINTN       Length
  )
{
  return CompareMem (Buffer1, Buffer2, Length);
}

//
// ============================================================================
// Library Wrappers (self-contained, with debug assertions)
// ============================================================================

/**
  Wrapper for ZeroMem with assertion.
**/
VOID *
EFIAPI
SnpZeroMem (
  VOID   *Buffer,
  UINTN  Length
  )
{
  ASSERT (Buffer != NULL);
  return InternalZeroMem (Buffer, Length);
}

/**
  Wrapper for CopyMem with assertion.
**/
VOID *
EFIAPI
SnpCopyMem (
  VOID        *Destination,
  CONST VOID  *Source,
  UINTN       Length
  )
{
  ASSERT (Destination != NULL || Length == 0);
  ASSERT (Source != NULL || Length == 0);
  return InternalCopyMem (Destination, Source, Length);
}

/**
  Wrapper for SetMem with assertion.
**/
VOID *
EFIAPI
SnpSetMem (
  VOID   *Buffer,
  UINTN  Count,
  UINT8  Value
  )
{
  ASSERT (Buffer != NULL || Count == 0);
  return InternalSetMem (Buffer, Count, Value);
}

/**
  Wrapper for CompareMem with assertion.
**/
INTN
EFIAPI
SnpCompareMem (
  CONST VOID  *Buffer1,
  CONST VOID  *Buffer2,
  UINTN       Length
  )
{
  ASSERT (Buffer1 != NULL || Length == 0);
  ASSERT (Buffer2 != NULL || Length == 0);
  return InternalCompareMem (Buffer1, Buffer2, Length);
}

/**
  Allocates a pool buffer.

  @param  AllocationSize  Size of the allocation in bytes.

  @return Pointer to the allocated buffer, or NULL on failure.
**/
VOID *
EFIAPI
SnpAllocatePool (
  IN UINTN  AllocationSize
  )
{
  VOID  *Buffer;

  Buffer = NULL;
  gBootServices->AllocatePool (EfiBootServicesData, AllocationSize, &Buffer);
  return Buffer;
}

/**
  Allocates a pool buffer and copies data into it.

  @param  AllocationSize  Size of the allocation in bytes.
  @param  Buffer          Source data to copy.

  @return Pointer to the allocated buffer, or NULL on failure.
**/
VOID *
EFIAPI
SnpAllocateCopyPool (
  IN UINTN  AllocationSize,
  IN VOID   *Buffer
  )
{
  VOID  *NewBuffer;

  NewBuffer = SnpAllocatePool (AllocationSize);
  if (NewBuffer != NULL && Buffer != NULL && AllocationSize > 0) {
    SnpCopyMem (NewBuffer, Buffer, AllocationSize);
  }
  return NewBuffer;
}

/**
  Frees a pool buffer.

  @param  Buffer  Pointer to the buffer to free.
**/
VOID
EFIAPI
SnpFreePool (
  IN VOID  *Buffer
  )
{
  ASSERT (Buffer != NULL);
  gBootServices->FreePool (Buffer);
}

//
// ============================================================================
// String Operations
// ============================================================================

/**
  Returns the length of a Unicode string.

  @param  String  Pointer to the null-terminated Unicode string.

  @return Number of Unicode characters, not including the null terminator.
**/
UINTN
EFIAPI
SnpStrLen (
  IN CONST CHAR16  *String
  )
{
  UINTN  Length;

  ASSERT (String != NULL);

  Length = 0;
  if (String != NULL) {
    while (String[Length] != 0) {
      Length++;
    }
  }
  return Length;
}

/**
  Returns the length of an ASCII string.

  @param  String  Pointer to the null-terminated ASCII string.

  @return Number of ASCII characters, not including the null terminator.
**/
UINTN
EFIAPI
SnpAsciiStrLen (
  IN CONST CHAR8  *String
  )
{
  UINTN  Length;

  ASSERT (String != NULL);

  Length = 0;
  if (String != NULL) {
    while (String[Length] != 0) {
      Length++;
    }
  }
  return Length;
}

/**
  Safe Unicode string length (max length bounded).

  @param  String  Pointer to the null-terminated Unicode string.
  @param  MaxSize  Maximum number of characters to check.

  @return Number of Unicode characters, not including null terminator.
**/
UINTN
EFIAPI
SnpStrnLenS (
  IN CONST CHAR16  *String,
  IN UINTN         MaxSize
  )
{
  UINTN  Length;

  ASSERT (String != NULL);

  Length = 0;
  if (String != NULL) {
    while (String[Length] != 0 && Length < MaxSize) {
      Length++;
    }
  }
  return Length;
}

/**
  Safe ASCII string length (max length bounded).

  @param  String  Pointer to the null-terminated ASCII string.
  @param  MaxSize  Maximum number of characters to check.

  @return Number of ASCII characters, not including null terminator.
**/
UINTN
EFIAPI
SnpAsciiStrnLenS (
  IN CONST CHAR8  *String,
  IN UINTN        MaxSize
  )
{
  UINTN  Length;

  ASSERT (String != NULL);

  Length = 0;
  if (String != NULL) {
    while (String[Length] != 0 && Length < MaxSize) {
      Length++;
    }
  }
  return Length;
}

/**
  Performs a case-sensitive comparison of two ASCII strings.

  @param  FirstString   Pointer to the first ASCII string.
  @param  SecondString  Pointer to the second ASCII string.

  @retval 0   FirstString equals SecondString.
  @retval <0  FirstString is less than SecondString.
  @retval >0  FirstString is greater than SecondString.
**/
INTN
EFIAPI
SnpAsciiStrCmp (
  IN CONST CHAR8  *FirstString,
  IN CONST CHAR8  *SecondString
  )
{
  ASSERT (FirstString != NULL);
  ASSERT (SecondString != NULL);

  while (*FirstString != '\0' && *FirstString == *SecondString) {
    FirstString++;
    SecondString++;
  }

  return (INTN)((UINT8)*FirstString - (UINT8)*SecondString);
}

/**
  Copies an ASCII string to a Unicode string.

  @param  Destination  Pointer to the destination Unicode buffer.
  @param  Source       Pointer to the source ASCII string.

  @return Pointer to Destination.
**/
CHAR16 *
EFIAPI
SnpStrCpyAscii (
  OUT CHAR16       *Destination,
  IN  CONST CHAR8  *Source
  )
{
  CHAR16  *DestPtr;

  ASSERT (Destination != NULL);
  ASSERT (Source != NULL);

  DestPtr = Destination;
  if (Destination != NULL && Source != NULL) {
    while (*Source != '\0') {
      *DestPtr++ = (CHAR16)*Source++;
    }
    *DestPtr = L'\0';
  }
  return Destination;
}

/**
  Converts an unsigned integer to an ASCII string.

  @param  Value   The unsigned integer value.
  @param  Buffer  Pointer to the output buffer.

  @return Length of the resulting string.
**/
UINTN
EFIAPI
SnpUtoA (
  IN  UINTN   Value,
  OUT CHAR8   *Buffer
  )
{
  CHAR8   Temp[20];
  UINTN   Index;
  UINTN   Length;

  ASSERT (Buffer != NULL);

  if (Buffer == NULL) {
    return 0;
  }

  Index = 0;
  if (Value == 0) {
    Temp[Index++] = '0';
  } else {
    while (Value > 0) {
      Temp[Index++] = (CHAR8)('0' + (Value % 10));
      Value /= 10;
    }
  }

  Length = Index;
  while (Index > 0) {
    *Buffer++ = Temp[--Index];
  }
  *Buffer = '\0';

  return Length;
}

//
// ============================================================================
// Linked List Operations
// ============================================================================

/**
  Checks if a LIST_ENTRY is valid.

  @param  ListEntry  Pointer to the list entry to check.

  @retval TRUE   The list entry is valid.
  @retval FALSE  The list entry is not valid.
**/
BOOLEAN
EFIAPI
SnpIsListValid (
  IN LIST_ENTRY  *ListEntry
  )
{
  ASSERT (ListEntry != NULL);

  if (ListEntry == NULL) {
    return FALSE;
  }

  return (BOOLEAN)(ListEntry->Flink != NULL && ListEntry->Blink != NULL);
}

/**
  Inserts a new entry at the tail of a doubly-linked list.

  @param  ListHead  Pointer to the list head.
  @param  Entry     Pointer to the entry to insert.
**/
VOID
EFIAPI
SnpInsertTailList (
  IN LIST_ENTRY  *ListHead,
  IN LIST_ENTRY  *Entry
  )
{
  ASSERT (ListHead != NULL);
  ASSERT (Entry != NULL);

  Entry->Flink = ListHead;
  Entry->Blink = ListHead->Blink;
  ListHead->Blink->Flink = Entry;
  ListHead->Blink = Entry;
}

/**
  Returns the first entry in a list.

  @param  List  Pointer to the list head.

  @return Pointer to the first list entry, or NULL if the list is empty.
**/
LIST_ENTRY *
EFIAPI
SnpGetFirstNode (
  IN LIST_ENTRY  *List
  )
{
  ASSERT (List != NULL);

  if (List == NULL || List->Flink == List) {
    return NULL;
  }

  return List->Flink;
}

/**
  Returns the next entry in a list.

  @param  List  Pointer to the list head.
  @param  Node  Pointer to the current node.

  @return Pointer to the next list entry.
**/
LIST_ENTRY *
EFIAPI
SnpGetNextNode (
  IN LIST_ENTRY  *List,
  IN LIST_ENTRY  *Node
  )
{
  ASSERT (List != NULL);
  ASSERT (Node != NULL);

  if (Node == NULL || Node->Flink == List) {
    return NULL;
  }

  return Node->Flink;
}

/**
  Checks if a list entry is the null entry (the list head).

  @param  List  Pointer to the list head.
  @param  Node  Pointer to the node to check.

  @retval TRUE   Node is the list head.
  @retval FALSE  Node is not the list head.
**/
BOOLEAN
EFIAPI
SnpIsNull (
  IN LIST_ENTRY  *List,
  IN LIST_ENTRY  *Node
  )
{
  ASSERT (List != NULL);
  ASSERT (Node != NULL);

  return (BOOLEAN)(Node == List);
}

/**
  Checks if a list is empty.

  @param  ListHead  Pointer to the list head.

  @retval TRUE   The list is empty.
  @retval FALSE  The list is not empty.
**/
BOOLEAN
EFIAPI
SnpIsListEmpty (
  IN LIST_ENTRY  *ListHead
  )
{
  ASSERT (ListHead != NULL);

  if (ListHead == NULL) {
    return TRUE;
  }

  return (BOOLEAN)(ListHead->Flink == ListHead);
}

/**
  Removes an entry from a doubly-linked list.

  @param  Entry  Pointer to the entry to remove.
**/
VOID
EFIAPI
SnpRemoveEntryList (
  IN LIST_ENTRY  *Entry
  )
{
  ASSERT (Entry != NULL);

  Entry->Flink->Blink = Entry->Blink;
  Entry->Blink->Flink = Entry->Flink;
}

//
// ============================================================================
// Debug and Assert Functions
// ============================================================================

/**
  Prints a debug message.

  @param  ErrorLevel  Debug error level.
  @param  Format      Print format string.
  @param  ...         Variable arguments.
**/
VOID
EFIAPI
SnpDebugPrint (
  IN UINTN       ErrorLevel,
  IN CONST CHAR8 *Format,
  ...
  )
{
  VA_LIST  Args;

  VA_START (Args, Format);
  if (gSystemTable != NULL && gSystemTable->ConOut != NULL) {
    gSystemTable->ConOut->OutputString (gSystemTable->ConOut, (CHAR16 *)Format);
  }
  VA_END (Args);
}

/**
  Asserts a condition; prints file/line/description and enters an infinite loop.

  @param  FileName     Pointer to the source file name string.
  @param  LineNumber   Line number of the assertion.
  @param  Description  Pointer to the assertion description string.
**/
VOID
EFIAPI
SnpDebugAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  )
{
  //
  // Print assertion information
  //
  SnpDebugPrint (
    0x80000000,
    "\nASSERT [SnpDxe] %a(%d): %a\n",
    FileName,
    LineNumber,
    Description
    );

  //
  // Deadlock to indicate fatal error
  //
  while (TRUE) {
    CpuDeadLoop ();
  }
}

//
// ============================================================================
// HOB and System Table Operations
// ============================================================================

/**
  Gets the HOB list from the system table GUID.

  @return Pointer to the HOB list, or NULL if not found.
**/
VOID *
EFIAPI
SnpGetHobList (
  VOID
  )
{
  EFI_HOB_HANDOFF_INFO_TABLE  *HobList;

  if (gHobList != NULL) {
    return gHobList;
  }

  //
  // Find HOB list via system table configuration table
  //
  HobList = NULL;
  if (gSystemTable != NULL) {
    UINTN  Index;
    for (Index = 0; Index < gSystemTable->NumberOfTableEntries; Index++) {
      if (CompareGuid (
            &gSystemTable->ConfigurationTable[Index].VendorGuid,
            &gEfiHobListGuid
            )) {
        HobList = (EFI_HOB_HANDOFF_INFO_TABLE *)gSystemTable->ConfigurationTable[Index].VendorTable;
        break;
      }
    }
  }

  gHobList = HobList;
  ASSERT (gHobList != NULL);
  return gHobList;
}

/**
  Gets a HOB from the system table.

  @return Pointer to the HOB from the system table.
**/
VOID *
EFIAPI
SnpGetHobFromSystemTable (
  VOID
  )
{
  return SnpGetHobList ();
}

/**
  Gets the image protection cookie from the system table.

  @param  ImageHandle  The image handle.

  @return Pointer to the image protection cookie.
**/
EFI_GUID *
EFIAPI
SnpGetImageProtectionCookie (
  IN EFI_HANDLE  ImageHandle
  )
{
  EFI_GUID  *Cookie;

  Cookie = NULL;

  if (gSystemTable != NULL) {
    UINTN  Index;
    for (Index = 0; Index < gSystemTable->NumberOfTableEntries; Index++) {
      if (CompareGuid (
            &gSystemTable->ConfigurationTable[Index].VendorGuid,
            &gEfiImageSecurityDatabaseGuid
            )) {
        Cookie = (EFI_GUID *)gSystemTable->ConfigurationTable[Index].VendorTable;
        break;
      }
    }
  }

  ASSERT (Cookie != NULL);
  return Cookie;
}

/**
  Compares two GUIDs for a partial match.

  @param  Guid1  Pointer to the first GUID.
  @param  Guid2  Pointer to the second GUID.

  @retval TRUE   The GUIDs match.
  @retval FALSE  The GUIDs do not match.
**/
BOOLEAN
EFIAPI
SnpCompareGuidPartial (
  IN CONST EFI_GUID  *Guid1,
  IN CONST EFI_GUID  *Guid2
  )
{
  if (Guid1 == NULL || Guid2 == NULL) {
    return FALSE;
  }

  return CompareGuid (Guid1, Guid2);
}

/**
  Checks if a protocol GUID matches.

  @param  ProtocolGuid  Pointer to the protocol GUID to check.

  @return TRUE if the protocol GUID matches the expected value.
**/
BOOLEAN
EFIAPI
SnpIsProtocolGuidMatch (
  IN EFI_GUID  *ProtocolGuid
  )
{
  return CompareGuid (ProtocolGuid, &gEfiSimpleNetworkProtocolGuid);
}

/**
  Creates a legacy boot event.

  @return EFI_STATUS.
**/
EFI_STATUS
EFIAPI
SnpCreateLegacyBootEvent (
  VOID
  )
{
  EFI_EVENT  Event;

  return gBootServices->CreateEvent (
                          EVT_SIGNAL_LEGACY_BOOT,
                          TPL_CALLBACK,
                          NULL,
                          NULL,
                          &Event
                          );
}

/**
  Reads an unaligned 64-bit value.

  @param  Address  Pointer to the potentially unaligned address.

  @return The 64-bit value.
**/
UINT64
EFIAPI
SnpReadUnaligned64 (
  IN CONST VOID  *Address
  )
{
  UINT64  Value;

  CopyMem (&Value, Address, sizeof (Value));
  return Value;
}

//
// ============================================================================
// Component Name Support
// ============================================================================

/**
  Parses a language string for Component Name protocol.

  @param  Language      Language string to parse.
  @param  SupportedLanguages  Supported languages list.

  @return EFI_STATUS.
**/
EFI_STATUS
EFIAPI
SnpComponentNameParseLanguage (
  IN  CHAR8  *Language,
  OUT CHAR8  **SupportedLanguages
  )
{
  //
  // Simple direct language comparison
  //
  if (Language == NULL || SupportedLanguages == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (SnpAsciiStrCmp (Language, "en") == 0 ||
      SnpAsciiStrCmp (Language, "eng") == 0) {
    *SupportedLanguages = "eng";
    return EFI_SUCCESS;
  }

  return EFI_UNSUPPORTED;
}

/**
  Adds a language to the supported languages list.

  @param  Language  Language to add.
**/
VOID
EFIAPI
SnpComponentNameAddLanguage (
  IN CHAR8  *Language
  )
{
  //
  // Stub - languages are predefined
  //
}

//
// ============================================================================
// Print Library
// ============================================================================

/**
  Simple formatted print (internal implementation).

  @param  Format  Format string.
  @param  ...     Variable arguments.
**/
VOID
EFIAPI
SnpPrintLib (
  IN CONST CHAR8  *Format,
  ...
  )
{
  VA_LIST  Args;

  VA_START (Args, Format);
  SnpPrintLibInternal (Format, Args);
  VA_END (Args);
}

/**
  Internal print library implementation (simplified).

  @param  Format  Format string.
  @param  VaList  Variable argument list.
**/
VOID
EFIAPI
SnpPrintLibInternal (
  IN CONST CHAR8  *Format,
  IN VA_LIST      VaList
  )
{
  //
  // Simplified print implementation that supports basic format specifiers.
  // The full implementation would handle %s, %d, %x, %r, %a, etc.
  //
  if (gSystemTable != NULL && gSystemTable->ConOut != NULL) {
    CHAR16  Buffer[256];
    CHAR16  *BufPtr;

    BufPtr = Buffer;
    while (*Format != '\0' && (UINTN)(BufPtr - Buffer) < sizeof(Buffer) / sizeof(CHAR16) - 1) {
      if (*Format == '%') {
        Format++;
        switch (*Format) {
        case 's':
          {
            CHAR16  *Str;
            Str = VA_ARG (VaList, CHAR16 *);
            if (Str != NULL) {
              while (*Str != '\0' && (UINTN)(BufPtr - Buffer) < sizeof(Buffer) / sizeof(CHAR16) - 1) {
                *BufPtr++ = *Str++;
              }
            }
          }
          break;

        case 'a':
          {
            CHAR8  *Str;
            Str = VA_ARG (VaList, CHAR8 *);
            if (Str != NULL) {
              while (*Str != '\0' && (UINTN)(BufPtr - Buffer) < sizeof(Buffer) / sizeof(CHAR16) - 1) {
                *BufPtr++ = (CHAR16)*Str++;
              }
            }
          }
          break;

        case 'd':
        case 'x':
          {
            UINTN  Value;
            Value = VA_ARG (VaList, UINTN);
            BufPtr += SnpUtoA (Value, Buffer);
          }
          break;

        case 'r':
          {
            EFI_STATUS  Status;
            Status = VA_ARG (VaList, EFI_STATUS);
            //
            // Print status code as hex
            //
            BufPtr += SnpUtoA ((UINTN)Status, Buffer);
          }
          break;

        default:
          break;
        }
      } else {
        *BufPtr++ = (CHAR16)*Format;
      }
      Format++;
    }
    *BufPtr = L'\0';

    gSystemTable->ConOut->OutputString (gSystemTable->ConOut, Buffer);
  }
}

/**
  Print function without format processing (direct string output).

  @param  String  String to output.
  @param  ...
**/
VOID
EFIAPI
SnpPrintLibNoFormat (
  IN CONST CHAR8  *String,
  ...
  )
{
  if (gSystemTable != NULL && gSystemTable->ConOut != NULL && String != NULL) {
    CHAR16  UnicodeBuffer[256];
    UINTN   Index;

    for (Index = 0; String[Index] != '\0' && Index < 255; Index++) {
      UnicodeBuffer[Index] = (CHAR16)String[Index];
    }
    UnicodeBuffer[Index] = L'\0';

    gSystemTable->ConOut->OutputString (gSystemTable->ConOut, UnicodeBuffer);
  }
}

/**
  Simple SPrint implementation.

  @param  Buffer  Output buffer.
  @param  BufferSize  Size of output buffer.
  @param  Format  Format string.
  @param  ...     Variable arguments.
**/
UINTN
EFIAPI
SnpSPrint (
  OUT CHAR16       *Buffer,
  IN  UINTN        BufferSize,
  IN  CONST CHAR16 *Format,
  ...
  )
{
  //
  // Simplified SPrint - just copy format string for now
  //
  if (Buffer != NULL && Format != NULL && BufferSize > 0) {
    UINTN  Index;
    for (Index = 0; Format[Index] != L'\0' && Index < BufferSize - 1; Index++) {
      Buffer[Index] = Format[Index];
    }
    Buffer[Index] = L'\0';
    return Index;
  }
  return 0;
}

//
// ============================================================================
// Callback Management
// ============================================================================

/**
  Registers a callback event for network interface notifications.

  @param  This   Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
  @param  Event  Event to register.
  @param  Tpl    TPL for the callback.

  @retval EFI_SUCCESS           Callback registered.
  @retval EFI_INVALID_PARAMETER Invalid parameter.
  @retval EFI_ALREADY_STARTED   Callback already exists.
  @retval EFI_OUT_OF_RESOURCES  Out of memory.
**/
EFI_STATUS
EFIAPI
SnpRegisterCallback (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN EFI_EVENT                    Event,
  IN EFI_TPL                      Tpl
  )
{
  SNP_DRIVER  *Snp;
  CALLBACK_ENTRY *Entry;

  if (This == NULL || Event == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  //
  // Check if callback already exists
  //
  Entry = (CALLBACK_ENTRY *)Snp->CallbackList.ForwardLink;
  while (Entry != &Snp->CallbackList) {
    if (Entry->Event == Event) {
      return EFI_ALREADY_STARTED;
    }
    Entry = (CALLBACK_ENTRY *)Entry->ForwardLink;
  }

  //
  // Allocate and add new callback entry
  //
  Entry = (CALLBACK_ENTRY *)SnpAllocatePool (sizeof (CALLBACK_ENTRY));
  if (Entry == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Entry->Event = Event;
  Entry->Tpl   = Tpl;
  InsertTailList (&Snp->CallbackList, &Entry->Link);

  return EFI_SUCCESS;
}

/**
  Unregisters a callback event.

  @param  This   Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
  @param  Event  Event to unregister.
  @param  Tpl    TPL of the callback.

  @retval EFI_SUCCESS           Callback unregistered.
  @retval EFI_INVALID_PARAMETER Invalid parameter.
  @retval EFI_NOT_STARTED       Callback not found.
**/
EFI_STATUS
EFIAPI
SnpUnregisterCallback (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN EFI_EVENT                    Event,
  IN EFI_TPL                      Tpl
  )
{
  SNP_DRIVER  *Snp;
  CALLBACK_ENTRY *Entry;

  if (This == NULL || Event == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  //
  // Find and remove callback entry
  //
  Entry = (CALLBACK_ENTRY *)Snp->CallbackList.ForwardLink;
  while (Entry != &Snp->CallbackList) {
    if (Entry->Event == Event) {
      RemoveEntryList (&Entry->Link);
      SnpFreePool (Entry);
      return EFI_SUCCESS;
    }
    Entry = (CALLBACK_ENTRY *)Entry->ForwardLink;
  }

  return EFI_NOT_STARTED;
}

/**
  Fires callbacks for a destroyed child handle.

  @param  Handle  Handle being destroyed.
**/
VOID
EFIAPI
SnpDestroyChild (
  IN EFI_HANDLE  Handle
  )
{
  SNP_DRIVER  *Snp;

  ASSERT (Handle != NULL);

  Snp = SNP_DRIVER_FROM_PROTOCOL (
          (EFI_SIMPLE_NETWORK_PROTOCOL *)Handle
          );

  //
  // Fire all registered callbacks
  //
  CALLBACK_ENTRY  *Entry;
  Entry = (CALLBACK_ENTRY *)Snp->CallbackList.ForwardLink;
  while (Entry != &Snp->CallbackList) {
    gBootServices->SignalEvent (Entry->Event);
    Entry = (CALLBACK_ENTRY *)Entry->ForwardLink;
  }
}

//
// ============================================================================
// ACPI I/O Callbacks
// ============================================================================

/**
  ACPI I/O check callback - checks if an event is signaled.

  @param  Context  SNP_DRIVER pointer.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpAcpiCheck (
  IN UINT64  Context
  )
{
  SNP_DRIVER  *Snp;

  Snp = (SNP_DRIVER *)Context;

  return gBootServices->CheckEvent (Snp->TimerEvent);
}

/**
  ACPI I/O lock acquire/release callback.

  @param  Lock    Lock value.
  @param  Acquire TRUE to acquire, FALSE to release.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpAcpiIoReadWrite (
  IN UINT64  Lock,
  IN BOOLEAN Acquire
  )
{
  //
  // Lock acquire/release using EFI TPL
  //
  if (Acquire) {
    gBS->RaiseTPL (TPL_NOTIFY);
  } else {
    gBS->RestoreTPL (TPL_APPLICATION);
  }

  return 0;
}

/**
  ACPI I/O port read/write callback with size dispatch.

  @param  Context     SNP_DRIVER pointer.
  @param  Write       TRUE for write, FALSE for read.
  @param  AddressSize Size of the I/O access (1, 2, 4, or 8 bytes).

  @return The read value or written value.
**/
UINT64
EFIAPI
SnpAcpiReadWrite (
  IN UINT64   Context,
  IN BOOLEAN  Write,
  IN UINT64   AddressSize
  )
{
  SNP_DRIVER  *Snp;
  UINTN       IoAddress;
  UINTN       AccessSize;

  Snp = (SNP_DRIVER *)Context;
  IoAddress = Snp->IoPortAddress;
  AccessSize = 0;

  //
  // Determine the access size
  //
  switch ((UINT8)AddressSize) {
  case 2:
    AccessSize = 1; // 16-bit
    break;
  case 4:
    AccessSize = 2; // 32-bit
    break;
  case 8:
    AccessSize = 3; // 64-bit
    break;
  case 1:
  default:
    AccessSize = 0; // 8-bit
    break;
  }

  //
  // Perform I/O read or write via the ACPI IO protocol
  //
  if (Snp->AcpiIo != NULL) {
    if (Write) {
      UINT8  WriteByte;

      WriteByte = (UINT8)Snp->IoDataValue;
      return Snp->AcpiIo->Io.Write (
                              Snp->AcpiIo,
                              (EFI_ACPI_IO_PROTOCOL_WIDTH)AccessSize,
                              IoAddress,
                              1,
                              &WriteByte
                              );
    } else {
      UINT8  ReadByte;

      ReadByte = 0;
      Snp->AcpiIo->Io.Read (
                      Snp->AcpiIo,
                      (EFI_ACPI_IO_PROTOCOL_WIDTH)AccessSize,
                      IoAddress,
                      1,
                      &ReadByte
                      );
      return ReadByte;
    }
  }

  return 0;
}

/**
  Maps a virtual address to a physical address for UNDI DMA.

  @param  Snp            SNP_DRIVER pointer.
  @param  HostAddress    Virtual address to map.
  @param  NumPages       Number of pages.
  @param  Direction      DMA direction (0=read, 1=write, 2=readwrite).
  @param  DeviceAddress  Returned physical address.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpAcpiMap (
  IN  SNP_DRIVER  *Snp,
  IN  UINT64      HostAddress,
  IN  UINT32      NumPages,
  IN  UINT32      Direction,
  OUT UINT64      *DeviceAddress
  )
{
  UINTN       Index;
  UINTN       DirectionMap;

  if (HostAddress == 0) {
    *DeviceAddress = 0;
    return 0;
  }

  //
  // Map direction
  //
  switch (Direction) {
  case 1:
    DirectionMap = 1; // Write
    break;
  case 2:
    DirectionMap = 2; // ReadWrite
    break;
  case 0:
  default:
    DirectionMap = 2; // Default to ReadWrite
    break;
  }

  //
  // Find a free entry in the map list
  //
  for (Index = 0; Index < SNP_MAP_LIST_MAX; Index++) {
    if (Snp->MapList[Index].VirtualAddr == 0) {
      break;
    }
  }

  if (Index >= SNP_MAP_LIST_MAX) {
    SnpDebugPrint (64, "SNP maplist is FULL\n");
    *DeviceAddress = 0;
    return 0;
  }

  //
  // Store the mapping
  //
  Snp->MapList[Index].VirtualAddr = HostAddress;

  //
  // Use ACPI IO protocol to map for DMA
  //
  if (Snp->AcpiIo != NULL) {
    EFI_STATUS  Status;
    UINTN       Pages;
    EFI_PHYSICAL_ADDRESS  PhysicalAddress;

    Pages = NumPages;
    PhysicalAddress = 0;
    Status = Snp->AcpiIo->Map (
                            Snp->AcpiIo,
                            (EFI_ACPI_IO_PROTOCOL_DMA)DirectionMap,
                            (VOID *)(UINTN)HostAddress,
                            &Pages,
                            &PhysicalAddress
                            );
    if (EFI_ERROR (Status)) {
      Snp->MapList[Index].VirtualAddr = 0;
      *DeviceAddress = 0;
      return Status;
    }

    Snp->MapList[Index].PhysicalAddr = PhysicalAddress;
    *DeviceAddress = PhysicalAddress;
    return EFI_SUCCESS;
  }

  *DeviceAddress = HostAddress;
  return EFI_SUCCESS;
}

/**
  Unmaps a previously mapped address.

  @param  Snp          SNP_DRIVER pointer.
  @param  HostAddress  Virtual address to unmap.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpAcpiUnmap (
  IN SNP_DRIVER  *Snp,
  IN UINT64      HostAddress
  )
{
  UINTN  Index;

  //
  // Find the entry and unmap
  //
  for (Index = 0; Index < SNP_MAP_LIST_MAX; Index++) {
    if (Snp->MapList[Index].VirtualAddr == HostAddress) {
      if (Snp->AcpiIo != NULL) {
        Snp->AcpiIo->Unmap (
                       Snp->AcpiIo,
                       (VOID *)(UINTN)Snp->MapList[Index].PhysicalAddr
                       );
      }
      Snp->MapList[Index].VirtualAddr = 0;
      Snp->MapList[Index].PhysicalAddr = 0;
      return EFI_SUCCESS;
    }
  }

  return EFI_NOT_FOUND;
}

/**
  Flushes data between buffers for cache coherency.

  @param  Snp          SNP_DRIVER pointer.
  @param  HostAddress  Address to flush.
  @param  Length       Length of data to flush.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpAcpiFlush (
  IN SNP_DRIVER  *Snp,
  IN UINT64      HostAddress,
  IN UINTN       Length
  )
{
  //
  // Copy data between buffers for coherency
  //
  if (HostAddress != 0 && Length > 0) {
    VOID  *Buffer;

    Buffer = (VOID *)(UINTN)HostAddress;
    //
    // Flush the data cache
    //
    if (Snp->AcpiIo != NULL) {
      Snp->AcpiIo->Flush (Snp->AcpiIo);
    }
  }

  return EFI_SUCCESS;
}

//
// ============================================================================
// UNDI Command Helper
// ============================================================================

/**
  Stub function that should never be called. Indicates Hw.UNDI is not available.

  @param  This  Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.

  @retval EFI_UNSUPPORTED  Always returns unsupported.
**/
EFI_STATUS
EFIAPI
SnpIssueHwUndiCommand (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
  )
{
  SnpDebugPrint (0x80000000, "\nIssueHwUndiCommand() - This should not be called!");

  return EFI_UNSUPPORTED;
}

//
// ============================================================================
// Timer Callback
// ============================================================================

/**
  Timer notification function that periodically polls GET_STATUS to check
  for received frames. Signals the event if data is available.

  @param  Event   The timer event.
  @param  Context SNP_DRIVER pointer.
**/
VOID
EFIAPI
SnpTimerNotifyFunction (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  SNP_DRIVER  *Snp;
  UINT32      InterruptStatus;
  UINT32      DbBuffer[2];

  if (Event == NULL || Context == NULL) {
    return;
  }

  Snp = (SNP_DRIVER *)Context;

  if (Snp->UndiState != SNP_STATE_INITIALIZED) {
    return;
  }

  //
  // Set up CDB for GET_STATUS
  //
  Snp->Cdb.OpCode   = SNP_CDB_OPCODE_GET_STATUS;
  Snp->Cdb.OpFlags  = 0;
  Snp->Cdb.CpbSize  = 0;
  Snp->Cdb.DbSize   = 8;
  Snp->Cdb.CpbAddr  = 0;
  Snp->Cdb.DbAddr   = (UINT64)(UINTN)Snp->DbAddr;
  Snp->Cdb.StatFlags = Snp->HwAddressSize;
  Snp->Cdb.OpStatus = 0;
  Snp->Cdb.StatCount = 0;

  //
  // Clear the DB buffer
  //
  SnpZeroMem (Snp->DbAddr, 8);

  //
  // Execute the UNDI GET_STATUS command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(&Snp->Cdb);

  //
  // Check interrupt status
  //
  if (Snp->Cdb.OpStatus == 0) {
    //
    // Copy the status from DB buffer
    //
    SnpCopyMem (&InterruptStatus, Snp->DbAddr, sizeof (InterruptStatus));

    if (InterruptStatus != 0) {
      //
      // Signal the event to indicate data is available
      //
      gBootServices->SignalEvent (Event);
    }
  }
}

//
// ============================================================================
// File: Snp.c - Driver Entry Point and Driver Binding
// ============================================================================

/**
  Module entry point. Saves global pointers and installs the driver binding protocol.

  @param  ImageHandle  The firmware allocated handle for the EFI image.
  @param  SystemTable  A pointer to the EFI System Table.

  @retval EFI_SUCCESS           Entry point executed successfully.
  @retval EFI_OUT_OF_RESOURCES  Out of resources.
**/
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;

  //
  // Save global pointers
  //
  gImageHandle     = ImageHandle;
  gSystemTable     = SystemTable;
  gBootServices    = SystemTable->BootServices;
  gRuntimeServices = SystemTable->RuntimeServices;

  //
  // Get image protection cookie
  //
  SnpGetImageProtectionCookie (ImageHandle);

  //
  // Install the driver binding protocol and component name protocol
  //
  Status = gBootServices->InstallMultipleProtocolInterfaces (
                            &ImageHandle,
                            &gEfiDriverBindingProtocolGuid,
                            &gSnpDriverBinding,
                            &gEfiComponentName2ProtocolGuid,
                            &gComponentName2,
                            NULL
                            );

  if (EFI_ERROR (Status)) {
    SnpDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
    ASSERT_EFI_ERROR (Status);
  }

  return Status;
}

//
// Global driver binding protocol instance
//
EFI_DRIVER_BINDING_PROTOCOL  gSnpDriverBinding = {
  SnpSupported,
  SnpStart,
  SnpDriverBindingStop,
  0x10,     // Version
  NULL,     // ImageHandle (filled at runtime)
  NULL      // ControllerHandle (filled at runtime)
};

//
// Global component name 2 protocol instance
//
EFI_COMPONENT_NAME2_PROTOCOL  gComponentName2 = {
  SnpComponentNameGetDriverName,
  SnpComponentNameGetControllerName,
  "eng"
};

/**
  Entry point for the SNP DXE driver.

  Reads the "NetworkStackVar" UEFI variable to determine if the network stack
  should be enabled. Configures CMOS registers for network control and
  conditionally installs the driver binding protocol.

  @param  ImageHandle  The firmware allocated handle for the EFI image.
  @param  SystemTable  A pointer to the EFI System Table.

  @retval EFI_SUCCESS           Driver initialized successfully.
  @retval EFI_NOT_FOUND         Network stack variable not found/disabled.
  @retval EFI_INVALID_PARAMETER Invalid parameter.
**/
EFI_STATUS
EFIAPI
SnpDxeEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;
  UINTN       DataSize;
  UINT8       VarData[8];
  UINT8       CmosValue;

  DataSize = 10;

  //
  // Read "NetworkStackVar" from UEFI Runtime Services
  //
  Status = gRuntimeServices->GetVariable (
                               L"NetworkStackVar",
                               &gEfiGlobalVariableGuid,
                               0,
                               &DataSize,
                               &VarData
                               );

  if (!EFI_ERROR (Status)) {
    //
    // Write CMOS registers for network control
    //
    // CMOS port 0x5F, 0x5E, 0x5D - network stack control
    //
    __outbyte (0x72, 0x5F);
    __outbyte (0x73, VarData[0]);

    __outbyte (0x72, 0x5E);
    __outbyte (0x73, VarData[0]);

    __outbyte (0x72, 0x5D);
    __outbyte (0x73, VarData[1] << 7);

    if (VarData[0] != 0) {
      //
      // Network stack is enabled - install driver binding
      //
      Status = gBootServices->InstallMultipleProtocolInterfaces (
                                &ImageHandle,
                                &gEfiDriverBindingProtocolGuid,
                                &gSnpDriverBinding,
                                &gEfiComponentName2ProtocolGuid,
                                &gComponentName2,
                                NULL
                                );

      if (EFI_ERROR (Status)) {
        SnpDebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
        ASSERT_EFI_ERROR (Status);
      }

      return Status;
    }

    //
    // Network stack is disabled
    //
    return EFI_NOT_FOUND;
  }

  return Status;
}

/**
  Notifies all SNP handles of a network interface identifier change.

  @param  Event   The event being signaled.
  @param  Context Pointer to event context.
**/
VOID
EFIAPI
SnpNotifyNetworkInterfaceIdentifier (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  EFI_STATUS  Status;
  UINTN       HandleCount;
  EFI_HANDLE  *HandleBuffer;
  UINTN       Index;

  //
  // Find all handles that have the SNP protocol installed
  //
  HandleBuffer = NULL;
  HandleCount = 0;

  Status = gBootServices->LocateHandleBuffer (
                            ByProtocol,
                            &gEfiSimpleNetworkProtocolGuid,
                            NULL,
                            &HandleCount,
                            &HandleBuffer
                            );

  if (!EFI_ERROR (Status) && HandleBuffer != NULL) {
    for (Index = 0; Index < HandleCount; Index++) {
      //
      // Reinstall the protocol to notify drivers
      //
      gBootServices->ReinstallProtocolInterface (
                       HandleBuffer[Index],
                       &gEfiSimpleNetworkProtocolGuid,
                       NULL,
                       NULL
                       );
    }

    gBootServices->FreePool (HandleBuffer);
  }
}

/**
  Notifies all SNP handles and triggers a PXE shutdown.

  @param  ImageHandle  Optional image handle to filter.
**/
VOID
EFIAPI
SnpTriggerPxeShutdown (
  IN EFI_HANDLE  ImageHandle OPTIONAL
  )
{
  //
  // First notify that interface identifier changed
  //
  SnpNotifyNetworkInterfaceIdentifier (NULL, NULL);

  //
  // Then trigger legacy boot shutdown
  //
  SnpCreateLegacyBootEvent ();
}

/**
  Creates a child handle with the SNP protocol.

  @param  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
  @param  ControllerHandle  Handle of the controller.
  @param  RemainingDevicePath  Remaining device path.

  @retval EFI_SUCCESS  Child handle created.
  @retval others       Error creating child.
**/
EFI_STATUS
EFIAPI
SnpCreateChild (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  //
  // For the SNP driver, child creation is handled within SnpStart
  // This function is a stub for completeness
  //
  return EFI_UNSUPPORTED;
}

/**
  Checks if the driver supports a given controller.

  Validates that the controller has UNDI3.1 support by:
  1. Opening the ACPI IO protocol on the controller
  2. Checking the !PXE structure for valid signature, revision >= 3.1,
     paragraph alignment, valid S/W entry point, and BusCnt > 0

  @param  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
  @param  ControllerHandle  Handle of the controller to test.
  @param  RemainingDevicePath  Remaining device path.

  @retval EFI_SUCCESS           The controller is supported.
  @retval EFI_UNSUPPORTED       The controller is not supported.
  @retval EFI_ALREADY_STARTED   The controller is already started.
**/
EFI_STATUS
EFIAPI
SnpSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  EFI_STATUS    Status;
  EFI_ACPI_IO   *AcpiIo;
  EFI_PXE_BASE_CODE_PROTOCOL  *Pxe;
  PXE_DB        *PxeDb;

  //
  // Try to open the ACPI IO protocol
  //
  Status = gBootServices->OpenProtocol (
                            ControllerHandle,
                            &gEfiAcpiIoProtocolGuid,
                            (VOID **)&AcpiIo,
                            This->DriverBindingHandle,
                            ControllerHandle,
                            EFI_OPEN_PROTOCOL_BY_DRIVER
                            );

  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Get the network interface identifier
  //
  PxeDb = NULL;
  Status = gBootServices->OpenProtocol (
                            ControllerHandle,
                            &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
                            (VOID **)&PxeDb,
                            This->DriverBindingHandle,
                            ControllerHandle,
                            EFI_OPEN_PROTOCOL_GET_PROTOCOL
                            );

  if (EFI_ERROR (Status)) {
    if (Status != EFI_ALREADY_STARTED) {
      SnpDebugPrint (64, "Support(): UNDI3.1 found on handle %p\n", ControllerHandle);
    }
    gBootServices->CloseProtocol (
                     ControllerHandle,
                     &gEfiAcpiIoProtocolGuid,
                     This->DriverBindingHandle,
                     ControllerHandle
                     );
    return Status;
  }

  //
  // Validate the !PXE structure
  //
  Pxe = (EFI_PXE_BASE_CODE_PROTOCOL *)PxeDb;

  if (PxeDb->Identifier[0] == 1) {
    //
    // Check !PXE structure at IdPtr
    //
    if (((UINTN)PxeDb->IdPtr & 0xF) != 0) {
      SnpDebugPrint (0x4000, "\n!PXE structure is not paragraph aligned.\n");
      goto NotSupported;
    }

    if (*(UINT32 *)PxeDb->IdPtr != PXE_SIGNATURE) {
      SnpDebugPrint (0x4000, "\n!PXE signature is not valid.\n");
      goto NotSupported;
    }

    if (*(UINT8 *)(PxeDb->IdPtr + 6) < 2) {
      SnpDebugPrint (0x4000, "\n!PXE.Rev is not supported.\n");
      goto NotSupported;
    }

    if (*(UINT8 *)(PxeDb->IdPtr + 8) < 3) {
      SnpDebugPrint (0x4000, "\n!PXE.MajorVer is not supported.\n");
      goto NotSupported;
    }

    if (*(UINT8 *)(PxeDb->IdPtr + 8) == 3 && *(UINT8 *)(PxeDb->IdPtr + 9) != 0) {
      SnpDebugPrint (0x4000, "\n!PXE.MinorVer is not supported.\n");
      goto NotSupported;
    }

    if (*(INT32 *)(PxeDb->IdPtr + 12) < 0) {
      goto NotSupported;
    }

    if (*(UINT64 *)(PxeDb->IdPtr + 16) < (UINT64)*(UINT8 *)(PxeDb->IdPtr + 4)) {
      SnpDebugPrint (0x4000, "\n!PXE S/W entry point is not valid.\n");
      goto NotSupported;
    }

    if (*(UINT8 *)(PxeDb->IdPtr + 27) == 0) {
      SnpDebugPrint (0x4000, "\n!PXE.BusCnt is zero.\n");
      goto NotSupported;
    }
  }

  SnpDebugPrint (64, "Support(): supported on %p\n", ControllerHandle);

  //
  // Close the protocols we opened for validation
  //
  gBootServices->CloseProtocol (
                   ControllerHandle,
                   &gEfiAcpiIoProtocolGuid,
                   This->DriverBindingHandle,
                   ControllerHandle
                   );

  return EFI_SUCCESS;

NotSupported:
  gBootServices->CloseProtocol (
                   ControllerHandle,
                   &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
                   This->DriverBindingHandle,
                   ControllerHandle
                   );
  return EFI_UNSUPPORTED;
}

/**
  Starts the SNP driver on a controller.

  Allocates the SNP_DRIVER structure, sets up the SNP protocol function table,
  and installs the protocol on the controller.

  @param  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
  @param  ControllerHandle  Handle of the controller to start.
  @param  RemainingDevicePath  Remaining device path.

  @retval EFI_SUCCESS           Driver started successfully.
  @retval EFI_OUT_OF_RESOURCES  Out of resources.
  @retval others                Error starting the driver.
**/
EFI_STATUS
EFIAPI
SnpStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  EFI_STATUS        Status;
  SNP_DRIVER        *Snp;
  EFI_ACPI_IO       *AcpiIo;
  EFI_PXE_BASE_CODE_PROTOCOL  *Pxe;
  PXE_DB            *PxeDb;
  EFI_EVENT         TimerEvent;

  //
  // Open ACPI IO protocol
  //
  Status = gBootServices->OpenProtocol (
                            ControllerHandle,
                            &gEfiAcpiIoProtocolGuid,
                            (VOID **)&AcpiIo,
                            This->DriverBindingHandle,
                            ControllerHandle,
                            EFI_OPEN_PROTOCOL_BY_DRIVER
                            );

  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Allocate SNP_DRIVER structure
  //
  Status = gBootServices->AllocatePool (
                            EfiBootServicesData,
                            sizeof (SNP_DRIVER),
                            (VOID **)&Snp
                            );

  if (EFI_ERROR (Status)) {
    gBootServices->CloseProtocol (
                     ControllerHandle,
                     &gEfiAcpiIoProtocolGuid,
                     This->DriverBindingHandle,
                     ControllerHandle
                     );
    return Status;
  }

  //
  // Zero the structure
  //
  SnpZeroMem (Snp, sizeof (SNP_DRIVER));
  Snp->Signature = SNP_DRIVER_SIGNATURE;

  //
  // Save ACPI IO pointer
  //
  Snp->AcpiIo = AcpiIo;

  //
  // Set up the SNP protocol function table
  //
  Snp->Snp.Revision       = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
  Snp->Snp.Start          = SnpStart;
  Snp->Snp.Stop           = SnpStop;
  Snp->Snp.Initialize     = SnpInitialize;
  Snp->Snp.Reset          = SnpReset;
  Snp->Snp.Shutdown       = SnpShutdownEntry;
  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;

  //
  // Set up Mode fields
  //
  Snp->Snp.Mode->State           = EFI_NETWORK_STOPPED;
  Snp->Snp.Mode->HwAddressSize   = Snp->HwAddressSize;
  Snp->Snp.Mode->MediaHeaderSize = 14;  // Typical Ethernet header size
  Snp->Snp.Mode->MaxPacketSize   = 1514; // Typical Ethernet MTU
  Snp->Snp.Mode->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;

  //
  // Set Upcall function to issue HW UNDI commands
  //
  Snp->IssueHwUndiCommand = SnpIssueHwUndiCommand;

  //
  // Register for network interface identifier changes
  //
  Status = gBootServices->CreateEvent (
                            EVT_NOTIFY_SIGNAL,
                            TPL_CALLBACK,
                            SnpNotifyNetworkInterfaceIdentifier,
                            NULL,
                            &TimerEvent
                            );

  if (EFI_ERROR (Status)) {
    gBootServices->FreePool (Snp);
    gBootServices->CloseProtocol (
                     ControllerHandle,
                     &gEfiAcpiIoProtocolGuid,
                     This->DriverBindingHandle,
                     ControllerHandle
                     );
    return Status;
  }

  //
  // Install SNP protocol on the controller
  //
  Status = gBootServices->InstallProtocolInterface (
                            &ControllerHandle,
                            &gEfiSimpleNetworkProtocolGuid,
                            EFI_NATIVE_INTERFACE,
                            &Snp->Snp
                            );

  if (EFI_ERROR (Status)) {
    gBootServices->CloseEvent (TimerEvent);
    gBootServices->FreePool (Snp);
    gBootServices->CloseProtocol (
                     ControllerHandle,
                     &gEfiAcpiIoProtocolGuid,
                     This->DriverBindingHandle,
                     ControllerHandle
                     );
    return Status;
  }

  return EFI_SUCCESS;
}

/**
  Stops the SNP driver on a controller.

  Validates the driver signature, destroys callbacks, closes protocols,
  closes timer events, calls shutdown and stop, and frees memory.

  @param  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
  @param  ControllerHandle  Handle of the controller to stop.
  @param  NumberOfChildren  Number of child handles.
  @param  ChildHandleBuffer  Buffer containing child handles.

  @retval EFI_SUCCESS  Driver stopped successfully.
  @retval others       Error stopping the driver.
**/
EFI_STATUS
EFIAPI
SnpDriverBindingStop (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN UINTN                        NumberOfChildren,
  IN EFI_HANDLE                   *ChildHandleBuffer
  )
{
  EFI_STATUS                Status;
  SNP_DRIVER                *Snp;
  EFI_SIMPLE_NETWORK_PROTOCOL  *SnpProtocol;

  //
  // Open SNP protocol to get the driver instance
  //
  Status = gBootServices->OpenProtocol (
                            ControllerHandle,
                            &gEfiSimpleNetworkProtocolGuid,
                            (VOID **)&SnpProtocol,
                            This->DriverBindingHandle,
                            ControllerHandle,
                            EFI_OPEN_PROTOCOL_GET_PROTOCOL
                            );

  if (EFI_ERROR (Status)) {
    return EFI_NOT_FOUND;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (SnpProtocol);

  //
  // Destroy child callbacks
  //
  SnpDestroyChild (ControllerHandle);

  //
  // Uninstall SNP protocol
  //
  Status = gBootServices->UninstallProtocolInterface (
                            ControllerHandle,
                            &gEfiSimpleNetworkProtocolGuid,
                            &Snp->Snp
                            );

  if (!EFI_ERROR (Status)) {
    //
    // Close timer events
    //
    if (Snp->TimerEvent != NULL) {
      gBootServices->CloseEvent (Snp->TimerEvent);
    }
    if (Snp->TimerEvent2 != NULL) {
      gBootServices->CloseEvent (Snp->TimerEvent2);
    }

    //
    // Close protocols
    //
    gBootServices->CloseProtocol (
                     ControllerHandle,
                     &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
                     This->DriverBindingHandle,
                     ControllerHandle
                     );

    gBootServices->CloseProtocol (
                     ControllerHandle,
                     &gEfiAcpiIoProtocolGuid,
                     This->DriverBindingHandle,
                     ControllerHandle
                     );

    //
    // Shutdown and stop the UNDI
    //
    SnpShutdownInternal (Snp);
    SnpStopEntry (Snp);

    //
    // Free ACPI IO buffer
    //
    if (Snp->AcpiIo != NULL) {
      Snp->AcpiIo->FreeBuffer (Snp->AcpiIo, 1, (VOID *)Snp->CpbAddr);
      Snp->AcpiIo->FreeBuffer (Snp->AcpiIo, 1, Snp);
    }

    //
    // Free the driver instance
    //
    gBootServices->FreePool (Snp);
  }

  return Status;
}

//
// ============================================================================
// File: ComponentName.c - Component Name Protocol
// ============================================================================

/**
  Retrieves the driver name.

  @param  This        Pointer to the EFI_COMPONENT_NAME2_PROTOCOL.
  @param  Language    Language code.
  @param  DriverName  Returned driver name string.

  @retval EFI_SUCCESS  Name returned successfully.
**/
EFI_STATUS
EFIAPI
SnpComponentNameGetDriverName (
  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
  IN CHAR8                         *Language,
  OUT CHAR16                       **DriverName
  )
{
  EFI_STATUS  Status;

  Status = SnpComponentNameParseLanguage (Language, NULL);

  if (!EFI_ERROR (Status)) {
    *DriverName = L"SNP (MAC=xx-xx-xx-xx-xx-xx)";
  }

  return Status;
}

/**
  Builds a controller name string in the format "SNP (MAC=xx-xx-xx-xx-xx-xx)".

  @param  Snp  Pointer to the SNP_DRIVER instance.

  @return EFI_STATUS.
**/
EFI_STATUS
EFIAPI
SnpGetControllerName (
  IN SNP_DRIVER  *Snp
  )
{
  CHAR16    NameBuffer[80];
  UINTN     Offset;
  UINTN     Index;

  if (Snp == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Build "SNP (MAC=" prefix
  //
  Offset = SnpUtoA ((UINTN)NameBuffer, 0xA0, L"SNP (MAC=");

  //
  // Append MAC address bytes in hex format
  //
  for (Index = 0; Index < Snp->HwAddressSize; Index++) {
    Offset += SnpUtoA (
                (INTN)&NameBuffer[2 * Offset],
                160 - 2 * Offset,
                L"%02X-",
                Snp->PermAddress[Index]
                );
  }

  ASSERT (Offset > 0);

  //
  // Replace trailing '-' with ')'
  //
  NameBuffer[2 * Offset - 2] = L')';
  NameBuffer[2 * Offset - 1] = L'\0';

  //
  // Store the name for retrieval (simplified)
  //

  return EFI_SUCCESS;
}

/**
  Retrieves the controller name.

  @param  This             Pointer to the EFI_COMPONENT_NAME2_PROTOCOL.
  @param  ControllerHandle  Handle of the controller.
  @param  ChildHandle       Child handle.
  @param  Language          Language code.
  @param  ControllerName    Returned controller name.

  @retval EFI_SUCCESS  Name returned successfully.
**/
EFI_STATUS
EFIAPI
SnpComponentNameGetControllerName (
  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
  IN EFI_HANDLE                    ControllerHandle,
  IN EFI_HANDLE                    ChildHandle,
  IN CHAR8                         *Language,
  OUT CHAR16                       **ControllerName
  )
{
  EFI_STATUS                Status;
  EFI_SIMPLE_NETWORK_PROTOCOL  *SnpProtocol;

  //
  // Open the SNP protocol on the controller
  //
  Status = gBootServices->OpenProtocol (
                            ControllerHandle,
                            &gEfiSimpleNetworkProtocolGuid,
                            (VOID **)&SnpProtocol,
                            NULL,
                            ControllerHandle,
                            EFI_OPEN_PROTOCOL_GET_PROTOCOL
                            );

  if (!EFI_ERROR (Status)) {
    Status = SnpGetControllerName (SnpProtocol);
    if (!EFI_ERROR (Status)) {
      Status = SnpComponentNameParseLanguage (Language, NULL);
    }
  }

  return Status;
}

//
// ============================================================================
// File: Start.c - SNP Start Protocol
// ============================================================================

/**
  Sets the CDB to opcode START and executes the UNDI command.
  If PxeInit was called, sets up the ACPI I/O function table with 6 callbacks.

  @param  Snp  Pointer to the SNP_DRIVER instance.

  @return EFI_STATUS from the UNDI command.
**/
UINT64
EFIAPI
SnpStartEntry (
  IN SNP_DRIVER  *Snp
  )
{
  SNP_CDB       *Cdb;
  SNP_ACPI_IO   *AcpiIoTable;

  Cdb        = &Snp->Cdb;
  AcpiIoTable = Snp->AcpiIo;

  //
  // Set up the CDB
  //
  Cdb->OpCode   = SNP_CDB_OPCODE_START;
  Cdb->OpFlags  = 0;
  Cdb->CpbSize  = 0;
  Cdb->DbSize   = 0;
  Cdb->CpbAddr  = 0;
  Cdb->DbAddr   = 0;
  Cdb->OpStatus = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  //
  // If PxeInit was previously called, set up the ACPI I/O function table
  //
  if (Snp->PxeInitCalled) {
    Cdb->CpbAddr = (UINT64)(UINTN)AcpiIoTable;
    Cdb->CpbSize = sizeof (SNP_ACPI_IO);

    //
    // Register the ACPI I/O callbacks
    //
    AcpiIoTable->Check           = SnpAcpiCheck;
    AcpiIoTable->ReadWrite       = (UINT64 (*)(UINT64, UINT64, UINT64, UINT64))SnpAcpiIoReadWrite;
    AcpiIoTable->ReadModifyWrite = NULL;
    AcpiIoTable->IoRead          = (UINT64 (*)(UINT64, UINT64))SnpAcpiReadWrite;
    AcpiIoTable->IoWrite         = (UINT64 (*)(UINT64, UINT64))SnpAcpiReadWrite;
    AcpiIoTable->MemRead         = (UINT64 (*)(UINT64, UINT64))SnpAcpiMap;
    AcpiIoTable->MemWrite        = (UINT64 (*)(UINT64, UINT64))SnpAcpiUnmap;
    AcpiIoTable->Context         = (UINT64 (*)(UINT64))(UINTN)Snp;
  }

  SnpDebugPrint (0x4000, "\nsnp->undi.start()  ");

  //
  // Execute the UNDI START command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.start()  %xh:%xh\n", Cdb->OpStatus, Cdb->StatFlags);
    return EFI_DEVICE_ERROR;
  }

  //
  // Update state to STARTED
  //
  Snp->UndiState = SNP_STATE_STARTED;

  return EFI_SUCCESS;
}

/**
  State-validating entry point for SnpStart. Validates the driver is in STOPPED state.

  @param  This  Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.

  @retval EFI_SUCCESS       Start completed.
  @retval EFI_NOT_STARTED   Driver already started.
  @retval EFI_DEVICE_ERROR  Device error.
**/
EFI_STATUS
EFIAPI
SnpStartEntryState (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
  )
{
  SNP_DRIVER  *Snp;
  UINTN       Index;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp->UndiState != SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  //
  // Call the start entry
  //
  EFI_STATUS  Status;

  Status = SnpStartEntry (Snp);

  if (!EFI_ERROR (Status)) {
    //
    // Clear the map list
    //
    for (Index = 0; Index < SNP_MAP_LIST_MAX; Index++) {
      Snp->MapList[Index].VirtualAddr = 0;
      Snp->MapList[Index].PhysicalAddr = 0;
    }
  }

  return Status;
}

//
// ============================================================================
// File: Stop.c - SNP Stop Protocol
// ============================================================================

/**
  Sets the CDB to opcode STOP and executes the UNDI command.

  @param  Snp  Pointer to the SNP_DRIVER instance.

  @return EFI_STATUS from the UNDI command.
**/
UINT64
EFIAPI
SnpStopEntry (
  IN SNP_DRIVER  *Snp
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  // Set up the CDB for STOP
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_STOP;
  Cdb->OpFlags   = 0;
  Cdb->CpbSize   = 0;
  Cdb->DbSize    = 0;
  Cdb->CpbAddr   = 0;
  Cdb->DbAddr    = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->OpStatus  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  SnpDebugPrint (0x4000, "\nsnp->undi.stop()  ");

  //
  // Execute the UNDI STOP command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (2, "\nsnp->undi.stop()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  //
  // Update state to STOPPED
  //
  Snp->UndiState = SNP_STATE_STOPPED;

  return EFI_SUCCESS;
}

/**
  SNP Stop protocol entry point.

  @param  This  Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.

  @retval EFI_SUCCESS       Stop completed.
  @retval EFI_NOT_STARTED   Driver not in STARTED state.
**/
EFI_STATUS
EFIAPI
SnpStop (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
  )
{
  SNP_DRIVER  *Snp;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp->UndiState != SNP_STATE_STARTED) {
    return EFI_NOT_STARTED;
  }

  return SnpStopEntry (Snp);
}

//
// ============================================================================
// File: Initialize.c - SNP Initialize Protocol
// ============================================================================

/**
  CDB opcode 5 (INITIALIZE). Allocates shared memory via ACPI and fills the CPB.

  @param  Snp       Pointer to the SNP_DRIVER instance.
  @param  RxFilter  Receive filter to set (0 = no filter, 1 = basic filter).

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpPxeInit (
  IN SNP_DRIVER  *Snp,
  IN UINT16      RxFilter
  )
{
  SNP_CDB   *Cdb;
  SNP_CPB_INITIALIZE  *Cpb;
  EFI_STATUS  Status;
  UINT64      MemSize;

  Cdb = &Snp->Cdb;
  MemSize = Snp->MaxPacketSize;

  //
  // Allocate shared memory buffer if needed
  //
  if (MemSize != 0) {
    UINTN  NumPages;

    NumPages = ((UINTN)(MemSize - 1) >> 12) + 1;

    Status = Snp->AcpiIo->AllocateBuffer (
                            Snp->AcpiIo,
                            EfiBootServicesData,
                            NumPages,
                            (VOID **)&Cpb,
                            0
                            );

    if (EFI_ERROR (Status)) {
      SnpDebugPrint (0x80000000, "\nSnp->PxeInit()  AllocateBuffer  %xh (%r)\n", Status, Status);
      return Status;
    }

    ASSERT (Cpb != NULL);
    Snp->CpbAddr = Cpb;
  }

  //
  // Fill CPB
  //
  Cpb = (SNP_CPB_INITIALIZE *)Snp->CpbAddr;
  Cpb->MemAddr     = (UINT64)(UINTN)Snp->CpbAddr;
  Cpb->MemLength   = (UINT32)MemSize;
  Cpb->MemReserved = 0;
  Cpb->Reserved    = 0;
  Cpb->RxFilter    = 0;

  //
  // Set up the CDB
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_INITIALIZE;
  Cdb->CpbAddr   = (UINT64)(UINTN)Snp->CpbAddr;
  Cdb->DbAddr    = (UINT64)(UINTN)Snp->DbAddr;
  Cdb->StatFlags = Snp->HwAddressSize;
  Cdb->OpFlags   = RxFilter;
  Cdb->CpbSize   = 36;  // sizeof(SNP_CPB_INITIALIZE) = 0x24
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;

  SnpDebugPrint (0x4000, "\nSnp->undi.initialize()  ");

  //
  // Execute the UNDI INITIALIZE command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if ((Cdb->StatFlags & 0xC000) != 0xC000 || Cdb->OpStatus != 0) {
    SnpDebugPrint (2, "\nSnp->undi.initialize()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);

    //
    // Free the allocated buffer on failure
    //
    if (Snp->CpbAddr != NULL) {
      Snp->AcpiIo->FreeBuffer (
                     Snp->AcpiIo,
                     ((UINTN)(MemSize - 1) >> 12) + 1,
                     Snp->CpbAddr
                     );
    }
    Snp->CpbAddr = NULL;

    return EFI_DEVICE_ERROR;
  }

  //
  // Update MediaPresent based on link status
  //
  if (RxFilter == 0) {
    Snp->MediaPresent = (BOOLEAN)((Cdb->StatFlags & 1) == 0);
  }

  //
  // Update state to INITIALIZED
  //
  Snp->UndiState = SNP_STATE_INITIALIZED;

  return EFI_SUCCESS;
}

/**
  SNP Initialize protocol entry point.

  State must be STARTED. Creates a timer event, clears filters/MAC,
  sets memory size, and calls PxeInit to initialize the UNDI.

  @param  This              Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  ExtraRxBufferSize  Extra receive buffer size.
  @param  ExtraTxBufferSize  Extra transmit buffer size.

  @retval EFI_SUCCESS       Initialize completed.
  @retval EFI_NOT_STARTED   Driver not started.
  @retval EFI_DEVICE_ERROR  Device error.
**/
EFI_STATUS
EFIAPI
SnpInitialize (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN UINTN                        ExtraRxBufferSize,
  IN UINTN                        ExtraTxBufferSize
  )
{
  SNP_DRIVER  *Snp;
  EFI_STATUS  Status;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Check state
  //
  if (Snp->UndiState == SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  if (Snp->UndiState == SNP_STATE_STARTED) {
    //
    // Create timer event for polling received frames
    //
    Status = gBootServices->CreateEvent (
                              EVT_TIMER | EVT_NOTIFY_SIGNAL,
                              TPL_CALLBACK,
                              SnpTimerNotifyFunction,
                              Snp,
                              &Snp->TimerEvent
                              );

    if (EFI_ERROR (Status)) {
      Snp->TimerEvent = NULL;
      return EFI_OUT_OF_RESOURCES;
    }

    //
    // Clear receive filter setting and multicast filter count
    //
    Snp->ReceiveFilterSetting = 0;
    Snp->MCastFilterCnt       = 0;

    //
    // Clear multicast filter buffer
    //
    SnpZeroMem (Snp->MCastFilter, sizeof (Snp->MCastFilter));

    //
    // Copy permanent MAC address to current address
    //
    SnpCopyMem (Snp->CurrentAddress, Snp->PermAddress, Snp->HwAddressSize);

    //
    // Set total memory size
    //
    Snp->MaxPacketSize = ExtraRxBufferSize + ExtraTxBufferSize + Snp->MaxPacketSize;

    //
    // Initialize with no filter first
    //
    if (Snp->MediaPresentSupported) {
      Snp->MediaPresent = FALSE;
    }

    Status = SnpPxeInit (Snp, 1);  // RxFilter = 1 (basic filter)

    if (EFI_ERROR (Status)) {
      gBootServices->CloseEvent (Snp->TimerEvent);
      Snp->TimerEvent = NULL;
      return Status;
    }

    //
    // Start the timer for periodic polling
    //
    Status = gBootServices->SetTimer (
                              Snp->TimerEvent,
                              TimerPeriodic,
                              500000   // 500ms interval
                              );

    if (!EFI_ERROR (Status)) {
      //
      // If media present supported, get initial status
      //
      if (Snp->MediaPresentSupported) {
        SnpGetStatusInternal (Snp, NULL, FALSE);
      }
    }
  } else {
    return EFI_DEVICE_ERROR;
  }

  return Status;
}

//
// ============================================================================
// File: Reset.c - SNP Reset Protocol
// ============================================================================

/**
  CDB opcode 6 (RESET). Resets the network adapter.

  @param  Snp  Pointer to the SNP_DRIVER instance.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpResetInternal (
  IN SNP_DRIVER  *Snp
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  // Set up the CDB for RESET
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_RESET;
  Cdb->OpFlags   = 0;
  Cdb->CpbSize   = 0;
  Cdb->DbSize    = 0;
  Cdb->CpbAddr   = 0;
  Cdb->DbAddr    = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  SnpDebugPrint (0x4000, "\nsnp->undi.reset()  ");

  //
  // Execute the UNDI RESET command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.reset()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

/**
  SNP Reset protocol entry point.

  @param  This                 Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  ExtendedVerification  Whether extended verification is requested.

  @retval EFI_SUCCESS       Reset completed.
  @retval EFI_NOT_STARTED   Driver not initialized.
**/
EFI_STATUS
EFIAPI
SnpReset (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN BOOLEAN                      ExtendedVerification
  )
{
  SNP_DRIVER  *Snp;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp->UndiState != SNP_STATE_INITIALIZED) {
    return EFI_NOT_STARTED;
  }

  return SnpResetInternal (Snp);
}

//
// ============================================================================
// File: Shutdown.c - SNP Shutdown Protocol
// ============================================================================

/**
  CDB opcode 7 (SHUTDOWN). Shuts down the UNDI and frees the ACPI memory buffer.

  @param  Snp  Pointer to the SNP_DRIVER instance.
**/
VOID
EFIAPI
SnpShutdownInternal (
  IN SNP_DRIVER  *Snp
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  // Set up the CDB for SHUTDOWN
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_SHUTDOWN;
  Cdb->OpFlags   = 0;
  Cdb->CpbSize   = 0;
  Cdb->DbSize    = 0;
  Cdb->CpbAddr   = 0;
  Cdb->DbAddr    = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  SnpDebugPrint (0x4000, "\nsnp->undi.shutdown()  ");

  //
  // Execute the UNDI SHUTDOWN command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.shutdown()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return;
  }

  //
  // Free the ACPI memory buffer
  //
  if (Snp->CpbAddr != NULL && Snp->AcpiIo != NULL) {
    Snp->AcpiIo->FreeBuffer (
                   Snp->AcpiIo,
                   ((UINTN)(Snp->MaxPacketSize - 1) >> 12) + 1,
                   Snp->CpbAddr
                   );
    Snp->CpbAddr = NULL;
  }
}

/**
  SNP Shutdown protocol entry point.

  @param  This  Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.

  @retval EFI_SUCCESS       Shutdown completed.
  @retval EFI_NOT_STARTED   Driver not initialized.
**/
EFI_STATUS
EFIAPI
SnpShutdownEntry (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
  )
{
  SNP_DRIVER  *Snp;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp->UndiState != SNP_STATE_INITIALIZED) {
    return EFI_NOT_STARTED;
  }

  //
  // Shutdown the UNDI
  //
  SnpShutdownInternal (Snp);

  //
  // Clear multicast filter count and receive filter setting
  //
  Snp->MCastFilterCnt       = 0;
  Snp->ReceiveFilterSetting = 0;

  //
  // Set state to STARTED
  //
  Snp->UndiState = SNP_STATE_STARTED;

  //
  // Clear multicast addresses
  //
  SnpZeroMem (Snp->MCastFilter, sizeof (Snp->MCastFilter));

  //
  // Copy permanent address back to current address
  //
  SnpCopyMem (Snp->CurrentAddress, Snp->PermAddress, Snp->HwAddressSize);

  //
  // Close timer event
  //
  if (Snp->TimerEvent != NULL) {
    gBootServices->CloseEvent (Snp->TimerEvent);
    Snp->TimerEvent = NULL;
  }

  return EFI_SUCCESS;
}

//
// ============================================================================
// File: Receive_filters.c - SNP ReceiveFilters Protocol
// ============================================================================

/**
  CDB opcode 9 - enables receive filters.

  @param  Snp            Pointer to the SNP_DRIVER instance.
  @param  Enable         Bitmask of filters to enable.
  @param  MCastFilterCnt Number of multicast filter entries.
  @param  MCastFilter    Pointer to multicast filter data.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpReceiveFiltersEnable (
  IN SNP_DRIVER  *Snp,
  IN UINT32      Enable,
  IN UINTN       MCastFilterCnt,
  IN VOID        *MCastFilter
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  // Set up the CDB for RECEIVE_FILTERS with enable flags
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_RECEIVE_FILTERS;
  Cdb->OpFlags   = (UINT16)Enable;
  Cdb->CpbSize   = 0;
  Cdb->DbSize    = 0;
  Cdb->CpbAddr   = (UINT64)(UINTN)MCastFilter;
  Cdb->DbAddr    = 0;
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  //
  // Map filter bits to UNDI flags:
  //   BIT0 = UNICAST
  //   BIT1 = MULTICAST
  //   BIT2 = BROADCAST
  //   BIT3 = PROMISCUOUS
  //   BIT4 = PROMISCUOUS_MULTICAST
  //

  SnpDebugPrint (0x4000, "\nsnp->undi.receive_filters()  ");

  //
  // Execute the UNDI RECEIVE_FILTERS command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.receive_filters()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  //
  * Update software state
  //
  Snp->ReceiveFilterSetting |= Enable;

  if (MCastFilterCnt > 0 && MCastFilter != NULL) {
    Snp->MCastFilterCnt = (UINT32)MCastFilterCnt;
    SnpCopyMem (Snp->MCastFilter, MCastFilter, MCastFilterCnt * sizeof (EFI_MAC_ADDRESS));
  }

  return EFI_SUCCESS;
}

/**
  CDB opcode 9 - disables receive filters.

  @param  Snp              Pointer to the SNP_DRIVER instance.
  @param  Disable          Bitmask of filters to disable.
  @param  ResetMCastFilter Whether to reset the multicast filter list.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpReceiveFiltersDisable (
  IN SNP_DRIVER  *Snp,
  IN UINT32      Disable,
  IN BOOLEAN     ResetMCastFilter
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  // Set up the CDB for RECEIVE_FILTERS with disable flags
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_RECEIVE_FILTERS;
  Cdb->OpFlags   = (UINT16)Disable;
  Cdb->CpbSize   = 0;
  Cdb->DbSize    = 0;
  Cdb->CpbAddr   = 0;
  Cdb->DbAddr    = 0;
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  SnpDebugPrint (0x4000, "\nsnp->undi.receive_filters()  ");

  //
  // Execute the UNDI RECEIVE_FILTERS command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.receive_filters()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  //
  // Update software state
  //
  Snp->ReceiveFilterSetting &= ~Disable;

  if (ResetMCastFilter) {
    Snp->MCastFilterCnt = 0;
    SnpZeroMem (Snp->MCastFilter, sizeof (Snp->MCastFilter));
  }

  return EFI_SUCCESS;
}

/**
  Gets the current receive filter settings from the hardware and copies
  multicast filter data back.

  @param  Snp  Pointer to the SNP_DRIVER instance.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpReceiveFiltersSet (
  IN SNP_DRIVER  *Snp
  )
{
  //
  // Read back current filter settings from HW
  //
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  // Issue a RECEIVE_FILTERS command to read settings
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_RECEIVE_FILTERS;
  Cdb->OpFlags   = 0;
  Cdb->CpbSize   = 0;
  Cdb->DbSize    = 0;
  Cdb->CpbAddr   = 0;
  Cdb->DbAddr    = 0;
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  //
  // Execute the UNDI command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.receive_filters()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  //
  // Copy the multicast filter data back from the hardware
  //
  if (Cdb->StatCount > 0) {
    Snp->MCastFilterCnt = Cdb->StatCount;
    SnpCopyMem (Snp->MCastFilter, (VOID *)(UINTN)Cdb->DbAddr, Cdb->StatCount * sizeof (EFI_MAC_ADDRESS));
  }

  return EFI_SUCCESS;
}

/**
  SNP ReceiveFilters protocol entry point.

  @param  This             Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  Enable           Filters to enable.
  @param  Disable          Filters to disable.
  @param  ResetMCastFilter Whether to reset the multicast filter list.
  @param  MCastFilterCnt   Number of multicast filter entries.
  @param  MCastFilter      Pointer to multicast filter data.

  @retval EFI_SUCCESS       Operation completed.
  @retval EFI_NOT_STARTED   Driver not started or not initialized.
  @retval EFI_INVALID_PARAMETER  Invalid parameter.
**/
EFI_STATUS
EFIAPI
SnpReceiveFilters (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN UINT32                       Enable,
  IN UINT32                       Disable,
  IN BOOLEAN                      ResetMCastFilter,
  IN UINTN                        MCastFilterCnt,
  IN EFI_MAC_ADDRESS              *MCastFilter
  )
{
  SNP_DRIVER  *Snp;
  EFI_STATUS  Status;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  //
  // Check state
  //
  if (Snp->UndiState == SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  if (Snp->UndiState == SNP_STATE_INITIALIZED) {
    //
    // Validate filter flags against supported mask
    //
    if ((~Snp->ReceiveFilterMask & Enable) != 0 || (~Snp->ReceiveFilterMask & Disable) != 0) {
      return EFI_INVALID_PARAMETER;
    }

    if (ResetMCastFilter) {
      Disable |= Snp->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
      MCastFilterCnt = 0;
    } else if (MCastFilterCnt > Snp->MCastFilterMax) {
      return EFI_INVALID_PARAMETER;
    }

    //
    * Handle empty operation
    //
    if (Enable == 0 && Disable == 0 && !ResetMCastFilter && MCastFilterCnt == 0) {
      return EFI_SUCCESS;
    }

    //
    // Require multicast filter data when enabling multicast
    //
    if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastFilterCnt == 0) {
      return EFI_INVALID_PARAMETER;
    }

    //
    // Enable filters
    //
    if (Enable != 0 || MCastFilterCnt > 0) {
      Status = SnpReceiveFiltersEnable (Snp, Enable, MCastFilterCnt, MCastFilter);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    //
    // Disable filters
    //
    if (Disable != 0 || ResetMCastFilter) {
      Status = SnpReceiveFiltersDisable (Snp, Disable, ResetMCastFilter);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    //
    // Read back and update filter settings
    //
    return SnpReceiveFiltersSet (Snp);
  }

  return EFI_DEVICE_ERROR;
}

//
// ============================================================================
// File: Station_address.c - SNP StationAddress Protocol
// ============================================================================

/**
  CDB opcode 10 - reads permanent, current, and multicast MAC addresses.

  @param  Snp  Pointer to the SNP_DRIVER instance.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpStationAddressGet (
  IN SNP_DRIVER  *Snp
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  // Set up CDB to read station address
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_STATION_ADDR;
  Cdb->OpFlags   = 0;
  Cdb->CpbSize   = 0;
  Cdb->DbSize    = 0;
  Cdb->CpbAddr   = (UINT64)(UINTN)Snp->PermAddress;
  Cdb->DbAddr    = (UINT64)(UINTN)Snp->CurrentAddress;
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  SnpDebugPrint (0x4000, "\nsnp->undi.station_addr()  ");

  //
  // Execute the UNDI STATION_ADDR command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.station_addr()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

/**
  CDB opcode 10 - sets a new MAC address, then reads it back.

  @param  Snp  Pointer to the SNP_DRIVER instance.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpStationAddressSet (
  IN SNP_DRIVER  *Snp
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  // Set up CDB to write station address
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_STATION_ADDR;
  Cdb->OpFlags   = 1;  // Write operation
  Cdb->CpbSize   = (UINT16)Snp->HwAddressSize;
  Cdb->DbSize    = 0;
  Cdb->CpbAddr   = (UINT64)(UINTN)Snp->CurrentAddress;
  Cdb->DbAddr    = 0;
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  SnpDebugPrint (0x4000, "\nsnp->undi.station_addr()  ");

  //
  // Execute the UNDI STATION_ADDR command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.station_addr()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  //
  // Now read back the address to verify
  //
  Cdb->OpFlags = 0;  // Read operation
  Cdb->CpbAddr  = (UINT64)(UINTN)Snp->PermAddress;
  Cdb->DbAddr   = (UINT64)(UINTN)Snp->CurrentAddress;

  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

/**
  SNP StationAddress protocol entry point.

  @param  This   Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  Reset  Whether to reset to permanent address.
  @param  New    Pointer to new MAC address.

  @retval EFI_SUCCESS       Operation completed.
  @retval EFI_NOT_STARTED   Driver not started.
**/
EFI_STATUS
EFIAPI
SnpStationAddress (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN BOOLEAN                      Reset,
  IN EFI_MAC_ADDRESS              *New
  )
{
  SNP_DRIVER  *Snp;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp->UndiState == SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  if (Reset) {
    //
    // Restore permanent address to current address
    //
    SnpCopyMem (Snp->CurrentAddress, Snp->PermAddress, Snp->HwAddressSize);
  } else if (New != NULL) {
    //
    * Set new current address
    //
    SnpCopyMem (Snp->CurrentAddress, New, Snp->HwAddressSize);
  }

  return SnpStationAddressSet (Snp);
}

//
// ============================================================================
// File: Statistics.c - SNP Statistics Protocol
// ============================================================================

/**
  CDB opcode 11 - reads statistics from the UNDI.

  @param  Snp              Pointer to the SNP_DRIVER instance.
  @param  Reset            Whether to reset the statistics.
  @param  StatisticsSize  On input, size of the statistics buffer.
                          On output, size of the returned statistics.
  @param  StatisticsTable  Pointer to the statistics table.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpStatisticsInternal (
  IN  SNP_DRIVER              *Snp,
  IN  BOOLEAN                 Reset,
  IN  OUT UINTN               *StatisticsSize,
  OUT EFI_NETWORK_STATISTICS  *StatisticsTable
  )
{
  SNP_CDB  *Cdb;
  UINTN     Count;
  UINT64    *StatData;

  if (Snp == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Cdb = &Snp->Cdb;

  //
  // Check state
  //
  if (Snp->UndiState == SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  if (Snp->UndiState != SNP_STATE_INITIALIZED) {
    return EFI_DEVICE_ERROR;
  }

  if (!Reset && StatisticsSize == NULL) {
    return (StatisticsTable != NULL) ? EFI_INVALID_PARAMETER : EFI_SUCCESS;
  }

  StatData = (UINT64 *)Snp->DbAddr;

  //
  // Set up the CDB
  //
  Cdb->CpbSize  = 0x7E;  // sizeof(SNP_CPB_STATISTICS) with reserved fields
  Cdb->OpCode   = SNP_CDB_OPCODE_STATISTICS;
  Cdb->StatFlags = Snp->HwAddressSize;
  Cdb->CpbAddr  = 0;
  Cdb->OpStatus = 0;
  Cdb->StatData = 0;
  Cdb->StatCount = 0;

  if (Reset) {
    //
    // Reset statistics
    //
    Cdb->OpFlags = 1;
    Cdb->DbSize  = 0;
    Cdb->DbAddr  = 0;
  } else {
    //
    // Read statistics
    //
    Cdb->OpFlags = 0;
    Cdb->DbSize  = 520;  // sizeof(SNP_DB_STATISTICS)
    Cdb->DbAddr  = (UINT64)(UINTN)StatData;
  }

  SnpDebugPrint (0x4000, "\nsnp->undi.statistics()  ");

  //
  // Execute the UNDI STATISTICS command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    if (Cdb->OpStatus == 12) {
      SnpDebugPrint (0x80000000, "\nsnp->undi.statistics()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
      return EFI_NOT_FOUND;
    }
    SnpDebugPrint (0x80000000, "\nsnp->undi.statistics()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  if (!Reset) {
    //
    * Return statistics size
    //
    if (StatisticsTable != NULL) {
      if (*StatisticsSize != 0) {
        SnpZeroMem (StatisticsTable, *StatisticsSize);
      }

      //
      // Translate UNDI statistics to EFI_NETWORK_STATISTICS format
      //
      Count = 0;
      UINT64  *Dest = (UINT64 *)StatisticsTable;

      for (UINTN Index = 0; Index < 0x208; Index += 8) {
        if (Count > *StatisticsSize / 8) {
          break;
        }

        if ((StatData[0] & (1ULL << (Index / 8))) != 0) {
          Dest[Count] = StatData[Index / 8];
          Count++;
        } else {
          Dest[Count] = 0xFF;
          Count++;
        }
      }

      //
      // Update remaining supported entries
      //
      for (UINTN Index = Count + 1; Index < 0x40; Index++) {
        if ((StatData[0] & (1ULL << Index)) != 0) {
          Count = Index;
        }
      }

      *StatisticsSize = 8 * (Count + 1);
    } else {
      *StatisticsSize = 0x208;  // 520 bytes = full statistics block
    }

    if (*StatisticsSize < 8 * (Count + 1)) {
      return EFI_BUFFER_TOO_SMALL;
    }
  }

  return EFI_SUCCESS;
}

//
// ============================================================================
// File: Get_status.c - SNP GetStatus Protocol
// ============================================================================

/**
  CDB opcode 14 (GET_STATUS). Returns interrupt status flags,
  recycles TX buffers, and updates MediaPresent.

  @param  Snp              Pointer to the SNP_DRIVER instance.
  @param  InterruptStatus  Optional pointer to receive interrupt status.
  @param  GetTxBuf         Whether to check for TX buffer recycling.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpGetStatusInternal (
  IN  SNP_DRIVER  *Snp,
  OUT UINT32      *InterruptStatus OPTIONAL,
  IN  BOOLEAN     GetTxBuf
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  * Set up the CDB
  //
  Cdb->CpbSize  = 0;
  Cdb->OpCode   = SNP_CDB_OPCODE_GET_STATUS;
  Cdb->OpFlags  = 0;
  Cdb->StatData = 0;
  Cdb->StatCount = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  if (InterruptStatus != NULL) {
    Cdb->DbSize  = sizeof (UINT32);
    Cdb->DbAddr  = (UINT64)(UINTN)InterruptStatus;
    Cdb->CpbAddr = 0;
  } else {
    Cdb->DbSize  = 0;
    Cdb->DbAddr  = 0;
    Cdb->CpbAddr = 0;
  }

  SnpDebugPrint (0x4000, "\nsnp->undi.get_status()  ");

  //
  // Execute the UNDI GET_STATUS command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nsnp->undi.get_status()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  //
  // Update MediaPresent based on link state
  //
  if ((Cdb->StatFlags & SNP_STATUS_LINK_UP_BIT) != 0) {
    Snp->MediaPresent = TRUE;
  } else {
    Snp->MediaPresent = FALSE;
  }

  //
  * Check for recycled TX buffers
  //
  if (GetTxBuf && Cdb->StatCount > 0) {
    //
    // Recycle TX buffers (max SNP_TX_BUFFER_MAX)
    //
    UINT32  Count;

    Count = Cdb->StatCount;
    if (Count > SNP_TX_BUFFER_MAX) {
      Count = SNP_TX_BUFFER_MAX;
    }

    for (UINT32 Index = 0; Index < Count; Index++) {
      if (Snp->TxBufCount < SNP_TX_BUFFER_MAX) {
        Snp->TxBufRecycle[Snp->TxBufCount] = Cdb->StatData;
        Snp->TxBufCount++;
      }
    }
  }

  return EFI_SUCCESS;
}

/**
  SNP GetStatus protocol entry point.

  @param  This              Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  InterruptStatus   Optional pointer to receive interrupt status.
  @param  TxBuf             Optional pointer to receive TX buffer address.

  @retval EFI_SUCCESS       Status retrieved.
  @retval EFI_NOT_STARTED   Driver not started.
  @retval EFI_DEVICE_ERROR  Device error.
**/
EFI_STATUS
EFIAPI
SnpGetStatus (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  OUT UINT32                      *InterruptStatus OPTIONAL,
  OUT VOID                        **TxBuf OPTIONAL
  )
{
  SNP_DRIVER  *Snp;
  EFI_STATUS  Status;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp == NULL) {
    return EFI_DEVICE_ERROR;
  }

  if (Snp->UndiState == SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  if (Snp->UndiState == SNP_STATE_INITIALIZED) {
    //
    // If TxBuf is requested and no recycled buffers are pending,
    // do a hardware GET_STATUS to check for TX completions
    //
    BOOLEAN  CheckTxBuf;

    CheckTxBuf = (BOOLEAN)(Snp->TxBufCount == 0 && TxBuf != NULL);

    Status = SnpGetStatusInternal (Snp, InterruptStatus, CheckTxBuf);

    if (TxBuf != NULL) {
      if (Snp->TxBufCount > 0) {
        Snp->TxBufCount--;
        *TxBuf = (VOID *)(UINTN)Snp->TxBufRecycle[Snp->TxBufCount];
      } else {
        *TxBuf = NULL;
      }
    }
  } else {
    //
    * State is STARTED but not INITIALIZED
    //
    Status = EFI_DEVICE_ERROR;
  }

  return Status;
}

//
// ============================================================================
// File: Transmit.c - SNP Transmit Protocol
// ============================================================================

/**
  CDB opcode 15 (FILL_HEADER). Builds the MAC header for a frame.

  @param  Snp          Pointer to the SNP_DRIVER instance.
  @param  Buffer       Pointer to the buffer.
  @param  HeaderSize   Size of the header.
  @param  FullPacket   Pointer to the full packet.
  @param  FullPacketSize  Size of the full packet.
  @param  SrcAddr      Source MAC address.
  @param  DestAddr     Destination MAC address.
  @param  Protocol     Protocol type.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpFillHeader (
  IN  SNP_DRIVER      *Snp,
  IN  VOID            *Buffer,
  IN  UINTN           HeaderSize,
  IN  EFI_MAC_ADDRESS *SrcAddr,
  IN  EFI_MAC_ADDRESS *DestAddr,
  IN  UINT16          *Protocol
  )
{
  SNP_CDB  *Cdb;
  SNP_DB_RECEIVE  *Db;
  UINT16    SwappedProtocol;

  Db = (SNP_DB_RECEIVE *)Snp->CpbAddr;

  //
  // Set source and destination addresses in the data block
  //
  if (SrcAddr != NULL) {
    SnpCopyMem ((VOID *)Db, SrcAddr, Snp->HwAddressSize);
  } else {
    SnpCopyMem ((VOID *)Db, Snp->PermAddress, Snp->HwAddressSize);
  }

  SnpCopyMem ((VOID *)((UINTN)Db + 32), DestAddr, Snp->HwAddressSize);

  //
  * Fill the DB fields
  //
  Db->PacketLen        = (UINT32)HeaderSize;
  Db->MediaHeaderLen   = (UINT16)HeaderSize;
  Db->FragCount        = 2;
  Db->ProtocolType     = (UINT16)((Protocol[0] << 8) | ((UINT8 *)Protocol)[1]);
  Db->DataOffset       = (UINT32)HeaderSize;
  Db->MediaHeaderFrag  = (UINT32)HeaderSize;
  Db->SrcAddr[0]       = (UINTN)Buffer;
  Db->DestAddr[0]      = (UINTN)((UINT8 *)Buffer + HeaderSize);
  Db->Reserved2[0]     = 0;
  Db->Reserved2[1]     = 0;
  Db->Status           = 0;

  //
  * Fill the header using UNDI
  //
  Cdb = &Snp->Cdb;
  Cdb->OpCode    = SNP_CDB_OPCODE_FILL_HEADER;
  Cdb->StatFlags = Snp->HwAddressSize;
  Cdb->CpbSize   = 0x014B8001;  // Special fill header flags
  Cdb->OpFlags   = 0;
  Cdb->DbSize    = 0;
  Cdb->DbAddr    = 0;
  Cdb->CpbAddr   = (UINT64)(UINTN)Db;
  Cdb->OpStatus  = 0;
  Cdb->StatData  = 0;
  Cdb->StatCount = 0;

  SnpDebugPrint (0x4000, "\nSnp->undi.fill_header()  ");

  //
  // Execute the UNDI FILL_HEADER command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    if (Cdb->OpStatus == 14) {
      SnpDebugPrint (0x80000000, "\nSnp->undi.fill_header()  %xh:%xh\n", Cdb->StatFlags, 14);
      return EFI_INVALID_PARAMETER;
    }
    SnpDebugPrint (0x80000000, "\nSnp->undi.fill_header()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

/**
  CDB opcode 16 (TRANSMIT). Transmits a frame.

  @param  Snp          Pointer to the SNP_DRIVER instance.
  @param  Buffer       Pointer to the buffer containing the frame.
  @param  BufferSize   Size of the frame.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpTransmitInternal (
  IN  SNP_DRIVER  *Snp,
  IN  VOID        *Buffer,
  IN  UINTN       BufferSize
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  * Set up the CDB for TRANSMIT
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_TRANSMIT;
  Cdb->OpFlags   = 0;
  Cdb->StatFlags = Snp->HwAddressSize;
  Cdb->CpbAddr   = (UINT64)(UINTN)Buffer;
  Cdb->CpbSize   = (UINT16)BufferSize;
  Cdb->DbSize    = 0;
  Cdb->DbAddr    = 0;
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;

  SnpDebugPrint (0x4000, "\nSnp->undi.transmit()  ");

  //
  // Execute the UNDI TRANSMIT command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    SnpDebugPrint (0x80000000, "\nSnp->undi.transmit()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

/**
  SNP Transmit protocol entry point.

  @param  This       Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  HeaderSize Size of the MAC header.
  @param  BufferSize Size of the buffer.
  @param  Buffer     Pointer to the buffer.
  @param  SrcAddr    Source MAC address.
  @param  DestAddr   Destination MAC address.
  @param  Protocol   Protocol type.

  @retval EFI_SUCCESS            Transmit completed.
  @retval EFI_NOT_STARTED        Driver not started.
  @retval EFI_INVALID_PARAMETER  Invalid parameter.
  @retval EFI_BAD_BUFFER_SIZE    Buffer size invalid.
**/
EFI_STATUS
EFIAPI
SnpTransmit (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN UINTN                        HeaderSize,
  IN UINTN                        BufferSize,
  IN VOID                         *Buffer,
  IN EFI_MAC_ADDRESS              *SrcAddr,
  IN EFI_MAC_ADDRESS              *DestAddr,
  IN UINT16                       *Protocol
  )
{
  SNP_DRIVER  *Snp;
  EFI_STATUS  Status;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp == NULL) {
    return EFI_DEVICE_ERROR;
  }

  if (Snp->UndiState == SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  if (Snp->UndiState == SNP_STATE_INITIALIZED) {
    if (Buffer == NULL) {
      return EFI_INVALID_PARAMETER;
    }

    if (BufferSize < Snp->MaxPacketSize) {
      return EFI_BAD_BUFFER_SIZE;
    }

    //
    // If HeaderSize > 0, fill the header first
    //
    if (HeaderSize > 0) {
      if (HeaderSize != Snp->Snp.Mode->MediaHeaderSize ||
          SrcAddr == NULL || Protocol == NULL) {
        return EFI_INVALID_PARAMETER;
      }

      Status = SnpFillHeader (
                 Snp,
                 Buffer,
                 HeaderSize,
                 SrcAddr,
                 DestAddr,
                 Protocol
                 );

      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    //
    * Transmit the frame
    //
    return SnpTransmitInternal (Snp, Buffer, BufferSize);
  }

  return EFI_DEVICE_ERROR;
}

//
// ============================================================================
// File: Receive.c - SNP Receive Protocol
// ============================================================================

/**
  CDB opcode 17 (RECEIVE). Copies received data from the DB buffer.

  @param  Snp          Pointer to the SNP_DRIVER instance.
  @param  Buffer       Pointer to the receive buffer.
  @param  BufferSize   On input, size of the buffer. On output, size of received data.
  @param  HeaderSize   Optional pointer to receive header size.
  @param  SrcAddr      Optional pointer to receive source address.
  @param  DestAddr     Optional pointer to receive destination address.
  @param  Protocol     Optional pointer to receive protocol type.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpReceiveInternal (
  IN  SNP_DRIVER  *Snp,
  OUT VOID        *Buffer,
  OUT UINTN       *BufferSize,
  OUT UINTN       *HeaderSize,
  OUT UINT32      *SrcAddr,
  OUT UINT32      *DestAddr,
  OUT UINT16      *Protocol
  )
{
  SNP_CDB   *Cdb;
  SNP_DB_RECEIVE  *Db;
  UINTN     ReceivedSize;

  ReceivedSize = *BufferSize;
  Cdb = &Snp->Cdb;
  Db  = (SNP_DB_RECEIVE *)Snp->DbAddr;

  //
  * Set up CPB and CDB
  //
  Cpb = (VOID *)(UINTN)Snp->CpbAddr;
  *(UINT64 *)Cpb = (UINT64)(UINTN)Buffer;
  *(UINT32 *)((UINTN)Cpb + 8) = (UINT32)ReceivedSize;
  *(UINT32 *)((UINTN)Cpb + 12) = 0;

  Cdb->OpCode    = SNP_CDB_OPCODE_RECEIVE;
  Cdb->CpbSize   = 0x50;  // sizeof(CPB)
  Cdb->StatFlags = Snp->HwAddressSize;
  Cdb->CpbAddr   = (UINT64)(UINTN)Cpb;
  Cdb->DbAddr    = (UINT64)(UINTN)Db;
  Cdb->OpStatus  = 0;
  Cdb->StatData  = 0;
  Cdb->DbSize    = 0x100000;
  Cdb->StatCount = 0;

  SnpDebugPrint (0x4000, "\nsnp->undi.receive ()  ");

  //
  // Execute the UNDI RECEIVE command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    if (Cdb->OpStatus == 19) {
      SnpDebugPrint (0x4000, "\nsnp->undi.receive ()  %xh:%xh\n", Cdb->StatFlags, 19);
      return EFI_NO_MEDIA;
    }
    SnpDebugPrint (0x80000000, "\nsnp->undi.receive()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  //
  * Copy received data info from the DB
  //
  *BufferSize = Db->DataOffset;

  if (HeaderSize != NULL) {
    *HeaderSize = Db->MediaHeaderLen;
  }

  if (SrcAddr != NULL) {
    SnpCopyMem (SrcAddr, Db->SrcAddr, Snp->HwAddressSize);
  }

  if (DestAddr != NULL) {
    SnpCopyMem (DestAddr, Db->DestAddr, Snp->HwAddressSize);
  }

  if (Protocol != NULL) {
    *Protocol = (UINT16)(Db->ProtocolType >> 8) |
                (UINT16)(Db->ProtocolType << 8);
  }

  //
  // Update MediaPresent flag
  //
  if (Snp->MediaPresentSupported && !Snp->MediaPresent) {
    Snp->MediaPresent = TRUE;
  }

  //
  * Check if buffer was too small
  //
  if (ReceivedSize < *BufferSize) {
    return EFI_BUFFER_TOO_SMALL;
  }

  return EFI_SUCCESS;
}

/**
  SNP Receive protocol entry point.

  @param  This        Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  HeaderSize  Optional pointer to receive header size.
  @param  BufferSize  On input, size of the buffer. On output, size of received data.
  @param  Buffer      Pointer to the receive buffer.
  @param  SrcAddr     Optional pointer to receive source address.
  @param  DestAddr    Optional pointer to receive destination address.
  @param  Protocol    Optional pointer to receive protocol type.

  @retval EFI_SUCCESS            Receive completed.
  @retval EFI_NOT_STARTED        Driver not initialized.
  @retval EFI_INVALID_PARAMETER  Invalid parameter.
  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
**/
EFI_STATUS
EFIAPI
SnpReceive (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  OUT UINTN                       *HeaderSize,
  OUT UINTN                       *BufferSize,
  OUT VOID                        *Buffer,
  OUT EFI_MAC_ADDRESS             *SrcAddr,
  OUT EFI_MAC_ADDRESS             *DestAddr,
  OUT UINT16                      *Protocol
  )
{
  SNP_DRIVER  *Snp;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  if (Snp->UndiState != SNP_STATE_INITIALIZED) {
    return EFI_NOT_STARTED;
  }

  if (!(Snp->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST)) {
    return EFI_NOT_STARTED;
  }

  return SnpReceiveInternal (
           Snp,
           Buffer,
           BufferSize,
           HeaderSize,
           (UINT32 *)SrcAddr,
           (UINT32 *)DestAddr,
           Protocol
           );
}

//
// ============================================================================
// File: Mcast_ip_to_mac.c - SNP McastIpToMac Protocol
// ============================================================================

/**
  CDB opcode 12 (MCAST_IP_TO_MAC). Converts an IP address to a MAC address.

  @param  Snp  Pointer to the SNP_DRIVER instance.
  @param  Ip   Pointer to the IP address.
  @param  Mac  Pointer to receive the MAC address.
  @param  IPv6 Whether the IP address is IPv6.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpMcastIpToMacInternal (
  IN  SNP_DRIVER    *Snp,
  IN  EFI_IP_ADDRESS  *Ip,
  OUT EFI_MAC_ADDRESS *Mac,
  IN  BOOLEAN       IPv6
  )
{
  SNP_CDB  *Cdb;

  Cdb = &Snp->Cdb;

  //
  * Set up the CDB for MCAST_IP_TO_MAC
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_MCAST_IP_TO_MAC;
  Cdb->OpFlags   = IPv6 ? 1 : 0;
  Cdb->StatFlags = Snp->HwAddressSize;
  Cdb->CpbAddr   = (UINT64)(UINTN)Ip;
  Cdb->CpbSize   = (UINT16)(IPv6 ? 16 : 4);
  Cdb->DbAddr    = (UINT64)(UINTN)Mac;
  Cdb->DbSize    = (UINT16)Snp->HwAddressSize;
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;

  SnpDebugPrint (0x4000, "\nsnp->undi.mcast_ip_to_mac()  ");

  //
  // Execute the UNDI MCAST_IP_TO_MAC command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    if (Cdb->OpStatus == 19) {
      return EFI_NO_MEDIA;
    }
    SnpDebugPrint (0x80000000, "\nsnp->undi.mcast_ip_to_mac()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

/**
  SNP McastIpToMac protocol entry point.

  @param  This  Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  IPv6  Whether the IP address is IPv6.
  @param  Ip    Pointer to the IP address.
  @param  Mac   Pointer to receive the MAC address.

  @retval EFI_SUCCESS  Conversion completed.
**/
EFI_STATUS
EFIAPI
SnpMcastIpToMac (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN BOOLEAN                      IPv6,
  IN EFI_IP_ADDRESS               *Ip,
  OUT EFI_MAC_ADDRESS             *Mac
  )
{
  SNP_DRIVER  *Snp;

  if (This == NULL || Ip == NULL || Mac == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  //
  * Check state
  //
  if (Snp->UndiState == SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  if (Snp->UndiState != SNP_STATE_INITIALIZED) {
    return EFI_DEVICE_ERROR;
  }

  return SnpMcastIpToMacInternal (Snp, Ip, Mac, IPv6);
}

//
// ============================================================================
// File: Nvdata.c - SNP Nvdata Protocol
// ============================================================================

/**
  CDB opcode 13 (NVDATA). Reads NVRAM data from the UNDI.

  @param  Snp         Pointer to the SNP_DRIVER instance.
  @param  Offset      Offset into NVRAM data.
  @param  BufferSize  Size of the buffer.
  @param  Buffer      Pointer to the buffer.

  @return EFI_STATUS.
**/
UINT64
EFIAPI
SnpNvdataInternal (
  IN  SNP_DRIVER  *Snp,
  IN  UINTN       Offset,
  IN  UINTN       BufferSize,
  OUT VOID        *Buffer
  )
{
  SNP_CDB  *Cdb;

  //
  * Validate parameters
  //
  if (Snp == NULL || Buffer == NULL || BufferSize == 0) {
    return EFI_INVALID_PARAMETER;
  }

  if (BufferSize > SNP_NVDATA_SIZE) {
    BufferSize = SNP_NVDATA_SIZE;
  }

  Cdb = &Snp->Cdb;

  //
  * Set up the CDB for NVDATA
  //
  Cdb->OpCode    = SNP_CDB_OPCODE_NVDATA;
  Cdb->OpFlags   = 0;
  Cdb->CpbAddr   = (UINT64)(UINTN)&Offset;
  Cdb->CpbSize   = sizeof (UINTN);
  Cdb->DbAddr    = (UINT64)(UINTN)Buffer;
  Cdb->DbSize    = (UINT16)BufferSize;
  Cdb->OpStatus  = 0;
  Cdb->StatCount = 0;
  Cdb->StatData  = 0;
  Cdb->StatFlags = Snp->HwAddressSize;

  SnpDebugPrint (0x4000, "\nsnp->undi.nvdata()  ");

  //
  // Execute the UNDI NVDATA command
  //
  ((void (*)(VOID *))Snp->UndiEntry)(Cdb);

  if (Cdb->OpStatus != 0) {
    if (Cdb->OpStatus == 12) {
      return EFI_NOT_FOUND;
    }
    SnpDebugPrint (0x80000000, "\nsnp->undi.nvdata()  %xh:%xh\n", Cdb->StatFlags, Cdb->OpStatus);
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

/**
  SNP Nvdata protocol entry point.

  @param  This       Pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
  @param  ReadWrite  TRUE for read, FALSE for write.
  @param  Offset     Offset into NVRAM.
  @param  BufferSize Size of the buffer.
  @param  Buffer     Pointer to the buffer.

  @retval EFI_SUCCESS            NVRAM operation completed.
  @retval EFI_INVALID_PARAMETER  Invalid parameter.
  @retval EFI_UNSUPPORTED        Write not supported.
**/
EFI_STATUS
EFIAPI
SnpNvdata (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *This,
  IN BOOLEAN                      ReadWrite,
  IN UINTN                        Offset,
  IN UINTN                        BufferSize,
  IN OUT VOID                     *Buffer
  )
{
  SNP_DRIVER  *Snp;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Snp = SNP_DRIVER_FROM_PROTOCOL (This);

  //
  * Check state
  //
  if (Snp->UndiState == SNP_STATE_STOPPED) {
    return EFI_NOT_STARTED;
  }

  if (Snp->UndiState != SNP_STATE_INITIALIZED) {
    return EFI_DEVICE_ERROR;
  }

  //
  * Validate parameters
  //
  if (Buffer == NULL || BufferSize == 0) {
    return EFI_INVALID_PARAMETER;
  }

  if (!ReadWrite) {
    return EFI_UNSUPPORTED;
  }

  //
  * Validate offset and size
  //
  if (Offset + BufferSize > SNP_NVDATA_SIZE) {
    return EFI_INVALID_PARAMETER;
  }

  return SnpNvdataInternal (Snp, Offset, BufferSize, Buffer);
}