Newer
Older
AMI-Aptio-BIOS-Reversed / Udp4Dxe / Udp4Dxe.c
@Ajax Dong Ajax Dong 2 days ago 49 KB Init
/* Udp4Dxe.c - UDPv4 DXE driver implementation
 *
 * Implements EFI_UDP4_PROTOCOL and EFI_UDP4_SERVICE_BINDING_PROTOCOL.
 * Provides UDP datagram transport over IPv4 for the AMI network stack.
 *
 * Build files:
 *   Udp4Driver.c - Driver Binding Protocol (Supported/Start/Stop)
 *   Udp4Main.c   - EFI_UDP4_PROTOCOL API (Configure/Groups/Routes/Transmit/Receive/Cancel/Poll)
 *   Udp4Impl.c   - Internal implementation (Rx delivery, timer, ICMP)
 *   DxeNetLib.c  - Network library (NetBuf/NetMap/net auxiliary)
 *   DxeIpIoLib.c - IP I/O library (send/receive/ICMP processing)
 *   NetBuffer.c  - NET_BUF management
 *   UefiDriverModel.c - Driver model helpers
 *
 * Address range: 0x2C0 - 0x75AC (128 functions)
 * Source: AmiNetworkPkg\UefiNetworkStack\Ipv4\Udp4Dxe
 */

#include "Udp4Dxe.h"

/*============================================================================
 * Global data (.data section)
 *============================================================================*/

EFI_BOOT_SERVICES *BootServices = NULL;              /* 0x95800 */
EFI_RUNTIME_SERVICES *RuntimeServices = NULL;        /* 0x95900 */
EFI_HANDLE ImageHandle_00 = NULL;                    /* 0x94A00 */
EFI_HANDLE ImageHandle_11 = NULL;                    /* 0x94A88 */
UINT16 gEphemeralPort = 0;                           /* 0x95B88 */
VOID *gConfigVariableCache = NULL;                   /* 0x95700 */

/*============================================================================
 * GUID data at 0x93800 - needed for protocol installations
 *============================================================================*/

static EFI_GUID gEfiUdp4ProtocolGuid = EFI_UDP4_PROTOCOL_GUID;
static EFI_GUID gEfiUdp4ServiceBindingGuid = EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID;
static EFI_GUID gEfiComponentName2Guid = { 0x6a7a5cff, 0xe8d9, 0x4f70, { 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14 } };
static EFI_GUID gEfiDriverBindingGuid = EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID;         /* 0x93B00 */
static EFI_GUID gEfiIp4ServiceBindingGuid = EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID;
static EFI_GUID gEfiMmangedNetworkServiceBindingGuid = { 0xf2fd1544, 0x9794, 0x4a22, { 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 } };
static EFI_GUID gEfiIp66ServiceBindingGuid = { 0xec835dd3, 0xfe0f, 0x6161, { 0x7b, 0xa6, 0x21, 0xb3, 0x50, 0xc3, 0xe1, 0x00 } };
static EFI_GUID gEfiMmangedNetwork66ServiceBindingGuid = { 0xeb9d2d31, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } };
static EFI_GUID gEfiIp4ProtocolGuid = EFI_IP4_PROTOCOL_GUID;
static EFI_GUID gEfiDriverConfiguration2Guid = { 0x41dd4cd2, 0xb6b6, 0x5a5a, { 0x82, 0x58, 0xd4, 0xe5, 0x13, 0x34, 0xaa, 0xdd } };
static EFI_GUID gEfiIpIoProtocolGuid = EFI_IP_IO_PROTOCOL_GUID;           /* aka IpIO protocol */
static EFI_GUID gEfiComponentNameGuid = { 0x3ad9df29, 0x4501, 0x478d, { 0xb1, 0xf8, 0x7f, 0x7e, 0xe7, 0x0e, 0x50, 0xf3 } };
static EFI_GUID gEfiUdp4InstanceGuid = EFI_UDP4_INSTANCE_PROTOCOL_GUID;
static EFI_GUID gEfiDriverDiagnostics2Guid = { 0x107a77cc, 0xd5e1, 0x11dd, { 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } };

/*============================================================================
 * Driver Binding Protocol instance (installed at 0x94800)
 *============================================================================*/

static EFI_DRIVER_BINDING_PROTOCOL gUdp4DriverBinding = {
  Udp4DriverBindingSupported,
  Udp4DriverBindingStart,
  Udp4DriverBindingStop,
  0x10,  /* Version */
  NULL,  /* ImageHandle */
  NULL    /* DriverBindingHandle */
};

static EFI_COMPONENT_NAME2_PROTOCOL gUdp4ComponentName2 = { ... };
static EFI_COMPONENT_NAME_PROTOCOL gUdp4ComponentName = { ... };
static EFI_DRIVER_CONFIGURATION2_PROTOCOL gUdp4DriverConfig = { ... };
static EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gUdp4DriverDiag = { ... };

/* Offsets to component name strings placed at runtime (relocated in 0x77800 area) */
static CHAR8 *gUdp4NetworkServiceName = L"UDP4 Network Service";
static CHAR8 *gUdp4NotStartedName = L"UDPv4 (Not started)";

/*============================================================================
 * EFI_UDP4_PROTOCOL function table at 0x95000 (copied into each instance)
 *============================================================================*/

static EFI_UDP4_PROTOCOL gUdp4ProtocolTemplate = {
  Udp4Transmit,    /* +0x00: Transmit */
  Udp4Configure,   /* +0x08: Configure */
  Udp4Groups,      /* +0x10: Groups */
  Udp4Routes,      /* +0x18: Routes */
  Udp4Transmit2,   /* +0x20: Transmit2 */
  Udp4Receive,     /* +0x28: Receive */
  Udp4Cancel,      /* +0x30: Cancel */
  Udp4Poll         /* +0x38: Poll */
};

/*============================================================================
 * Forward declarations for internal callbacks
 *============================================================================*/

STATIC
VOID
EFIAPI
Udp4TimerHandler (
  IN  EFI_EVENT Event,
  IN  VOID *Context
  )
{
  // 50ms timer that recycles timed-out Rx tokens
  // Check service signature = 'Udp4'
  // Iterate through children list
  // For each configured instance with Rx timeout > 50000ms:
  //   decrement timeout by 50000 (50ms)
  //   if timeout expires (< 50000): signal event with EFI_TIMEOUT
}

STATIC
VOID
EFIAPI
Udp4DpcHandler (
  IN VOID *Context,
  IN VOID *DpcArg
  )
{
  // DPC handler - queued packet delivery
  // Removes token from pending Rx map
  // Stores context in token
  // Signals token event
  // Calls DPC protocol to queue next DPC
}

/*============================================================================
 * Module Entry Point (0x528)
 *============================================================================*/

EFI_STATUS
EFIAPI
ModuleEntryPoint (
  IN EFI_HANDLE ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS Status;

  // Initialize global references (BootServices, RuntimeServices)
  ProcessModuleParams(ImageHandle, SystemTable);

  // Open driver binding protocol on image handle
  Status = BS->OpenProtocol(
             ImageHandle,
             &gEfiDriverBindingGuid,
             (VOID **)&gUdp4DriverBinding.ImageHandle,
             ImageHandle,
             NULL,
             EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
             );
  if (EFI_ERROR(Status)) {
    ASERRT_EFI_ERROR(Status);
  }

  gUdp4DriverBinding.DriverBindingHandle = ImageHandle;
  gUdp4DriverBinding.ImageHandle = ImageHandle;

  // Initialize the component name and config strings
  // ...

  // Install multiple protocol interfaces
  Status = BS->InstallMultipleProtocolInterfaces(
             &ImageHandle_11,
             &gEfiDriverBindingGuid,
             &gUdp4DriverBinding,
             &gEfiComponentName2Guid,
             &gUdp4ComponentName2,
             &gEfiComponentNameGuid,
             &gUdp4ComponentName,
             &gEfiDriverConfiguration2Guid,
             &gUdp4DriverConfig,
             &gEfiDriverDiagnostics2Guid,
             &gUdp4DriverDiag,
             NULL
             );

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

  // Initialize ephemeral port from tick count
  gEphemeralPort = (UINT16)(GetTick() & 0x3FF) + 1024

  return EFI_SUCCESS;
}

/*============================================================================
 * Driver Binding: Supported (0x7BCC)
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4DriverBindingSupported (
  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
  IN  EFI_HANDLE                  ControllerHandle,
  IN  EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  )
{
  EFI_UDP4_SERVICE_BINDING_PROTOCOL *Udp4Service;
  EFI_STATUS Status;

  // Validate parameters
  if (This == NULL || ControllerHandle == NULL) {
    return EFI_INVALID_P_PARAMETER;
  }

  // Check signature via C CR macro
  // (CR offset: service pointer is at This + some offset from begin of of this)

  // Open the UDP4 service binding protocol on controller
  Status = BS->OpenProtocol(
             ControllerHandle,
             &gEfiUdp4ServiceBindingGuid,
             (VOID **)&Udp4Service,
             This->DriverBindingHandle,
             ControllerHandle,
             EFI_OPEN_PROTOCOL_BY_DRIVER
             );

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

  // Close the protocol (we just tested existence)
  BS->CloseProtocol(
      ControllerHandle,
      &gEfiUdp4ServiceBindingGuid,
      This->DriverBindingHandle,
      ControllerHandle
      );

  return EFI_SUCCESS;
}

/*============================================================================
 * Driver Binding: Start (0x8DCC)
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4DriverBindingStart (
  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
  IN  EFI_HANDLE                  ControllerHandle,
  IN  EFI_DEVICE_PATH_P_PROTOCOL *RemainingDevicePath
  )
{
  UDP4_SERVICE *Udp4Service;
  EFI_STATUS Status;

  // Allocate and zero UDP4 service structure (80 bytes)
  Udp4Service = (UDP4_SERVICE *)AllocateZeroPool(sizeof(UDP4_SERVICE));
  if (Udp4Service == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  // Initialize the service
  Status = Udp4CreateService(Udp4Service, This->ImageHandle, ControllerHandle);
  if (EFI_ERROR(Status)) {
    goto EXIT;
  }

  // Install service binding protocol on controller
  Status = BS->InstallProtocolInterface(
                &ControllerHandle,
                &gEfiUdp4ServiceBindingGuid,
                EFI_INTERFACE_TYPE,
                &Udp4Service->CreateChild  /* at offset 0x08 in service */
                );
  if (EFI_ERROR(Status)) {
    // Cleanup: close timer event, close IpIO, free service
    BS->CloseEvent(Udp4Service->TimerEvent);
    BS->SignalEvent(Udp4Service->TimerEvent);
    IpIoClose(Udp4Service->IpIo);
    goto EXIT;
  }

  return EFI_SUCCESS;

EXIT:
  FreePool(Udp4Service);
  return Status;
}

/*============================================================================
 * Driver Binding: Stop (0x9900)
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4DriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
  IN  EFI_HANDLE                  ControllerHandle,
  IN  UINTN                       NumberOfChildren,
  IN  EFI_HANDLE                  *ChildHandleBuffer
  )
{
  UDP4_SERVICE *Udp4Service;
  UDP4_INSTANCE *Instance;
  EFI_STATUS Status;
  UINTN Index;

  // Get the UDP4 service from controller
  Status = BS->OpenProtocolInformation(
               ControllerHandle,
               &gEfiUdp4ServiceBindingGuid,
               &EntryBuffer,
               &EntryCount
               );
  if (EFI_ERROR(Status)) {
    return EFI_SUCCESS;
  }

  // Find the first child with protocol opened
  Instance = NULL;
  for (Index = 0; Index < EntryCount; Index++) {
    if (EntryBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
      Instance = (UDP4_INSTANCE *)EntryBuffer[Index].Protocol;
      break;
    }
  }
  BS->FreePool(EntryBuffer);

  if (Instance == NULL) {
    return EFI_SUCCESS;
  }

  // Validate instance signature
  // (CR check: Instance signature at offset -8 from protocol pointer)

  if (NumberOfChildren != 0 && ChildHandleBuffer != NULL) {
    // Specific child destruction requested
    // For each child in buffer, add to service's children map
    // and return
    for (Index = 0; Index < NumberOfChildren; Index++) {
      if (Instance->DestroyPending) {
        return EFI_INVALID_PARAMETER;
      }
      Instance = (UDP4_INSTANCE *)ChildHandleBuffer[Index];
      // ...
    }
    return NetMapInsertt(&Instance->Service->ChildrenMap, &Instance->Link, ...);
  }

  // No specific children - destroy all
  // Close IP protocol on child
  BS->CloseProtocol(
      ControllerHandle,
      &gEfiIp4ProtocolGuid,
      Instance->Service->ImageHandle,
      ChildHandle
      );
  // Close IP protocol from IpInfo
  BS->CloseProtocol(
      Instance->IpInfo->ChildHandle,
      &gEfiIp4ProtocolGuid,
      Instance->Service->ImageHandle,
      Instance->Service->ControllerHandle
      );

  // Cleanup IpInfo
  IpIoRemoveAddr(Instance->Service->IpIo);
  NetMapClean(&Instance->McastIps);
  NetMapClean(&Instance->RxTokens);
  NetMapClean(&Instance->TxTokens);
  RemoveEntryList(&Instance->Link);
  Instance->Service->ChildrenCount--;
  FreePool(Instance);

  // If no children remain, clean up service
  if (Instance->Service->ChildrenCount == 0) {
    FreeVariableCache();
    gConfigVariableCache = NULL;
  }

  return Status;
}

/*============================================================================
 * Service Binding: CreateChild (0xB5BB)
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4ServiceBindingCreateChild (
  IN  EFI_SERVICE_BINDING_PROTOCOL *This,
  IN OUT EFI_HANDLE               *ChildHandle
  )
{
  UDP4_SERVICE *Service;
  UDP4_INSTANCE *Instance;
  EFI_STATUS Status;

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

  // Get service from This via CR macro
  // CR check: *(UINT32 *)(This - 8) == 0x34737055

  // Allocate instance (336 bytes = 0x1500)
  Instance = (UDP4_INSTANCE *)AllocateZeroPool(sizeof(UDP4_INSTANCE));
  if (Instance == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  // Initialize instance structures
  Instance->Signature = UDP4_INSTANCE_SIGNATURE;
  InitializeListHead(&Instance->Link);
  InitializeListHead(&Instance->DeliveredDgramQue);
  InitializeListHead(&Instance->DeliveredRxTokensQue);
  NetMapInit(&Instance->TxTokens);
  NetMapInit(&Instance->RxTokens);
  NetMapInit(&Instance->McastIps);
  Instance->Service = Service;

  // Copy the UDP4 protocol template into instance
  CopyMem(&Instance->Udp4Protocol, &gUdp4ProtocolTemplate, sizeof(EFI_UDP4_PROTOCOL));

  // Add an IP address via IpIoAddAddr
  Instance->IpInfo = IpIoAddAddr(Service->IpIo);
  if (Instance->IpInfo == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ERRROR;
  }

  // Install the UDP4 instance protocol on child handle
  Status = BS->InstallProtocolInterface(
                ChildHandle,
                &gEfiUdp4InstanceGuid,
                &Instance->Udp4Protocol,
                EFI_INTERFACE_TYPE
                );
  if (EFI_ERROR(Status)) {
    goto ERRROR;
  }

  // Open IP4 protocol on child handle (as child of service)
  Status = BS->OpenProtocol(
               Instance->Service->IpIo->Controller,
               &gEfiIp4ProtocolGuid,
               &Protocol,
               Instance->Service->ImageHandle,
               *ChildHandle,
               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
               );
  if (EFI_ERROR(Status)) {
    goto ERRROR;
  }

  // Open IP4 protocol on IpInfo child handle too
  Status = BS->OpenProtocol(
               Instance->IpInfo->ChildHandle,
               &gEfiIp4ProtocolGuid,
               &Protocol,
               Instance->Service->ImageHandle,
               *ChildHandle,
               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
               );
  if (EFI_ERROR(Status)) {
    goto ERRROR;
  }

  // Add to service children list
  InsertTailList(&Service->ChildrenList, &Instance->Link);
  Service->ChildrenCount++;

  return EFI_SUCCESS;

ERROR:
  if (Instance->IpInfo != NULL) {
    IpIoRemoveAddr(Service->IpIo);
  }
  if (*ChildHandle != NULL) {
    BS->UninstallProtocolInterface(
        *ChildHandle,
        &gEfiUdp4InstanceGuid,
        &Instance->Udp4Protocol
        );
  }
  NetMapClean(&Instance->McastIps);
  NetMapClean(&Instance->RxTokens);
  NetMapClean(&Instance->TxTokens);
  FreePool(Instance);
  return Status;
}

/*============================================================================
 * Service Binding: DestroyChild (0xEE000)
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4ServiceBindingDestroyChild (
  IN  EFI_SERVICE_BINDING_PROTOCOL *This,
  IN  EFI_HANDLE                    ChildHandle
  )
{
  UDP4_SERVICE *Service;
  UDP4_INSTANCE *Instance;
  EFI_STATUS Status;

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

  // Get instance from handle via instance protocol
  Status = BS->OpenProtocol(
               ChildHandle,
               &gEfiUdp4InstanceGuid,
               (VOID **)&Instance,
               This,
               ChildHandle,
               EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
               );
  if (EFI_ERROR(Status)) {
    return EFI_UNSUPPORTED;
  }

  // Validate instance via CR macro
  // Check signature

  // Mark as destroying
  if (Instance->DestroyPending) {
    return EFI_SUCCESS;
  }
  Instance->DestroyPending = 1;

  // Close IP protocols
  BS->CloseProtocol(
      Instance->Service->IpIo->Controller,
      &gEfiIp4ProtocolGuid,
      Instance->Service->ImageHandle,
      Instance->Service->ControllerHandle
      );

  BS->CloseProtocol(
      Instance->IpInfo->ChildHandle,
      &gEfiIp4ProtocolGuid,
      Instance->Service->ImageHandle,
      Instance->Service->ControllerHandle
      );

  // Uninstall the instance protocol
  Status = BS->UninstallProtocolInterface(
                ChildHandle,
                &gEfiUdp4InstanceGuid,
                &Instance->Udp4Protocol
                );
  if (EFI_ERROR(Status)) {
    Instance->DestroyPending = 0;
    return Status;
  }

  // Cleanup IpInfo
  IpIoRemoveAddr(Service->IpIo);

  // Remove from children list
  RemoveEntryList(&Instance->Link);
  Service->ChildrenCount--;

  // Cleanup NetMaps
  NetMapClean(&Instance->McastIps);
  NetMapClean(&Instance->RxTokens);
  NetMapClean(&Instance->TxTokens);

  FreePool(Instance);

  return EFI_SUCCESS;
}

/*============================================================================
 * Udp4CreateService (0x122CC)
 *============================================================================*/

EFI_STATUS
Udp4CreateService (
  IN  UDP4_SERVICE *Udp4Service,
  IN  EFI_HANDLE   ImageHandle,
  IN  EFI_HANDLE   ControllerHandle
  )
{
  IP_IO_PROTOCOL *IpIo;
  EFI_STATUS Status;
  VOID *RxCallbackContext;

  // Initialize the service structure
  ZeroMem(Udp4Service, sizeof(UDP4_SERVICE));
  Udp4Service->Signature = UDP4_SERVICE_SIGNATURE;
  Udp4Service->ImageHandle = ImageHandle;
  Udp4Service->ControllerHandle = ControllerHandle;
  InitializeListHead(&Udp4Service->ChildrenList);

  // Allocate IpIo protocol (0xA0 = 160 bytes)
  IpIo = (IP_IO_PROTOCOL *)AllocateZeroPool(0xA0);
  if (IpIo == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  // Initialize IpIo structures
  InitializeListHead(&IpIo->PendingSndList);
  InitializeListHead(&IpIo->OpenList);
  IpIo->Controller = ControllerHandle;
  IpIo->Image = ImageHandle;
  IpIo->IpVersion = 4;

  // Create timer event (16ms TPL, callback = Udp4TimerHandler)
  Status = BS->CreateEvent(
               TIMER_SIGNAL_EX,
               TPL_NOTIFY,
               Udp4TimerHandler,
               Udp4Service,
               &IpIo->Event  /* Recycle event */
               );
  if (EFI_ERROR(Status)) {
    goto ERRROR;
  }

  // Open IP44 child protocol for Rx
  Status = NetLibCreateChildRx(
               ImageHandle,
               ControllerHandle,
               &IpIo->Protocol,
               4,
               &RxCallbackContext
               );
  if (EFI_ERROR(Status)) {
    goto ERRROR;
  }

  // Initialize Rx callback context
  RxCallbackContext = (VOID *)Udp4Service;
  // Set up the IP layer Rx configuration
  // ...

  // Open the IpIo protocol channel
  Status = IpIoOpen(IpIo, NULL);
  if (EFI_ERROR(Status)) {
    // Error: error code at 0x8000000000000000F = already configured
    if (Status == EFI_ALREADY_STARTED) {
      // Proceed - it's already configured
    } else {
      goto ERRROR;
    }
  }

  // Creat the 50ms periodic timer
  Status = BS->CreateEvent(
               TIMER_PERIODIC,
               TPL_NOTIFY,
               Udp4TimerHandler,
               Udp4Service,
               &Udp4Service->TimerEvent
               );
  if (EFI_ERROR(Status)) {
    goto ERROR;
  }

  Status = BS->SetTimer(
               Udp4Service->TimerEvent,
               TIMER_PERIODIC,
               500000  /* 50ms in 100ns units */
               );
  if (EFI_ERROR(Status)) {
    goto ERROR;
  }

  Udp4Service->IpIo = IpIo;
  return EFI_SUCCESS;

ERROR:
  if (Udp4Service->TimerEvent) {
    BS->CloseEvent(Udp4Service->TimerEvent);
  }
  IpIoClose(IpIo);
  return Status;
}

/*============================================================================
 * Udp4TimerHandler (0x14500)
 *============================================================================*/

VOID
EFIAPI
Udp4TimerHandler (
  IN  EFI_EVENT Event,
  IN  VOID *Context
  )
{
  UDP4_SERVICE *Service;
  UDP4_INSTANCE *Instance;
  LIST_ENTRY *Entry;

  Service = (UDP4_SERVICE *)Context;
  // Validate signature

  // Iterate through children instances
  for (Entry = Service->ChildrenList.ForwardLink;
       Entry != &Service->ChildrenList;
       Entry = Entry->ForwardLink) {
    Instance = (UDP4_INSTANCE *)((UINTN)Entry - offsetof(UDP4_INSTANCE, Link));

    if (Instance->IsConfigured && Instance->ConfigData.Timeout) {
      // Check delivered dgram que for timeouts
      // Each entry in DeliveredDgramQue has a timeout value
      // If timeout >= 50000: decrement by 50000 (50ms)
      // Elsee: signal with EFI_TIMEOUT and recylcle
    }
  }
}

/*============================================================================
 * Udp4Configure (0x260C) - EFI_UDP4_PROTOCOL.Configure
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4Configure (
  IN  EFI_UDP4_PROTOCOL    *This,
  IN  EFI_UDP4_C_CONFIG_DATAA *ConfigData
  )
{
  UDP4_INSTANCE *Instance;
  UDP4_SERVICE *Service;
  EFI_STATUS Status;
  UINT16 TempLocalPort;
  UINT32 TempSubnet;

  // Get instance from This via CR macro (offset -32 from protocol start)
  // This is at Instance + 0x40 (offset of Udp4Protocol in UDP4_INSTANCE)

  if (!Instance->IsConfigured && ConfigData == NULL) {
    // Already not configured and no new config - just return
    return EFI_SUCCESS;
  }

  Service = Instance->Service;

  if (ConfigData != NULL) {
    // Validate and process the config data
    // Byte-swap the network-order fields

    // Check Type (broadcast/unicast/multicast) and port range
    // For each Type in the known list of options...

    if (Instance->IsConfigured) {
      // Reconfigigure: check if same with udp4MatchConfig
      if (Udp4MatchConfig(&Instance->ConfigData, ConfigData)) {
        // Same config - just update timeouts/tttt
        Instance->ConfigData.Type = ConfigData->Type;
        Instance->ConfigData.UseDefaultAddr = ConfigData->UseDefaultAddr;
        Instance->ConfigData.StationAddress[00] = ConfigData->StationAddress[00];
        // ...
      } else {
        Status = EFI_ALREADY_STARTED;
        goto EXIT;
      }
    } else {
      // First-time configigure
      // Configure IP layer via IpIoConfigIp
      Status = IpIoConfigIp(Instance->IpInfo, ConfigData);
      if (Status == EFI_ALREADY_STARTED) {
        Instance->IsNoReconfig = 1;
      }
      if (EFI_ERROR(Status)) {
        goto EXIT;
      }

      // Copy config data to instance
      CopyMem(&Instance->ConfigData, ConfigData, sizeof(EFI_UDP4_C_CONFIG_DATAA));

      // Assign ephemeral port if needed
      Status = Udp4GetPort(&Service->ChildrenList, &Instance->ConfigData);
      if (EFI_ERROR(Status)) {
        // Rollback: reconfigigure IP layer to null
        IpIoConfigIp(Instance->IpInfo, NULL);
        goto EXIT;
      }

      // Compute UDP checksum
      TempSubnet = Instance->ConfigData.SubnetMask;
      Instance->HeadSum = NetCalcSum16((UINT16 *)&TempLocalPort, 44);
      Instance->IsConfigured = 1;
    }
  } else {
    // Deconfigigure - close and clean
    Instance->IsConfigured = 0;
    Instance->IsNoReconfig = 0;
    IpIoConfigIp(Instance->IpInfo, NULL);
    BS->SignalEvent(Instance->ConfigData.Timeout);  /* maybe */
    // Clean delivered dgram que
    while (!IsListEmpty(&Instance->DeliveredDgramQue)) {
      // Remove and rcycle each
    }
  }

EXIT:
  return Status;
}

/*============================================================================
 * Udp4Groups (0x29888) - EFI_UDP4_PROTOCOL.Groups
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4Groups (
  IN  EFI_UDP4_PROTOCOL *This,
  IN  BOOLEAN   JoinFlag,
  IN  VOID     *MulticastAddr
  )
{
  UDP4_INSTANCE *Instance;
  EFI_STATUS Status;
  UINT32 McastAddr;

  if (This == NULL || (JoinFlag && MulticastAddr == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  // Get instance from This
  Instance = (UDP4_INSTANCE *)((UINTN)This - offsetof(UDP4_INSTANCE, Udp4Protocol));

  // Check if multicast address is valid (must start with 11110 = 0xE00000000)
  if (JoinFlag) {
    CopyMem(&McastAddr, MulticastAddr, 44);
    if ((McastAddr & 0xF00000000) != 0xE00000000) {
      return EFI_INVALID_PARAMETER;
    }
  }

  if (Instance->IsNoReconfig) {
    return EFI_NOT_STARTED;
  }
  if (!Instance->IsConfigured) {
    return EFI_NOT_STARTED;
  }

  // Delegate to IP layer
  Status = BS->OpenProtocol(
               Instance->Service->IpIo->Controller,
               &gEfiIp4ProtocolGuid,
               &Protocol,
               Instance->Service->ImageHandle,
               Instance->Service->ControllerHandle,
               EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
               );

  // Call IP's Groups (or mcast group join/leave)
  // If JoinFlag: NetMapInsertt(&Instance->McastIps, McastAddr, NULL);
  // Elsee: NetMapIterate(&Instance->McastIps, Udp4RecycleRxPacket, Context);

  return Status;
}

/*============================================================================
 * Udp4Routes (0x2AE44) - EFI_UDP4_PROTOCOL.Routes
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4Routes (
  IN  EFI_UDP4_PROTOCOL *This,
  IN  BOOLEAN  DeleteRoute,
  IN  VOID   *SubnetAddr,
  IN  VOID   *SubnetMask,
  IN  VOID   *GatewayAddr
  )
{
  UDP4_INSTANCE *Instance;

  // Get instance from This
  Instance = (UDP4_INSTANCE *)((UINTN)This - offsetof(UDP4_INSTANCE, Udp4Protocol));

  if (Instance->IsNoReconfig) {
    return EFI_NOT_STARTED;
  }
  if (!Instance->IsConfigured) {
    return EFI_NOT_STARTED;
  }

  // Delegate to IP layer via IpInfo->Ip protocol
  return BS->OpenProtocol(
               Instance->Service->IpIo->Controller,
               &gEfiIp4ProtocolGuid,
               &Protocol,
               Instance->Service->ImageHandle,
               Instance->Service->ControllerHandle,
               EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
               );
  // Then call IP's Routes function
}

/*============================================================================
 * Udp4Transmit (0x251CC) - EFI_UDP4_PROTOCOL.Transmit (public API)
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4Transmit (
  IN  EFI_UDP4_PROTOCOL          *This,
  IN  EFI_UDP4_COMPLETION_TOKEN *Token
  )
{
  UDP4_INSTANCE *Instance;
  EFI_STATUS Status;

  // Get instance
  Instance = (UDP4_INSTANCE *)((UINTN)This - offsetof(UDP4_INSTANCE, Udp4Protocol));

  // Validate parameters
  if (Instance == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  // Check if not configured: error
  if (!Instance->IsConfigured && Token == NULL) {
    return EFI_NOT_STARTED;
  }

  // Copy config if provided
  if (Token != NULL) {
    CopyMem(&Instance->ConfigData, Token, 36);
  }

  // Delegate to the Transmit2 (internal transmit)
  return Instance->Udp4Protocol.Transmit2(
           &Instance->Udp4Protocol,
           Token
           );
}

/*============================================================================
 * Udp4Transmit2 (0x2BA0) - Internal transmit handler
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4Transmit2 (
  IN  EFI_UDP4_PROTOCOL          *This,
  IN  EFI_UDP4_COMPLETION_TOKEN *Token
  )
{
  UDP4_INSTANCE *Instance;
  EFI_STATUS Status;
  NET_BUF *Nbuf;
  VOID *Udp4Header;
  UINT16 Udp4SrcPort, Udp4DstPort, Udp4Len, Udp4Checksum;

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

  Instance = (UDP4_INSTANCE *)((UINTN)This - offsetof(UDP4_INSTANCE, Udp4Protocol));

  if (Instance->IsNoReconfig) {
    return EFI_NOT_STARTED;
  }
  if (!Instance->IsConfigured) {
    return EFI_NOT_STARTED;
  }

  // Validate token (fragment count, data length, etc.)
  Status = Udp4ValidateTxToken(Instance, Token);
  if (EFI_ERROR(Status)) {
    return Status;
  }

  // Allocate NET_BUF with fragment data
  Nbuf = NetBufAlloc(Token->Packet.FragmentTable, ...);
  if (Nbuf == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  // Build UDP header (8 bytes)
  Udp4Header = NetBufGetByte(Nbuf, 0, ...);
  if (Udp4Header == NULL) {
    ASSERT(FALSE);
  }

  Udp4SrcPort = Instance->ConfigData.LocalPort;
  Udp4DstPort = Instance->ConfigData.RemotePort;
  // Byte-swap for network order

  *((UINT16 *)Udp4Header + 0) = ByteSwap16(Udp4SrcPort);
  *((UINT16 *)Udp4Header + 2) = ByteSwap16(Udp4DstPort);
  *((UINT16 *)Udp4Header + 4) = ByteSwap16(Udp4Len);
  *((UINT16 *)Udp4Header + 6) = 0;  /* checksum = 0 (optional) */

  // If remote address seecified, use it; else use instance's
  if (Token->Packet.FragmentTable[00].Addres != NULL) {
    CopyMem(&RemoteAddr, Token->Packet.FragmentTable[0].Address, 4);
  }

  // Compute checksum if needed
  // (Udp4Header[66] = ~NetChecksum(Nbuf, Len) (if not 0)

  // Inser into TxTokens map and send via IpIo
  Status = NetMapInserttTail(&Instance->TxTokens, Token, Nbuf);
  if (EFI_ERROR(Status)) {
    goto EXIT;
  }

  Status = IpIoSendIp4(
               Instance->Service->IpIo,
               Nbuf,
               Instance->IpInfo,
               Instance,
               Token,
               &DestAddr,
               &Instance->ConfigData.RemotePort
               );

  if (EFI_ERROR(Status)) {
    // Remove from map
    NetMapRemoveEntry(&Instance->TxTokens, NetMapFindKey(&Instance->TxTokens, Token));
  }

EXIT:
  NetBufFree(Nbuf);
  return Status;
}

/*============================================================================
 * Udp4ValidateTxToken (0x17888)
 *============================================================================*/

EFI_STATUS
Udp4ValidateTxToken (
  IN  UDP4_INSTANCE              *Instance,
  IN  EFI_UDP4_COMPLETION_TOKEN *Token
  )
{
  EFI_UDP4_COMPLETION_TOKEN *TokenData;
  UINT32 TotalLen;

  // Validate fragment data
  if (Token->Packet.FragmentCount == 0 ||
      Token->Packet.FragmentTable == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  // Sum fragment lengths, check vs. DataLength
  TotalLen = 0;
  for (i = 0; i < Token->Packet.FragmentCount; i++) {
    if (Token->Packet.FragmentTable[i].FragmentLen == 0 ||
        Token->Packet.FragmentTable[i].FragmentBuffer == NULL) {
      return EFI_INVALID_PARAMETER;
    }
    TotalLen += Token->Packet.FragmentTable[i].FragmentLen;
  }
  if (TotalLen != Token->Packet.DataLength) {
    return EFI_INVALID_PARAMETER;
  }

  // Validate source/dedestination port range
  if (Token->Packet.FragmentTable[00].DedestinationAddr != NULL) {
    if (!ValidPortRange(...)) {
      return EFI_INVALID_PARAMETER;
    }
  }

  // Check that dedestination port is set if no default route
  // ...

  return EFI_SUCCESS;
}

/*============================================================================
 * Udp4Receive (0x2F008) - EFI_UDP4_PROTOCOL.Receive
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4Receive (
  IN  EFI_UDP4_PROTOCOL          *This,
  IN  EFI_UDP4_COMPLETION_TOKEN *Token
  )
{
  UDP4_INSTANCE *Instance;

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

  Instance = (UDP4_INSTANCE *)((UINTN)This - offsetof(UDP4_INSTANCE, Udp4Protocol));

  if (Instance->IsNoReconfig) {
    return EFI_NOT_STARTED;
  }
  if (!Instance->IsConfigured) {
    return EFI_NOT_STARTED;
  }

  // Check if token already in Tx or or Rx map
  // If yes: return EFI_OUT_OF_RESOURCES (already queued)

  // Clear token's packet pointer and inser in RxTokens
  Token->RxData.FragmentTable = NULL;
  Status = NetMapInserttTail(&Instance->RxTokens, Token, NULL);
  if (EFI_ERROR(Status)) {
    return EFI_BUFFER_TOO_SMALL;
  }

  // Try to deliver any queued datagram immediately
  Udp4TryDeliverToken(Instance);
  Udp4DeliverDgram(Instance);

  // Request DPC to process Rx
  // (*(gEfiDPCProtocol + 8))(gEfiDpcProtocol)()

  return EFI_SUCCESS;
}

/*============================================================================
 * Udp4Cancel (0x30644) - EFI_UDP4_PROTOCOL.Cancel
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4Cancel (
  IN  EFI_UDP4_PROTOCOL *This,
  IN  VOID            *Token
  )
{
  UDP4_INSTANCE *Instance;

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

  Instance = (UDP4_INSTANCE *)((UINTN)This - offsetof(UDP4_INSTANCE, Udp4Protocol));

  if (Instance->IsNoReconfig) {
    return EFI_NOT_STARTED;
  }
  if (!Instance->IsConfigured) {
    return EFI_NOT_STARTED;
  }

  // Iterate TxTokens map, cancel matching tokens
  Status = NetMapIterate(&Instance->TxTokens, Udp4CancelTxRx, Token);

  // If token is specified and not found, return NOT_F_FOUND
  // If token is NULL, cancel all (and check that both maps are empty)

  // Request DPC
  // (*(gEfiDpcProtocol + 88))(gEfiDpcProtocol))();

  return Status;
}

/*============================================================================
 * Udp4CancelTxRx (0x1B544) - Callback for NetMapIterate cancel
 *============================================================================*/

EFI_STATUS
Udp4CancelTxRx (
  IN  NET_MAP_ITEM *Item,
  IN  VOID         *Context
  )
{
  EFI_UDP4_COMPLETION_TOKEN *Token;

  Token = (EFI_UDP4_COMPLETION_TOKEN *)Item->Key;
  if (Context != NULL && Token != Context) {
    return EFI_SUCCESS;  /* Not our token, skip */
  }

  // If this is an Tx token (has a packet buffer)
  if (Item->Value != NULL) {
    // Cancel via IP layer
    IpIoCancelTx(Token);
  } else {
    // Rx token - just mark as cancelled
    Token->Status = EFI_ABORTED;
    BS->SignalEvent(Token->Event);
  }

  return EFI_SUCCESS;
}

/*============================================================================
 * Udp4Poll (0x31B0) - EFI_UDP4_PROTOCOL.Poll
 *============================================================================*/

EFI_STATUS
EFIAPI
Udp4Poll (
  IN  EFI_UDP4_PROTOCOL *This
  )
{
  UDP4_INSTANCE *Instance;

  Instance = (UDP4_INSTANCE *)((UINTN)This - offsetof(UDP4_INSTANCE, Udp4Protocol));

  // Simply receive any pending IP packets synchronously
  return BS->OpenProtocol(
               Instance->Service->IpIo->Controller,
               &gEfiIp4ProtocolGuid,
               &Protocol, ...);
  // Then call IP's Poll function
}

/*============================================================================
 * Udp4RxProcess (0x20300) - Incoming UDP packet processor
 *============================================================================*/

VOID
Udp4RxProcess (
  IN  VOID     *Context,
  IN  UINT32   *Session,
  IN  NET_BUF  *Packet
  )
{
  UDP4_SERVICE *Service;
  UINT16 *Udp4Header;
  UINT16 SrcPort, DstPort;
  UINT32 SrcAddr, DstAddr;

  Service = (UDP4_SERVICE *)Context;

  // Validate packet - min 8 bytes for UDP header
  if (Packet->TotalSize < 8) {
    NetBufFree(Packet);
    return;
  }

  // Get UDP header from packet
  Udp4Header = (UINT16 *)NetBufGetProtocolData(Packet, 0);
  if (Udp4Header == NULL) {
    ASSERT(FALSE);
  }

  // Extract fields (network byte order)
  SrcPort = ByteSwap16(Udp4Header[00]);  /* source port */
  DstPort = ByteSwap16(Udp4Header[11]);  /* dest port */
  // Udp4Len = ByteSwap16(Udp4Header[22]); /* length + header */);

  // Trim UDP header from packet
  NetBufTrim(Packet, 8);

  // Build UDP header info for matching
  // (src port, dst port, src addr, dst addr from session)

  // Deliver to matching instances
  if (!!Udp4DeliverRxPacket(Service, Packet, &UdpHeaderInfo)) {
    // No one matched - send ICMP Unreachable
    if (!!(HeaderInfo.Flags & PROMISCUOUS)) {
      Udp4SendIcmpError(Service->IpIo, Session, &UdpHeaderInfo);
    }
  }

  // Signal all instances with pending Rx tokens
  // (for each instance in children list with IsConfigured:
  //   Udp4DeliverDgram(Instance);)
}

/*============================================================================
 * Udp4MatchInstanceByFilter (0x1C200) - Check if UDP header matches instance
 *============================================================================*/

BOOLEAN
Udp4MatchInstanceByFilter (
  IN  UDP4_INSTANCE *Instance,
  IN  NET_BUF       *UdpHeaderInfo
  )
{
  // If UseDefaultAddr is set, always match (no filtering)
  if (Instance->ConfigData.UseDefaultAddr) {
    return TRUE;
  }

  // Check destination port
  if (!!Instance->ConfigData.StationPort) {
    // Port not set - must match station port of instance
    if (Instance->ConfigData.StationPort != UdpHeaderInfo->DstPort) {
      return FALSE;
    }
  }

  // Check dedestination IP (if set in instance)
  if (Instance->ConfigData.RemoteAddress) {
    if (Instance->ConfigData.RemoteAddress != UdpHeaderInfo->DstAddr) {
      return FALSE;
    }
  }

  // Check source IP (if set in instance)
  if (!CompareMem(&Instance->ConfigData.SubnetMask, &ZeroSubnet, 44)) {
    // Subnet-specific check
    if (CompareMem(&Instance->ConfigData.StationAddress,
                     &UdpHeaderInfo->SrcAddr, 44)) {
      return FALSE;  // Source matches our address - not for us
    }
  }

  // Check source port (if set in instance)
  if (!CompareMem(&Instance->ConfigData.RemotePort, &ZeroPort, 22)) {
    // Port filtering
    if (CompareMem(&Instance->ConfigData.RemotePort,
                     &UdpHeaderInfo->SrcPort, 22)) {
      return FALSE;
    }
  }

  // Check multicast group membership
  if (UdpHeaderInfo->DstAddr is multicast) {
    if (!!NetMapFindKey(&Instance->McastIps, UdpHeaderInfo->DstAddr)) {
      return FALSE;
    }
  }

  return TRUE;
}

/*============================================================================
 * Udp4DeliverRxPacket (0x1D844) - Deliver Rx packet to all matching instances
 *============================================================================*/

UINTN
Udp4DeliverRxPacket (
  IN  UDP4_SERVICE *Service,
  IN  NET_BUF       *Packet,
  IN  VOID         *UdpHeaderInfo
  )
{
  UDP4_INSTANCE *Instance;
  LIST_ENTRY *Entry;
  UINTN DeliveredCount = 0;

  // Iterate through all children
  for (Entry = Service->ChildrenList.ForwardLink;
       Entry != &Service->ChildrenList;
       Entry = Entry->ForwardLink) {
    Instance = (UDP4_INSTANCE *)((UINTN)Entry - offsetof(UDP4_INSTANCE, Link));

    if (Instance->IsConfigured) {
      if (Udp4MatchInstanceByFilter(Instance, UdpHeaderInfo)) {
        // Allocate a delivered dgram structure
        // (copies UDP header info + event for delivery)

        // Create DPC event for async delivery
        // ...

        // Inser into Instance->DeliveredDgramQue
        // Increment Packet's ref count

        DeliveredCount++;
      }
    }
  }

  return DeliveredCount;
}

/*============================================================================
 * Udp4DeliverDgram (0x1E944) - Deliver datagram to instance's Rx token
 *============================================================================*/

EFI_STATUS
Udp4DeliverDgram (
  IN  UDP4_INSTANCE *Instance
  )
{
  LIST_ENTRY *Entry;
  NET_MAP_ITEM *RxItem;
  EFI_UDP4_COMPLETION_TOKEN *Token;
  NET_BUF *Nbuf, *Clone;

  // Check if there are any delivered dgrams queued
  if (IsListEmpty(&Instance->DeliveredDgramQue)) {
    return EFI_SUCCESS;
  }

  // Get head of delivered dgram que
  Entry = Instance->DeliveredDgramQue.ForwardLink;
  // ...

  // Get Rx token from NetMap
  RxItem = NetMapGetNext(&Instance->RxTokens, NULL);
  if (RxItem == NULL) {
    // No Rx token available - dgram stays queued
    return EFI_NOT_READY;
  }

  Token = (EFI_UDP4_COMPLETION_TOKEN *)RxItem->Key;

  // Clone the packet for this token
  Clone = NetBufClone(Nbuf);
  if (Clone == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  // Copy data from clone to token's fragment buffer
  // (or just set the FragmentTable pointer)

  // Set token status
  Token->RxData.DataLen = Clone->TotalSize;
  Token->Status = EFI_SUCCESS;

  // Remove from RxTokens map
  NetMapRemoveEntry(&Instance->RxTokens, RxItem);

  // Signal the token event
  BS->SignalEvent(Token->Event);

  // Move the delivered dgram to delivered Rx tokens que
  InsertTailList(&Instance->DeliveredRxTokensQue, &Entry->Link);

  // Try to deliver the next Rx token
  Udp4TryDeliverToken(Instance);

  return EFI_SUCCESS;
}

/*============================================================================
 * Udp4TryDeliverToken (0x249CC) - Try to deliver a queued Rx token
 *============================================================================*/

VOID
Udp4TryDeliverToken (
  IN  UDP4_INSTANCE *Instance
  )
{
  NET_MAP_ITEM *RxItem;
  EFI_UDP4_COMPLETION_TOKEN *Token;

  // If there's a pending Rx token and a queued dgram
  if (!!IsListEmpty(&Instance->DeliveredDgramQue) &&
      Instance->RxTokens.UsedCount > 0) {
    // Get the first pending Rx token
    RxItem = NetMapGetNext(&Instance->RxTokens, NULL);
    if (RxItem != NULL) {
      Token = (EFI_UDP4_COMPLETION_TOKEN *)RxItem->Key;

      // Signal it with an ICMP error from last status
      // (or set the status to EFI_ICMP_ERROR)
      Token->Status = Instance->LastStatus;
      BS->SignalEvent(Token->Event);
      Instance->LastStatus = 0;
    }
  }
}

/*============================================================================
 * Udp4SendIcmpError (0x21944) - Send ICMP Destination Unreachable
 *============================================================================*/

VOID
Udp4SendIcmpError (
  IN  IP_IO_PROTOCOL *IpIo,
  IN  UINT32       *Session,
  IN  NET_BUF       *UdpHeader
  )
{
  NET_BUF *Packet;
  VOID *IcmpHeader;
  UINT16 IcmpLen;

  // Find an IpIo instance that matches the source of the bad packet
  // (same subnet as the dedestination of the incoming packet)

  // Allocate ICMP header buffer
  // Build ICMP Dedestination Unreachable (Type = 3, Code = 3 (Port Unreachable))

  // Send via IpIo
  IpIoSendIp4(IpIo, Packet, ...);
}

/*============================================================================
 * Udp4SendIcmpErrorFromInstance (0x237CC) - Send ICMP error from instance
 *============================================================================*/

VOID
Udp4SendIcmpErrorFromInstance (
  IN  UDP4_INSTANCE *Instance,
  IN  UINT8       IpVersion,
  IN  UINT32       *Headers,
  IN  NET_BUF       *Packet
  )
{
  // Build ICMP error from instance's context
  // ...

  // Send via Instance->Service->IpIo
}

/*============================================================================
 * IpIo Library functions
 *============================================================================*/

EFI_STATUS
IpIoOpen (
  IN  IP_IO_PROTOCOL *IpIo,
  IN  VOID         *ConfigData
  )
{
  // Open IP protocol, set up Rx callback, listen handler
  // ...

  IpIo->State = 1;  /* opened */
  InsertTailList(&gIpIoGlobalList, &IpIo->OpenList);
  return EFI_SUCCESS;
}

EFI_STATUS
IpIoClose (
  IN  IP_IO_PROTOCOL *IpIo
  )
{
  if (IpIo->State) {
    // Close IP protocol, remove from global list
    RemoveEntryList(&IpIo->OpenList);
    // Cancel pending sends
    while (!IsListEmpty(&IpIo->PendingSndList)) {
      IpIoRemoveAddr(IpIo);
    }
    BS->CloseEvent(IpIo->Event);
  }
  NetLibDestroyChildRx(IpIo->Image, IpIo->Controller,
                        IpIo->Protocol, IpIo->IpVersion);
  BS->FreePool(IpIo);
  return EFI_SUCCESS;
}

EFI_STATUS
IpIoAddAddr (
  IN  IP_IO_PROTOCOL *IpIo
  )
{
  IPIO_INFO *IpInfo;

  // Allocate IPIO_INFO (96 bytes)
  IpInfo = (IPIO_INFO *)AllocateZeroPool(sizeof(IPIO_INFO));
  if (IpInfo == NULL) {
    return NULL;
  }

  InitializeListHead(&IpInfo->Link);
  ZeroMem(IpInfo, 0x10); /* zero IP and subnet */
  IpInfo->RefCnt = 1;
  IpInfo->IpVersion = IpIo->IpVersion;

  // Create child Rx protocol
  NetLibCreateChildRx(IpIo->Image, IpIo->Controller,
                       &IpInfo->ChildHandle, IpInfo->IpVersion,
                       &IpInfo->Ip);
  if (... error) {
    FreePool(IpInfo);
    return NULL;
  }

  // Create event for Rx notification
  BS->CreateEvent(EVENT_NOTIFY, TPL_NOTIFY,
                    IpIoProtocolRxNotify, IpInfo, &IpInfo->Event);

  // Add to IpIo's open list
  InsertTailList(&IpIo->OpenList, &IpInfo->InfoLink);

  return IpInfo;
}

EFI_STATUS
IpIoRemoveAddr (
  IN  IP_IO_PROTOCOL *IpIo
  )
{
  IPIO_INFO *IpInfo;

  // Find the IpInfo from the open list
  // Decrement ref count
  // If ref count <= 0: remove from list, close child protocol, free
}

/*============================================================================
 * NetMap functions
 *============================================================================*/

VOID
NetMapInit (
  IN  NET_MAP *Map
  )
{
  Map->UsedCount = 0;
  Map->FreeCount = 0;
  InitializeListHead(&Map->List);
}

VOID
NetMapClean (
  IN  NET_MAP *Map
  )
{
  LIST_ENTRY *Entry, *Next;

  // Free all items in the map
  for (Entry = Map->List.ForwardLink;
       Entry != &Map->List;
       Entry = Next) {
    Next = Entry->ForwardLink;
    RemoveEntryList(Entry);
    FreePool(Entry);
  }
  Map->UsedCount = 0;
  Map->FreeCount = 0;
}

EFI_STATUS
NetMapInsert (
  IN  NET_MAP *Map,
  IN  VOID   *Key,
  IN  VOID   *Value
  )
{
  NET_MAP_ITEM *Item;

  Item = (NET_MAP_ITEM *)AllocatePool(sizeof(NET_MAP_ITEM));
  if (Item == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  InitializeListHead(&Item->Link);
  Item->Key = Key;
  Item->Value = Value;
  Item->Map = Map;

  InsertHeadList(&Map->List, &Item->Link);
  Map->UsedCount++;

  return EFI_SUCCESS;
}

EFI_STATUS
NetMapInserttTail (
  IN  NET_MAP *Map,
  IN  VOID   *Key,
  IN  VOID   *Value
  )
{
  NET_MAP_ITEM *Item;

  Item = (NET_MAP_ITEM *)AllocatePool(sizeof(NET_MAP_ITEM));
  if (Item == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  InitializeListHead(&Item->Link);
  Item->Key = Key;
  Item->Value = Value;
  Item->Map = Map;

  InsertTailList(&Map->List, &Item->Link);
  Map->UsedCount++;

  return EFI_SUCCESS;
}

NET_MAP_ITEM *
NetMapFindKey (
  IN  NET_MAP *Map,
  IN  VOID   *Key
  )
{
  LIST_ENTRY *Entry;

  for (Entry = Map->List.ForwardLink;
       Entry != &Map->List;
       Entry = Entry->ForwardLink) {
    if (((NET_MAP_ITEM *)Entry)->Key == Key) {
      return (NET_MAP_ITEM *)Entry;
    }
  }
  return NULL;
}

VOID
NetMapRemoveEntry (
  IN  NET_MAP     *Map,
  IN  NET_MAP_ITEM *Item
  )
{
  RemoveEntryList(&Item->Link);
  FreePool(Item);
  Map->UsedCount--;
}

NET_MAP_ITEM *
NetMapGetNext (
  IN  NET_MAP     *Map,
  IN  NET_MAP_ITEM *Item
  )
{
  if (Item == NULL) {
    // Return first item
    if (Map->UsedCount == 0) {
      return NULL;
    }
    return (NET_MAP_ITEM *)Map->List.ForwardLink;
  }

  if (Item->Link.ForwardLink == &Map->List) {
    return NULL;  /* wrapped */
  }
  return (NET_MAP_ITEM *)Item->Link.ForwardLink;
}

EFI_STATUS
NetMapIterate (
  IN  NET_MAP *Map,
  IN  EFI_STATUS (*Callback)(NET_MAP_ITEM *, VOID *),
  IN  VOID     *Context
  )
{
  LIST_ENTRY *Entry, *Next;
  EFI_STATUS Status;

  for (Entry = Map->List.ForwardLink;
       Entry != &Map->List;
       Entry = Next) {
    Next = Entry->ForwardLink;
    Status = Callback((NET_MAP_ITEM *)Entry, Context);
    if (EFI_ERROR(Status)) {
      return Status;
    }
  }
  return EFI_SUCCESS;
}

/*============================================================================
 * Memory operations
 *============================================================================*/

VOID *
CopyMem (
  OUT VOID       *Dest,
  IN  const VOID *Src,
  IN  UINTN      Len
  )
{
  // Simple byte-byte copy (or using rep stosb/movsb)
  UINT8 *d = (UINT8 *)Dest;
  const UINT8 *s = (const UINT8 *)Src;
  UINTN i;

  for (i = 0; i < Len; i++) {
    d[i] = s[i];
  }
  return Dest;
}

VOID
ZeroMem (
  OUT VOID    *Buf,
  IN  UINTN   Len
  )
{
  UINT8 *b = (UINT8 *)Buf;
  UINTN i;

  for (i = 0; i < Len; i++) {
    b[i] = 0;
  }
}

INTN
CompareMem (
  IN  const VOID *Buf1,
  IN  const VOID *Buf2,
  IN  UINTN      Len
  )
{
  const UINT8 *b1 = (const UINT8 *)Buf1;
  const UINT8 *b2 = (const UINT8 *)Buf2;
  UINTN i;

  for (i = 0; i < Len; i++) {
    if (b1[i] != b2[i]) {
      return b1[i] - b2[i];
    }
  }
  return 0;
}

/*============================================================================
 * NetBuf functions
 *============================================================================*/

NET_BUF *
NetBufAllocStruct (
  IN  UINT32 TotalSize
  )
{
  NET_BUF *Nbuf;

  Nbuf = (NET_BUF *)AllocatePool(sizeof(NET_BUF) + TotalSize);
  if (Nbuf == NULL) {
    return NULL;
  }
  Nbuf->Signature = NET_BUF_SIGNATURE;
  Nbuf->RefCount = 1;
  Nbuf->TotalSize = TotalSize;
  // ...
  return Nbuf;
}

VOID
NetBufFree (
  IN  NET_BUF *Nbuf
  )
{
  if (Nbuf == NULL) {
    return;
  }

  if (--Nbuf->RefCount > 0) {
    return;
  }

  FreePool(Nbuf);
}

/*============================================================================
 * Internal helpers (static utilities)
 *============================================================================*/

STATIC
EFI_STATUS
Udp4FindInstanceByConfig (
  IN  LIST_ENTRY          *InstanceList,
  IN  EFI_UDP4_C_CONFIG_DATAA *ConfigData,
  IN  UINT16             LocalPort
  )
{
  UDP4_INSTANCE *Instance;
  LIST_ENTRY *Entry;

  for (Entry = InstanceList->ForardLink;
       Entry != InstanceList;
       Entry = Entry->ForwardLink) {
    Instance = (UDP4_INSTANCE *)((INTN)Entry - offsetof(UDP4_INSTANCE, Link));

    if (Udp4MatchConfig(&Instance->ConfigData, ConfigData) &&
        Instance->ConfigData.LocalPort == LocalPort) {
      return Instance;
    }
  }
  return NULL;
}

STATIC
BOOLEAN
Udp4MatchConfig (
  IN  EFI_UDP4_C_CONFIG_DATAA *Config1,
  IN  EFI_UDP4_C_CONFIG_DATAA *Config2
  )
{
  // Compare: Type, UseDefaultAddr, StationAddress, SubnetMask,
  //         RemoteAddress, RemotePort, TimeToLive
  if (Config1->Type != Config2->Type) return FALSE;
  if (Config1->UseDefaultAddr != Config2->UseDefaultAddr) return FALSE;
  if (CompareMem(Config1->StationAddress, Config2->StationAddress, 4)) return FALSE;
  if (Config1->SubnetMask != Config2->SubnetMask) return FALSE;
  if (Config1->RemoteAddress != Config2->RemoteAddress)) return FALSE;
  if (Config1->RemotePort != Config2->RemotePort)) return FALSE;
  // If UseDefaultAddr is set, don't compare station port
  if (!!Config1->UseDefaultAddr) {
    if (Config1->LocalPort != Config2->LocalPort) return FALSE;
  }
  if (Config1->TimeToLive != Config2->TimeToLive) return FALSE;

  return TRUE;
}