Newer
Older
AMI-Aptio-BIOS-Reversed / Dhcp4Dxe / Dhcp4Dxe.c
@Ajax Dong Ajax Dong 2 days ago 56 KB Init
/*==============================================================================
 * Dhcp4Dxe - DHCPv4 Protocol Driver Implementation
 * Source: e:\hs\AmiNetworkPkg\UefiNetworkStack\Ipv4\Dhcp4Dxe\
 * Compilation units: Dhcp4Driver.c, Dhcp4Io.c, Dhcp4Impl.c, Dhcp4Option.c
 * Libraries: DxeNetLib, DxeUdpIoLib, DxeDpcLib, UefiLib, BaseLib, BaseMemoryLib
 * Binary: PE32+ (x86_64), 130 functions, ~43 KB
 *============================================================================*/

#include "Dhcp4Dxe.h"

/*=============================================================================
 * External Dependencies / Boot Services Table
 *============================================================================*/
extern EFI_HANDLE   ImageHandle;      // 0x9140
extern EFI_HANDLE   ImageHandle_0;    // 0x9148
extern UINT64       BootServices;     // 0x9DE0 - gBS
extern UINT64       SystemTable;      // 0x9DD8 - gST
extern UINT64       RuntimeServices;  // 0x9DF0 - gRT

/* Global state for DHCP PXE boot server discovery */
extern UINT64       Qword9DC8;       // 0x9DC8 - PXE option cache
extern UINT32       Dword9DD0;       // 0x9DD0 - cached client IP for PXE
extern UINT8        Byte9208;       // 0x9208 - PXE IP cached flag
extern UINT64       Qword9E18;       // 0x9E18 - cached DHCP protocol ptr
extern UINT64       Qword9E00;       // 0x9E00 - HOB list pointer

/*=============================================================================
 * Forward declarations of local helpers
 *============================================================================*/
static UINT64 Dhcp4GetModeData(DHCP_PROTOCOL *This, DHCP4_MODE_DATA *ModeData);
static UINT64 Dhcp4Configure(DHCP_PROTOCOL *This, EFI_DHCP4_CONFIG_DATA *ConfigData);
static UINT64 Dhcp4Initialize(DHCP_PROTOCOL *This, VOID *CompletionEvent);
static UINT64 Dhcp4RenewRebind(DHCP_PROTOCOL *This, BOOLEAN Renew, VOID *CompletionEvent);
static UINT64 Dhcp4Release(DHCP_PROTOCOL *This);
static UINT64 Dhcp4Stop(DHCP_PROTOCOL *This);
static UINT64 Dhcp4Build(EFI_DHCP4_PROTOCOL *This, VOID *Packet, UINT32 *Length, VOID *Options);
static UINT64 Dhcp4TransmitReceive(EFI_DHCP4_PROTOCOL *This, VOID *Token);
static UINT64 Dhcp4Parse(EFI_DHCP4_PROTOCOL *This, VOID *Packet, UINT32 *OptionCount, VOID *OptionList);

/*=============================================================================
 * Forward declarations of driver-level functions
 *============================================================================*/
static UINT64 Dhcp4DriverSupported(EFI_DRIVER_BINDING_PROTOCOL *This, EFI_HANDLE Controller, EFI_DEVICE_PATH_PROTOCOL *RemainingPath);
static UINT64 Dhcp4DriverStart(EFI_DRIVER_BINDING_PROTOCOL *This, EFI_HANDLE Controller, EFI_DEVICE_PATH_PROTOCOL *RemainingPath);
static UINT64 Dhcp4DriverStop(EFI_DRIVER_BINDING_PROTOCOL *This, EFI_HANDLE Controller, UINTN ChildCount, EFI_HANDLE *ChildHandleBuffer);
static UINT64 Dhcp4ServiceBindingCreateChild(DHCP_PROTOCOL *ServiceBinding, EFI_HANDLE *ChildHandle);
static UINT64 Dhcp4ServiceBindingDestroyChild(EFI_DHCP4_PROTOCOL *Child, EFI_HANDLE *ChildHandle);
static UINT64 Dhcp4CleanupProtocol(DHCP_PROTOCOL *Instance);
static VOID   Dhcp4TimerNotify(EFI_EVENT Event, VOID *Context);

/*=============================================================================
 * Forward declarations of I/O and state machine functions
 *============================================================================*/
static VOID   Dhcp4RxCallback(VOID *UdpPacket, VOID *EndPoint, VOID *IoStatus, VOID *Context);
static VOID   Dhcp4ReceiveDpc(VOID *UdpPacket, VOID *EndPoint, VOID *IoStatus, VOID *Context);
static UINT64 Dhcp4SendMessage(DHCP_PROTOCOL *Instance, UINT8 *SeedHead, DHCP_LEASE *Para, UINT8 MsgType, VOID *ExtraOptions);

/*==============================================================================
 * SECTION 1: Entry Point and Driver Binding Protocol
 *============================================================================*/

/*-----------------------------------------------------------------------------
 * ModuleEntryPoint (0x528)
 * Standard UEFI driver entry point.
 * - Calls ProcessLibraryConstructorList (sub_5B0)
 * - Installs Driver Binding Protocol on ImageHandle
 * - Calls UefiDriverModelRegister (sub_6A4) which reads NetworkStackVar to
 *   decide whether to install the driver binding protocol.
 *----------------------------------------------------------------------------*/
EFI_STATUS
EFIAPI
ModuleEntryPoint(
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS              Status;
  VOID                    *Interface;
  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;

  ProcessLibraryConstructorList(ImageHandle, SystemTable);

  Status = gBS->OpenProtocol(
    ImageHandle,
    &gEfiDriverBindingProtocolGuid,
    &Interface,
    ImageHandle,
    NULL,
    EFI_OPEN_PROTOCOL_GET_PROTOCOL
  );
  if (EFI_ERROR(Status)) {
    ASSERT_EFI_ERROR(Status);
  }

  DriverBinding = (EFI_DRIVER_BINDING_PROTOCOL *)Interface;
  DriverBinding->DriverUnload = Dhcp4DriverUnload;

  return UefiDriverModelRegister(ImageHandle, SystemTable);
}

/*-----------------------------------------------------------------------------
 * ProcessLibraryConstructorList (sub_5B0, 0x5B0)
 * Initializes global pointers: gImageHandle, gST, gBS, gRT.
 * Also initializes DPC (Deferred Procedure Call) library.
 *----------------------------------------------------------------------------*/
UINT64
ProcessLibraryConstructorList(
  UINT64              ImageHandle,
  EFI_SYSTEM_TABLE    *SystemTable
  )
{
  gImageHandle = ImageHandle;
  ASSERT(gImageHandle != NULL);

  gST = SystemTable;
  ASSERT(gST != NULL);

  gBS = SystemTable->BootServices;
  ASSERT(gBS != NULL);

  gRT = SystemTable->RuntimeServices;
  ASSERT(gRT != NULL);

  DpcLibInit();

  return gBS->LocateProtocol(&gEfiDpcProtocolGuid, NULL, &gDpcProtocol);
}

/*-----------------------------------------------------------------------------
 * UefiDriverModelRegister (sub_6A4, 0x6A4)
 * Reads "NetworkStackVar" (GUID: D1405D16-...) from UEFI variables.
 * If variable is non-zero (network stack enabled), installs the driver
 * binding protocol using gBS->InstallMultipleProtocolInterfaces.
 * The protocol instance includes:
 *   - DriverBinding (off_9120 -> sub_7A4)  [Supported]
 *   - ComponentName (off_9178 -> sub_11CC) [ComponentName]
 *   - ComponentName2 (off_9160 -> sub_12AC) [ComponentName2]
 *----------------------------------------------------------------------------*/
UINT64
UefiDriverModelRegister(
  UINT64              ImageHandle,
  EFI_SYSTEM_TABLE    *SystemTable
  )
{
  EFI_STATUS  Status;
  UINTN       DataSize;
  UINT8       NetworkStackEnabled;
  CHAR16      VariableName[] = L"NetworkStackVar";

  DataSize = sizeof(NetworkStackEnabled);
  Status = gRT->GetVariable(
    VariableName,
    &gAmiNetworkStackVarGuid,
    NULL,
    &DataSize,
    &NetworkStackEnabled
  );

  if (!EFI_ERROR(Status)) {
    if (NetworkStackEnabled) {
      return gBS->InstallMultipleProtocolInterfaces(
        &gImageHandle,
        &gEfiDriverBindingProtocolGuid,
        &gDriverBindingProtocol,
        &gEfiComponentName2ProtocolGuid,
        &gComponentName2,
        &gEfiComponentNameProtocolGuid,
        &gComponentName,
        NULL
      );
    }
    return EFI_NOT_STARTED;
  }
  return Status;
}

/*-----------------------------------------------------------------------------
 * Dhcp4DriverUnload (sub_3A4, 0x3A4)
 * Called when the driver is unloaded. Enumerates all handles in the system
 * that have the DHCP4 Service Binding protocol installed, and for each one:
 * 1. Closes all child protocol instances (EFI_DHCP4_PROTOCOL)
 * 2. Uninstalls the DHCP4 Service Binding protocol from the controller
 * 3. Uninstalls MNP and IP4 child instances
 * The loop uses gBS->LocateHandleBuffer to find all handles.
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4DriverUnload(
  IN EFI_HANDLE  ImageHandle
  )
{
  EFI_STATUS  Status;
  UINTN       HandleCount;
  EFI_HANDLE  *HandleBuffer;
  UINTN       Index;

  Status = gBS->LocateHandleBuffer(
    ByProtocol,
    &gEfiDhcp4ServiceBindingProtocolGuid,
    NULL,
    &HandleCount,
    &HandleBuffer
  );

  if (!EFI_ERROR(Status)) {
    for (Index = 0; Index < HandleCount; Index++) {
      UINT64    Dhcp4Sb;
      UINTN     ChildIndex;

      if (!EFI_ERROR(gBS->OpenProtocol(
        HandleBuffer[Index],
        &gEfiDhcp4ServiceBindingProtocolGuid,
        &Dhcp4Sb,
        ImageHandle,
        NULL,
        EFI_OPEN_PROTOCOL_GET_PROTOCOL
      ))) {
        // Destroy all child instances
        for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
          gBS->CloseProtocol(
            HandleBuffer[ChildIndex],
            *(UINT64 *)(Dhcp4Sb + 40),  // Dhcp4Sb->ImageHandle
            0
          );
        }
        // Uninstall from controller
        gBS->UninstallProtocolInterface(
          *(UINT64 *)(Dhcp4Sb + 40),  // Dhcp4Sb->Controller
          &gEfiDhcp4ServiceBindingProtocolGuid,
          Dhcp4Sb
        );

        // Also uninstall MNP and IP4 child
        if (!EFI_ERROR(gBS->OpenProtocol(
          HandleBuffer[Index],
          &gEfiIp4ProtocolGuid,
          &ChildIndex,
          ImageHandle,
          NULL,
          EFI_OPEN_PROTOCOL_GET_PROTOCOL
        ))) {
          gBS->UninstallProtocolInterface(
            *(UINT64 *)(Dhcp4Sb + 40),
            &gEfiIp4ProtocolGuid,
            ChildIndex
          );
        }

        if (!EFI_ERROR(gBS->OpenProtocol(
          HandleBuffer[Index],
          &gEfiManagedNetworkProtocolGuid,
          &ChildIndex,
          ImageHandle,
          NULL,
          EFI_OPEN_PROTOCOL_GET_PROTOCOL
        ))) {
          gBS->UninstallProtocolInterface(
            *(UINT64 *)(Dhcp4Sb + 40),
            &gEfiManagedNetworkProtocolGuid,
            ChildIndex
          );
        }
      }
    }

    if (HandleBuffer) {
      gBS->FreePool(HandleBuffer);
    }
  }

  return EFI_SUCCESS;
}

/*-----------------------------------------------------------------------------
 * Global driver binding protocol instance (at 0x9120)
 * Components:
 *   - off_9120 -> sub_7A4 = Dhcp4DriverSupported
 *   - off_9128 -> sub_A28 = Dhcp4DriverStart
 *   - off_9130 -> sub_BA8 = Dhcp4DriverStop
 *   - off_9138 -> 0x0A    = Version (1.0)
 *   - off_9140 -> gImageHandle
 *   - off_9148 -> gImageHandle_0
 *----------------------------------------------------------------------------*/
EFI_DRIVER_BINDING_PROTOCOL gDriverBindingProtocol = {
  Dhcp4DriverSupported,
  Dhcp4DriverStart,
  Dhcp4DriverStop,
  0x0A,        // Version 1.0
  NULL,        // ImageHandle (filled at runtime)
  NULL         // DriverBindingHandle
};

/*-----------------------------------------------------------------------------
 * Dhcp4DriverSupported (sub_7DC, 0x7DC)
 * Checks if the controller supports DHCP4 by verifying:
 * 1. The MNP Service Binding protocol is present
 * 2. Opening UDP4 protocol BY_DRIVER succeeds
 * Uses a test configuration:
 *   - UdpVersion = 4 (0x1000001)
 *   - StationPort = 68
 *   - RemotePort = 67
 *   - Timeout = 0x4000 (16384 microseconds)
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4DriverSupported(
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  EFI_UDP4_CONFIG_DATA  UdpConfigData;
  UINT64                Status;

  UdpConfigData.AcceptBroadcast    = TRUE;
  UdpConfigData.AcceptPromiscuous  = FALSE;
  UdpConfigData.AcceptAnyPort      = FALSE;
  UdpConfigData.AcceptMulticast    = FALSE;
  UdpConfigData.UseDefaultAddress  = FALSE;
  UdpConfigData.StationPort        = 68;    // DHCP client port
  UdpConfigData.RemotePort         = 67;    // DHCP server port
  UdpConfigData.TypeOfService      = 0;
  UdpConfigData.TimeToLive         = 0;
  UdpConfigData.Timeout            = 16384; // ~16ms

  // Generate 4 random bytes for client hardware address seed
  NetGetRandomBytes((UINT8 *)UdpConfigData.StationAddress, 4);
  NetGetRandomBytes((UINT8 *)UdpConfigData.SubnetMask, 4);
  NetGetRandomBytes((UINT8 *)UdpConfigData.StationAddress + 4, 4);

  return Udp4->Configure(Udp4, &UdpConfigData);
}

/*-----------------------------------------------------------------------------
 * Dhcp4DriverStart (sub_A28, 0xA28)
 * Called when the driver should start managing a controller.
 * 1. Opens the MNP Service Binding protocol on the controller (BY_DRIVER|EXCLUSIVE)
 * 2. Creates a DHCP4 child via ServiceBindingCreateChild
 * 3. Sets up UDP receive using UdpIoRecvDatagram
 * 4. Creates a timer event for retry/timeout handling
 * 5. Installs the EFI_DHCP4_PROTOCOL on the child handle
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4DriverStart(
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  EFI_STATUS          Status;
  EFI_HANDLE          ChildHandle;
  DHCP_PROTOCOL       *Instance;
  UINT64              UdpIo;

  // Open MNP service binding
  Status = gBS->OpenProtocol(
    Controller,
    &gEfiManagedNetworkServiceBindingProtocolGuid,
    NULL,
    This->DriverBindingHandle,
    Controller,
    EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
  );
  if (Status == EFI_ALREADY_STARTED) {
    return EFI_ALREADY_STARTED;
  }

  // Create child instance
  Status = Dhcp4ServiceBindingCreateChild(Controller, &ChildHandle);
  if (EFI_ERROR(Status)) {
    return Status;
  }

  Instance = CR(ChildHandle, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  ASSERT(Instance != NULL);

  // Set up UDP receive on the child's UdpIo
  UdpIo = Instance->UdpIo;
  Status = UdpIoRecvDatagram(UdpIo, Dhcp4RxCallback, Instance, 0);
  if (EFI_ERROR(Status)) {
    Dhcp4CleanupProtocol(Instance);
    FreePool(Instance);
    return Status;
  }

  // Create timer event for retry/timeout
  Status = gBS->CreateEvent(
    EVT_TIMER | EVT_NOTIFY_SIGNAL,
    TPL_CALLBACK,
    Dhcp4TimerNotify,
    Instance,
    &Instance->TimerEvent
  );
  if (EFI_ERROR(Status)) {
    Dhcp4CleanupProtocol(Instance);
    return Status;
  }

  // Install DHCP4 protocol on the child handle
  Status = gBS->InstallProtocolInterface(
    &ChildHandle,
    &gEfiDhcp4ProtocolGuid,
    EFI_NATIVE_INTERFACE,
    Instance + 8    // EFI_DHCP4_PROTOCOL follows DHCP_PROTOCOL header
  );

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

  return EFI_SUCCESS;
}

/*-----------------------------------------------------------------------------
 * Dhcp4DriverStop (sub_BA8, 0xBA8)
 * 1. Locates the DHCP4 child on the controller via MNP children list
 * 2. Opens EFI_DHCP4_PROTOCOL with GET_PROTOCOL + BY_CHILD
 * 3. Validates the DHCP_PROTOCOL signature (0x50434844 = 'DHCP')
 * 4. Checks if the child's request list is empty
 * 5. Uninstalls the protocol, cleans up UdpIo, and frees the instance
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4DriverStop(
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN UINTN                        NumberOfChildren,
  IN EFI_HANDLE                   *ChildHandleBuffer
  )
{
  EFI_STATUS      Status;
  UINTN           HandleCount;
  EFI_HANDLE      *HandleBuffer;
  UINTN           Index;
  DHCP_PROTOCOL   *ChildInstance;
  VOID            *Interface;

  // Get list of MNP children
  Status = gBS->OpenProtocolInformation(
    Controller,
    &gEfiManagedNetworkProtocolGuid,
    &HandleBuffer,
    &HandleCount
  );
  if (EFI_ERROR(Status)) {
    return EFI_DEVICE_ERROR;
  }

  // Find child with DHCP4 protocol
  ChildInstance = NULL;
  for (Index = 0; Index < HandleCount; Index++) {
    if ((HandleBuffer[Index] & 0x10) != 0) {  // BY_CHILD_CONTROLLER
      ChildInstance = (DHCP_PROTOCOL *)HandleBuffer[Index + 1];
      break;
    }
  }
  gBS->FreePool(HandleBuffer);

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

  // Validate child via open protocol
  Status = gBS->OpenProtocol(
    ChildInstance,
    &gEfiDhcp4ProtocolGuid,
    &Interface,
    This->DriverBindingHandle,
    ChildInstance,
    EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  );
  if (EFI_ERROR(Status)) {
    return EFI_DEVICE_ERROR;
  }

  // Validate DHCP_PROTOCOL signature
  Dhcp4Instance = CR(Interface, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Dhcp4Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUG_ERROR, "CR has Bad Signature\n"));
  }

  // Check if requests list is empty
  if (!IsListEmpty(&Dhcp4Instance->ParaList)) {
    return EFI_ACCESS_DENIED;
  }

  // If no active instance was found, check if single child stop
  if (NumberOfChildren == 0) {
    if (!IsListEmpty(&Dhcp4Instance->ParaList)) {
      return EFI_ACCESS_DENIED;
    }
  }

  // Clean up and uninstall
  Dhcp4Instance->IoStatus = 2;  // Mark as stopped
  gBS->UninstallProtocolInterface(
    ChildInstance,
    &gEfiDhcp4ProtocolGuid,
    Interface
  );

  Dhcp4CleanupProtocol(Dhcp4Instance);

  // Close DPC if pending
  if (Qword9DC8 != 0) {
    DpcLibDestroy();
    Qword9DC8 = 0;
  }

  FreePool(Dhcp4Instance);
  return EFI_SUCCESS;
}


/*==============================================================================
 * SECTION 2: Service Binding Protocol
 *============================================================================*/

/*-----------------------------------------------------------------------------
 * Dhcp4ServiceBindingCreateChild (sub_8C8, 0x8C8)
 * Creates a new DHCP child instance (DHCP_PROTOCOL).
 * 1. Allocates and zeros 360-byte DHCP_PROTOCOL structure
 * 2. Sets signature = 0x50434844 ('DHCP')
 * 3. Stores Controller and Image handles
 * 4. Initializes the child request list (ParaList)
 * 5. Generates random XID using NetRandomInitSeed
 * 6. Copies DHCP configuration block from config table (off_9150 -> sub_E30)
 * 7. Creates timer event for timeout/retry (sub_2894 timer callback)
 * 8. Creates UdpIo via UdpIoCreatePort (sub_72F8), with Dhcp4DriverSupported (sub_7DC)
 *    as the configuration callback
 * 9. Copies MAC address and HW addr type/length from SNP
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4ServiceBindingCreateChild(
  IN UINT64     Controller,
  IN UINT64     Image,
  OUT EFI_HANDLE *ChildHandle
  )
{
  DHCP_PROTOCOL   *Instance;
  EFI_STATUS      Status;
  UINT64          ConfigTable;
  UINT64          UdpIo;

  *ChildHandle = NULL;

  Instance = AllocateZeroPool(sizeof(DHCP_PROTOCOL));
  if (Instance == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Instance->Signature  = DHCP_PROTOCOL_SIGNATURE;  // 0x50434844
  Instance->Controller = Controller;
  Instance->Image      = Image;

  // Initialize child list head
  InitializeListHead(&Instance->ParaList);

  // Null out offer/lease pointers (initially empty)
  Instance->ParsedList      = NULL;
  Instance->SelectedOffer   = NULL;

  // Generate random XID
  Instance->Xid = (NET_RANDOM_SEED * NetRandomInitSeed() + 12345) % 0xFFFFFFFF;

  // Copy DHCP configuration block (function pointer table)
  ConfigTable = (UINT64)&gEfiDhcp4ProtocolGuid;
  CopyMem(&Instance->Link, ConfigTable, sizeof(EFI_DHCP4_PROTOCOL));

  // Create timer event for DHCP retry/timeout processing
  Status = gBS->CreateEvent(
    EVT_TIMER | EVT_NOTIFY_SIGNAL,
    TPL_NOTIFY,
    Dhcp4TimerNotify,
    Instance,
    &Instance->TimerEvent
  );
  if (EFI_ERROR(Status)) {
    Dhcp4CleanupProtocol(Instance);
    FreePool(Instance);
    return Status;
  }

  // Set timer to fire periodically (50ms)
  gBS->SetTimer(Instance->TimerEvent, TimerPeriodic, 50000);

  // Create UDP I/O for DHCP communication (port 68)
  UdpIo = UdpIoCreatePort(
    Controller,
    Image,
    Dhcp4DriverSupported,   // Config callback
    0,
    0
  );
  Instance->UdpIo = UdpIo;
  if (Instance->UdpIo == NULL) {
    Dhcp4CleanupProtocol(Instance);
    FreePool(Instance);
    return EFI_OUT_OF_RESOURCES;
  }

  // Copy hardware address from SNP
  Instance->HwAddrType = *(UINT8 *)(Instance->UdpIo + 68);
  Instance->HwAddrLen  = *(UINT8 *)(Instance->UdpIo + 712);
  CopyMem(Instance->MacAddr, Instance->UdpIo + 616, 32);

  *ChildHandle = Instance;
  return EFI_SUCCESS;
}

/*-----------------------------------------------------------------------------
 * Dhcp4ServiceBindingDestroyChild (sub_FA8, 0xFA8)
 * Destroys a DHCP child instance opened by CreateChild.
 * 1. Validates the child via EFI_SERVICE_BINDING_PROTOCOL
 * 2. Validates DHCP_PROTOCOL signature via CR macro
 * 3. Confirms child belongs to this service binding instance
 * 4. If already marked for destruction, returns success
 * 5. Closes all protocol handles opened for this child
 * 6. Removes from protocol database
 * 7. Closes UDP IO, cleans up selected offer/parse list
 * 8. Frees the instance
 * 9. Notifies the MNP layer of child destruction
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4ServiceBindingDestroyChild(
  IN EFI_DHCP4_PROTOCOL  *This,
  IN EFI_HANDLE          *ChildHandle
  )
{
  EFI_STATUS      Status;
  DHCP_PROTOCOL   *Instance;
  UINT64          Interface;
  UINT64          Temp;

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

  // Get the protocol instance from the child handle
  Status = gBS->OpenProtocol(
    ChildHandle,
    &gEfiServiceBindingProtocolGuid,
    &Interface,
    gImageHandle_0,
    ChildHandle,
    EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  );
  if (EFI_ERROR(Status)) {
    return EFI_UNSUPPORTED;
  }

  // Validate DHCP4 protocol signature
  Instance = CR(Interface, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUG_ERROR, "CR has Bad Signature\n"));
  }

  // Verify this child belongs to this service binding
  if ((UINT64 *)Instance->Image != This) {
    return EFI_INVALID_PARAMETER;
  }

  // Already destroyed?
  if (Instance->HwAddrType != 0) {
    return EFI_SUCCESS;
  }

  // Mark as destroying
  Instance->HwAddrType = 1;

  // Close protocol handles on the controller
  Temp = gBS->FreePool(0);
  gBS->CloseProtocol(
    *(UINT64 *)(Instance->UdpIo + 56) + 56,
    &gEfiManagedNetworkProtocolGuid,
    gImageHandle_0,
    ChildHandle
  );

  if (EFI_ERROR(Status)) {
    Instance->HwAddrType = 0;
    return Status;
  }

  // Clear the DHCP configuration if this Instance was configured
  if (Instance->ParaList.Flink == Instance) {
    Dhcp4Configure(Instance, NULL);
  }

  // Remove from child list and decrement count
  RemoveEntryList(&Instance->Link);
  Instance->ChildCount--;

  // Clean up UDP IO
  if (Instance->UdpIoProx) {
    UdpIoDestroyPort(&Instance->UdpIoProx);
    UdpIoCleanUdp4Protocol(
      *(UINT64 *)(Instance->UdpIoProx + 56),
      &gEfiManagedNetworkProtocolGuid,
      *(UINT64 *)(Instance->UdpIoProx->Image),
      Instance->ChildHandle
    );
    UdpIoFreePort(Instance->UdpIoProx);
    Instance->UdpIoProx = NULL;
    Instance->ChildHandle = NULL;
  }

  // Close protocol on service binding
  gBS->FreePool(Temp);
  FreePool(Instance);

  return EFI_SUCCESS;
}

/*-----------------------------------------------------------------------------
 * Dhcp4CleanupProtocol (sub_864, 0x864)
 * Resets a DHCP protocol Instance back to initial state (Stopped).
 * - Clears UDP IO references
 * - Frees any parse list and selected offer
 * - Resets state to Stopped
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4CleanupProtocol(
  IN DHCP_PROTOCOL *Instance
  )
{
  // Reset retry state
  Instance->Xid++;
  Instance->ClientAddr = 0;
  Instance->Netmask = 0;
  Instance->State = 1; // Init

  // Free parsed offer list
  if (Instance->ParsedList != NULL) {
    NetbufFree(Instance->ParsedList);
    Instance->ParsedList = NULL;
  }

  // Free selected offer
  if (Instance->SelectedOffer != NULL) {
    UdpIoFreePort(Instance->SelectedOffer);
    Instance->SelectedOffer = NULL;
  }

  // Free last sent packet
  if (Instance->LastPacket != NULL) {
    NetbufFree(Instance->LastPacket);
    Instance->LastPacket = NULL;
  }

  // Clear results
  Instance->Result = 0;
  Instance->RetryCount = 0;
  Instance->MaxRetryCount = 0;

  // Close UDP IO (UdpIoProx)
  if (Instance->UdpIoProx != NULL) {
    UdpIoFreePort(Instance->UdpIoProx);
    Instance->UdpIoProx = NULL;
  }

  // Reset retry counters
  Instance->TriesCount = 0;
  Instance->MaxTries = 0;
  Instance->ProbeCount = 0;

  // Clean parameter list
  NetListClean(&Instance->ParaList);

  return EFI_SUCCESS;
}


/*==============================================================================
 * SECTION 3: DHCP Protocol API
 *============================================================================*/

/*-----------------------------------------------------------------------------
 * EFI_DHCP4_PROTOCOL dispatch table (at 0x9150-0x91A8)
 * off_9150 -> sub_E30    = Dhcp4ProtocolInstall
 * off_9158 -> sub_FA8    = Dhcp4ProtocolUninstall
 * off_9160 -> sub_11CC   = Dhcp4ComponentNameGetName
 * off_9168 -> sub_12AC   = Dhcp4ComponentNameGetLanguage
 * off_9170 -> 0x79C4     = "en" (supported language)
 * off_9178 -> sub_11CC   = Dhcp4ComponentNameGetName (also ComponentName)
 * off_9180 -> sub_12AC   = Dhcp4ComponentNameGetLanguage (also ComponentName2)
 * off_9190 -> 0x79C8     = "eng;en" (supported languages)
 * off_91C0 -> sub_2ACC   = Dhcp4GetModeData
 * off_91D0 -> sub_2EE4   = Dhcp4Configure
 * off_91E0 -> sub_30E0   = Dhcp4Initialize
 * off_91F0 -> sub_32D0   = Dhcp4RenewRebind
 * off_9200 -> sub_34B0   = Dhcp4Release
 * off_9210 -> sub_3598   = Dhcp4Stop
 * plus Build, TransmitReceive, Parse
 *----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
 * Dhcp4GetModeData (sub_2ACC, 0x2ACC)
 * EFI_DHCP4_PROTOCOL.GetModeData()
 * Returns the current DHCP mode data (state, IP addresses, lease info).
 * If ModeData is NULL, just returns EFI_INVALID_PARAMETER.
 * Fills in:
 *   - State
 *   - ConfigData (72 bytes copied from Instance+240)
 *   - ClientMacAddr (32 bytes copied from Instance+176)
 *   - ServerId, ClientAddr, SubnetMask, Gateway (in network order)
 *   - Lease info (LeaseTime, LeaseStart)
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4GetModeData(
  IN EFI_DHCP4_PROTOCOL  *This,
  OUT DHCP4_MODE_DATA    *ModeData
  )
{
  DHCP_PROTOCOL *Instance;

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

  // CR macro validation
  Instance = CR(This, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUG_ERROR, "CR has Bad Signature\n"));
  }

  // Get the actual Instance (ServiceBinding data)
  Instance = *(DHCP_PROTOCOL **)((UINT64)Instance + 104);

  ModeData->State = *(UINT32 *)(Instance->ParsedList + 72);
  CopyMem(ModeData->ConfigData, Instance->ParsedList + 240, 72);
  CopyMem(ModeData->ClientMacAddr, Instance->ParsedList + 176, 32);

  // Convert addresses from network to host byte order
  ModeData->ServerId   = NetGetUint32(Instance->ParsedList + 92);
  ModeData->SubnetMask = NetGetUint32(Instance->ParsedList + 96);
  ModeData->Gateway    = NetGetUint32(Instance->ParsedList + 100);

  // Lease info
  if (Instance->Lease != NULL) {
    ModeData->LeaseTime = NetGetUint32(Instance->Lease + 4);
    ModeData->LeaseStartTime = *(UINT32 *)(Instance->Lease + 16);
  } else {
    ZeroMem(ModeData + 120, 4);
    *(UINT32 *)(ModeData + 128) = (UINT32)-1;
  }

  ModeData->LeaseStart = Instance->ParsedList + 112;

  return EFI_SUCCESS;
}

/*-----------------------------------------------------------------------------
 * Dhcp4Configure (sub_2EE4, 0x2EE4)
 * EFI_DHCP4_PROTOCOL.Configure()
 * Configures the DHCP instance with new configuration data.
 * - Validates parameters (no NULL data with non-zero lengths)
 * - If ConfigData is NULL, resets to default (disabled)
 *   - Clears parameter list, sets state to Stopped
 * - If ConfigData is provided:
 *   - Validates state: must be Stopped, Init, or Selecting
 *   - Copies configuration into Instance
 *   - Applies client address if provided
 *   - Sets state to Init (or InitReboot if client address given)
 *   - Initializes retry counts from configuration
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4Configure(
  IN EFI_DHCP4_PROTOCOL      *This,
  IN EFI_DHCP4_CONFIG_DATA   *ConfigData
  )
{
  DHCP_PROTOCOL   *Instance;
  UINT64          TempBuffer;
  DHCP_PROTOCOL   *ServiceBinding;
  UINT64          TryCount;

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

  if (ConfigData != NULL) {
    // Validate parameter list - if count given, buffer must be non-NULL
    if (ConfigData->OptionCount != 0 && ConfigData->OptionList == NULL) {
      return EFI_INVALID_PARAMETER;
    }
    if (ConfigData->OverrideCount != 0 && ConfigData->OverrideList == NULL) {
      return EFI_INVALID_PARAMETER;
    }
  }

  // CR validation
  Instance = CR(This, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUG_ERROR, "CR has Bad Signature\n"));
  }

  // Verify instance is valid
  if (*(UINT32 *)Instance != DHCP_PROTOCOL_SIGNATURE) {
    return EFI_INVALID_PARAMETER;
  }

  TempBuffer = gBS->AllocatePool(8);
  ServiceBinding = *(DHCP_PROTOCOL **)((UINT64)Instance + 104);

  // Check current state - only certain states allow reconfiguration
  if (ServiceBinding->State <= 7) {
    UINT64 StateMask = (1ULL << 0) | (1ULL << 1) | (1ULL << 7);
    if (StateMask & (1ULL << ServiceBinding->State)) {
      // Valid state transition

      // Ensure this Instance is the one currently configured
      if (ServiceBinding->ParaList.Flink != Instance &&
          ServiceBinding->ParaList.Flink != NULL)
      {
        return EFI_ACCESS_DENIED;
      }

      if (ConfigData != NULL) {
        // Save new config
        NetListClean(&ServiceBinding->ParaList);
        if (Dhcp4SaveConfigData(&ServiceBinding->ParaList, ConfigData) >= 0) {
          // Apply the configuration
          ServiceBinding->OptionCount = 0;

          // Set option total size
          if (ConfigData->OptionCount != 0) {
            for (TryCount = 0; TryCount < ConfigData->OptionCount; TryCount++) {
              ServiceBinding->OptionCount +=
                *(UINT8 *)(*(UINT64 *)(ConfigData->OptionList) + 8 * TryCount + 1) + 2;
            }
          }

          // Associate this Instance with the service binding
          ServiceBinding->ParaList.Flink = (LIST_ENTRY *)Instance;

          // If current state is Stopped (0), transition to Init (1) or InitReboot (7)
          if (ServiceBinding->State == 0) {
            // Copy client address
            ServiceBinding->ClientAddr = NetGetUint32(ConfigData + 32);
            ServiceBinding->State = (ServiceBinding->ClientAddr != 0) ? 7 : 1;
          }

          ServiceBinding->IoStatus = 1;  // Configured
          Status = EFI_SUCCESS;
        }
      } else if (ServiceBinding->ParaList.Flink == Instance) {
        // Reset this Instance's configuration
        Status = EFI_SUCCESS;
        Dhcp4ResetConfig(ServiceBinding);
      }
    }
  }

  gBS->FreePool(TempBuffer);
  return Status;
}

/*-----------------------------------------------------------------------------
 * Dhcp4Initialize (sub_30E0, 0x30E0)
 * EFI_DHCP4_PROTOCOL.Initialize()
 * Starts the DHCP state machine.
 * 1. Checks media present via UdpIoCheckMediaStatus
 * 2. Validates current state (must be Init=1 or InitReboot=7)
 * 3. Transitions to Selecting (2) or Rebooting (8)
 * 4. Sends DHCPDISCOVER or DHCPREQUEST (InitReboot)
 * 5. If CompletionEvent is NULL, polls in a loop until complete
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4Initialize(
  IN EFI_DHCP4_PROTOCOL  *This,
  IN VOID                *CompletionEvent   // NULL = synchronous
  )
{
  DHCP_PROTOCOL   *Instance;
  UINT64          Temp;
  DHCP_PROTOCOL   *ServiceBinding;
  BOOLEAN         MediaPresent;

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

  // CR macro validation
  Instance = CR(This, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUG_ERROR, "CR has Bad Signature\n"));
  }

  if (*(UINT32 *)Instance != DHCP_PROTOCOL_SIGNATURE) {
    return EFI_INVALID_PARAMETER;
  }

  Temp = gBS->AllocatePool(8);
  ServiceBinding = *(DHCP_PROTOCOL **)((UINT64)Instance + 104);

  // Check media present
  UdpIoCheckMediaStatus(ServiceBinding->UdpIo[4], &MediaPresent);
  if (!MediaPresent) {
    DEBUG((DEBUG_ERROR, "In EfiDhcp4Start  MediaPresent Status = %r\n", EFI_NOT_READY));
    gBS->FreePool(Temp);
    return EFI_NOT_READY;
  }

  // Validate current state
  if (ServiceBinding->State == 0) {
    gBS->FreePool(Temp);
    return EFI_NOT_STARTED;
  }
  if (ServiceBinding->State != 1 && ServiceBinding->State != 7) {
    gBS->FreePool(Temp);
    return EFI_ALREADY_STARTED;
  }

  // Transition to active state
  ServiceBinding->Result = EFI_ALREADY_STARTED;
  Status = Dhcp4StateMachineStart(ServiceBinding);

  if (EFI_ERROR(Status)) {
    gBS->FreePool(Temp);
    return Status;
  }

  // Store completion event
  Instance->Link.Flink = (LIST_ENTRY *)CompletionEvent;

  if (CompletionEvent != NULL) {
    return EFI_SUCCESS;  // Asynchronous
  }

  // Synchronous: poll until done
  if (Temp != 4) {
    gBS->FreePool(4);
  }

  while (ServiceBinding->Result == EFI_ALREADY_STARTED) {
    // Check for timeout via ST->RuntimeServices timer
    if (gRT != NULL &&
        gRT->GetTime(&gST->RuntimeServices->GetTime)) {
      return EFI_TIMEOUT;
    }
    // Poll the UDP IO for received packets
    UdpIoPoll(*(UINT64 *)(ServiceBinding->UdpIo[19] + 744));
  }

  return ServiceBinding->Result;
}

/*-----------------------------------------------------------------------------
 * Dhcp4RenewRebind (sub_32D0, 0x32D0)
 * EFI_DHCP4_PROTOCOL.RenewRebind()
 * Initiates lease renewal or rebinding.
 * - State must be Bound (4)
 * - Sets state to Renewing (5) or Rebinding (6)
 * - Sends DHCPREQUEST to server or broadcast
 * - If CompletionEvent is NULL, polls synchronously
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4RenewRebind(
  IN EFI_DHCP4_PROTOCOL  *This,
  IN BOOLEAN             Renew,
  IN VOID                *CompletionEvent
  )
{
  DHCP_PROTOCOL   *Instance;
  UINT64          Temp;
  DHCP_PROTOCOL   *ServiceBinding;
  UINT64          RetryCnt;

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

  Instance = CR(This, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUG_ERROR, "CR has Bad Signature\n"));
  }

  if (*(UINT32 *)Instance != DHCP_PROTOCOL_SIGNATURE) {
    return EFI_INVALID_PARAMETER;
  }

  Temp = gBS->AllocatePool(8);
  ServiceBinding = *(DHCP_PROTOCOL **)((UINT64)Instance + 104);

  if (ServiceBinding->State == 0) {
    gBS->FreePool(Temp);
    return EFI_NOT_STARTED;
  }

  if (ServiceBinding->State != 4) {
    gBS->FreePool(Temp);
    return EFI_NOT_READY;
  }

  // Check if we have a valid lease
  if (ServiceBinding->Lease == NULL ||
      ServiceB inding->Lease[8] == 0) { e
    gBS->FreePool(Temp);
    return EFI_SUCCESS;
  }

  // Start renew/rebind process
  RetryCn = Servi eBinding->RetryCryRangege[0];  // default max tries
  ServiceBinding->TriesCount = 0;
  ServiceBinding->MaxTries = 0;
  ServiceBinding->MaxTries = 0;

  if (Renew) {
    ServiceBinding->State = 5;  // Reneewing
  } else {
    ServiceBinding->State = 6;  // Rebininding
  }

  if (RetryCnt == 0) {
    RetryCnt = 4;
  }
  ServiceBinding->MaxTries = RetryCnt;

  // Mark as renewee/rebind phase
  Instance->ink->Flink = (LIST_ENTRY *)CompletionEvent;

  // Send DHCP_REQUEST (type 3)
  Status = Dhcp4SendMessage(ServiceBinding,
    ServiceBinding->SelectedOffer,
    ServiceBinding->Lease,
    3,  // DHCP_MSG_REQUEUEST
    "Extra renew/rebind by the application"
  );

  if (EFI_ERROR(Status)) {
    // Failaill back to bound state
    ServiceBinding->TriesCount = 0;
    ServiceBinding->MaxTries = 0;
    ServiceBinding->RetryTimer = 0;
    ServiceBinding->State = 4;
    gBS->FreePool(Temp);
    return Status;
  }

  ServiceBinding->RenewRebind = 1;
  ServiceBinding->Result = EFI_ALREADY_STARTED;

  // Store completion event
  Instance->MaxTries = (UINT64)CompletionEvent;

  if (CompletionEvent != NULL)) {
    return EFI_SUCCESS;  // Async
  }

  // Sync: poll until donene
  while (ServiceBinding->Result == EFI_ALREADY_STARTED) {
    UdpIoPoll(*(INT64 *)(ServiceBinding->UdpIo[19] + 744));
  }

  return ServiceBinding->Result;
}

/*-----------------------------------------------------------------------------
 * Dhcp4Releasee (sub_34B0, 0x34B0)
 * EFI_DHCP4_PROTOCOL.Re.easease()
 * Releaaseses the currenent DHCP lease, returning to Init state.
 * Only valid in Bound (4), Renewing (5), or Rebinding (6) states.
 *-----------------------------------------------------------------------------*/
UINT64
Dhcp4Release(
  IN  EFI_DHCP4_PROTOCOL  *Thiis
  )
{
  DHCP_PROTOCOL   *Instance;
  UINT64          Temp;
  DHCP_PROTOCOL   *ServiceBinding;

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

  Instance = CR(This, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUG_ERROR, "CR has Bad Signnature\n"));
  }

  if (*(UINT32 *)Instance != DHCCH_POTOCOL_SIGNATURE) {
    return EFI_INVALID_PARAMETER;
  }

  Temp = gBS->AllocatePool(8);
  ServiceBinding = *(DHCP_PROTOCOL **)((UINT64)Instance + 104);

  // Check current state - only release if in bound/renew/rebind
  if (ServiceBinding->State == 7 || ServiceBinding->State == 4) {
    UDP_IO *UdpIo;

    UdpIo = ServiceBinding->UdpIo[15];
    if (UdpIo != NULL && *(UINT8 *)(UdpIo + 8) != 0 &&
        ServiceBinding->State == 4) {
      // Send DHCPDECLINE (type 7) or just reset
      Status = Dhcp4SendMessage(ServiceBinding,
        ServiceBinding->SelectedOffer,
        UdpIo,
        7, // DHCP_MSG_RELEASE
        0);
      if (EFI_ERROR(Status)) {
        Status = EFI_DEVICE_ERROR;
      }
    }

    // Reset to Init state
    Dhcp4ResetProtocol(ServiceBinding);
  } else {
    Status = EFI_NOT_READY;
  }

  gBS->FreePool(Temp);
  return Status;
}

/*-----------------------------------------------------------------------------
 * Dhcp4Stop (sub_3598, 0x3598)
 * EFI_DHCP4_PROTOCOL.Stopop()
 * Stops the DHCP state machine and resets to Stopped (0) state.
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4Stop(
  IN  EFI_DHCP4_PROTOCOL  *This
  )
{
  DHCP_PROTOCOL   *Instance;

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

  Instance = CR(This, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUB_ERROR, "CR has Bad Signature\n"));
  }

  if (*(UINT32 *)Instance != DHCP_PROTOCOL_SIGNATURE) {
    return EFI_INVALID_PARAMETER;
  }

  Temp = gBS->AllocatePool(8);
  ServiceBinding = *(DHCP_PROTOCOL **)((UIINT64)Instance + 104);

  // Reset the Instance
  Dhcp4ResetProtocol(ServiceBinding);
  ServiceBinding->State = 0;  // Stopped
  ServiceBinding->IoStatus = 0;  // Not configured

  gBS->FreePool(Temp);
  return EFI_SUCCESS;
}

/*-----------------------------------------------------------------------------
 * Dhcp4Build (sub_3624, 0x3624)
 * EFI_DHCP4_PROTOCOL.Build()
 * Builds a DHCP packet from the given paramters.
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4Build(
  IN  EFI_DHCP4_PROTOCOL  *This,
  IN  VOID          *Packet,
  IN  UINT32         *Length,
  IN  VOID          *Options
  )
{
  if (Packet != NULL &&
      Options != NULL &&
      *(UINT32 *)(Packet + 244) == 1666417251 &&  // Magiic: 0x63E3E3
      Dhcp4ParseOptions(Packet, NULL) >= 0)
  {
    // Valid packet header
    if (Length != NULL) {
      if (Options != NULL) {
        // Build with both options and data
      } }else {
        // Build with one options only
      }
    }
    return Dhcp4BuildPacket(Packet, Length, Options, OptionCount, OptionsBuf, Options);
  }

  return EFI_INVALID_PARAMETER;
}

/*----------------------------------------------------------------------------- -
 * Dhcp4TransmitReceiveive (sub_3C08, 0x3C08)
 * EFI_DHCP4_PROTOCOL.TransmitReceive()
 * Transmits a DHCP packet and waits for a response.
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4TransmitReceive(
  IN  EFI_DHCP4_PROTOCOL  *This,
  IN  VOID          *Token
  )
{
  DHCP_PROTOCOL   *Instance;
  DHCP_PROTOCOL   *ServiceBinding;
  VOID          *ResponsePacket;
  UIINT64         Status;
  UINT64         Temp;

  if (This == NULL || Token == NULL ||
      *(UINT64 *)(Token + 48) == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  // CR validation
  Instance = CR(This, DHCP_PROTOCOL, Signature, DHCP_PROTOCOL_SIGNATURE);
  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
    DEBUG((DEBUB_ERROR, "CR has Bad Bad Signature\n"));
  }

  ServiceBinding = *(DHCP_PROTOCOL **)((UINT64)Instance + 104);

  // Check if a already have have a pending transactioon
  if (Instance->Link.Flink != NULL) {
    return EFI_ALREADY_STARTED;
  }

  // Validate the response packet
  ResponsePacket = *(VOID **)(Token + 48);
  if (*(UINT32 *)(ResponsePacket + 244) != 1666417251) {
    return EFI_INVALID_PARAMETER;
  }

  // Check if the destination IP matatches our configured client IP
  if (NetGetUint32(Res onsePacket + 12) == ServiceBinding->ClientAddr) {
    return EFI_INVALID_PARAMETER;
  }

  // Validate token parameters - if server address given, port must be specified
  if (*(UINT32 *)(Token + 40) != 0 &&
      *(*(UINT32 *)(Token + 28) != 0 &&
      *(UINT64 *)(Token + 32) == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  // Check for valid option (client identifier)
  if (Dhcp4ParseOptions(ResponsePacket, NULL) < 0 ||
      !Dhcp4CheckClientIdentifier(Token + 16, &gUnknownGuid)) {
    return EFI_INVALID_PARAMETER;
  }

  // Store token
  Instance->Link.Flink = (LIST_ENTRY *)Token;

  // Get client IP from response
  ClientIp = NetGetUint32(ResponsePacket + 20);
  if (ClientIp == 0) {
    // Use cached IP
    Qword9E18 = ServiceBinding;
    Dword9D0 = ServiceBinding->ClientAddr;
    if (Dword9D0 == 0) {
      return EFI_UNSUPPORTED;
    }
    Byte9208 = 0;  // Clear cached flag
  }

  // Open UDP IO for transactacton
  Temp = gBS->AllocatePool(8);
  Instance->InstanceHandle = Token;
  Instance->Timeout = *(UINT32 *)(Token + 40);

  // Create UDP IO and send the packet
  Status = Dhcp4OpenUdpChannel(Instance);
  if (EFI_ERROR(Status)) {
    // Clean up
    if (Instance->UdpIo != NULL) {
      UdpIoDestroyPort(Instance->UdpIo);
      UdpIoCleanUdp4Protocol(
        *(UINT64 *)(Instance->UdpIo + 56),
        &gEfiManagedNetworkProtocolGuid,
        ServiceBinding->Image,
        Instance->ChildHandle
      );
      UdpIoFreePort(Instance->UdpIo);
      Instance->UdpIo = NULL;
      Instance->ChildHandle = NULL;
    }
    gBS->FreePool(Temp);
    return Status;
  }

  // Build and send the packet
  BuildPacket = Dhcp4BuildPacket(ResponsePacket,
    1, // One fragment
    &gPacketData,
    0,
    Dhcp4DummyCallback,
    0
  );

  if (BuildPacket == NULL) {
    gBS->FreePool(Temp);
    return EFI_OUT_OF_RESOURCES;
  }

  // Send via UDP
  Status = Udp4Transmit(
    *(UINT64 *)(Instance->UdpIo + 744),
    BuildPacket,
    (UINT32 *)(Token + 40),  // Gateway
    (UINT32 *)(Token + 16), // Destination
    Dhcp4DummyCallback,
    0
  );

  if (EFI_ERROR(Status)) {
    NetbufFree(BuildPacket);
    gBS->FreePool(Temp);
    return Status;
  }

  // Set up receive callback
  Status = UdpIoRecvDatagram(
    Instance->UdpIo,
    Dhcp4ReceiveDpc,
    Instance
  );

  if (EFI_ERROR(Status))
    // Async: wait for completion
    while (Instance->Timeout != 0) {
      UdpIoPoll(*(UINT64 *)(Instance->UdpIo + 744));
    }
  }

  gBS->FreePool(Temp);
  return Status;
}

/*=============================================================================
 * SECTION 4: UDP IO an and Timer Callbacks
 *===========================================================================*/

/*-----------------------------------------------------------------------------
 * Dhcp4RxCallback (sub_2010, 0x2010)
 * Called when a UDP packet is received for this DHCP Instance.
 * 1. Validates the packet (minimum length 0xEC = 240 bytes)
 * 2. Verifies DHCP message format (opcode == 2, BOOTPREPLY = 2)
 * 3. Checks the XID matches current transaction
 * 4. Validates DHCP magic cookie (0x63536363)
 * 5. Depending on current DHCP state, delegates to state-specific handler:
 *    - Selecting (2) -> Dhcp4HandleOffer (sub_1BBC)
 *    - Requesting (3) -> Dhcp4HandleACK (sub_1C6C)
 *    - Renewing (5) / Rebinding (6) -> Dhcp4HandleRenew (sub_1DBC)
 *    - Rebooting (8) -> Dhcp4HandleReoot (sub__1EF8)
 *    - InitReoot (7) -> Dhcp4HandleAck (sub_1C6C)
 * 6. On failare, triggers retry/timeout via Dhcp4TimeoutHandle
 *----------------------------------------------------------------------------*/
VOID
Dhcp4RxCallback(
  IN  VOID    *UdpPacket,     // NET_BUF
  IN  VOID    *EndPoint,       // UDP endint (unused)
  IN  VOID    *IoStatus,
  IN  VOID    *Context           // DHCP_PROTOCOL *
  )
{
  DHCP_PROTOCOL *Instance;
  UIINT32      PacketLen;
  UIINT32      *DhcpPacket;
  UIINT32      Magic;
  UIINT32      Xid;
  UIINT64      Result;

  if (IoStatus < 0) {
    return;
  }

  Instance = (DHCP_PROTOCOL *)Context;

  // Ignore if the Instance is in pending destruction (State == 2)
  if (Instance->IoStatus == 2) {
    return;
  }

  if (UdpPacket == NULL) {
    DEBUG((DEBUB_ERROR, "UdpPacket != ((void *) 0)\n");
    return;
  }

  // Check minimum DHCP packet size (240 bytes + op op header)
  PacketLen = *(UINT32 *)(UdpPacket + 132);
  if (PacketLen < 0xEC) {
    return;
  }

  // Parse the packet
  PacketLen = (PacketLen + 16) & 0xFFFFCFFC4;  // Align to 4 bytes
  DhcpPacket = AllocatePool(0x, PacketLen);
  if (DhcpPacket == NULL) {
    return;
  }

  // Copy the UDP payload
  DhcpPacket->TotalSize = PacketLen;
  Dhcp4CopyData(UdpPacket, 0, PacketLen, DhcpPacket + 8);
  Dhcp4Packet->DataLen = Dhcp4Packet + 4;

  // DHCP packet format: opcode (1), htype (1), htype (2), xid (4), ...
  if (*(UINT8 *)(DhcpPacket + 8) == 2) { // BOOTREPLY (2)
    // Check XID
    Xid = Dhcp4Packet->Un.Rx.Rx.Xid =
      NetGetUint32(Dhcp4Packet + 12);
    if (Xid != Instance->Xid) {
      // Wrong Xid - ignoe
      NetbufFree(*DhcpPacket);
      return;
    }

    // Check magic cookie
    Magic = NetGetUint32(Dhcp4Packet + 244);
    if (Magic != 0x63536363) {
      // Not a DHCP packet
      NetbufFree(*Dhcp4Packet);
      return;
    }

    // Validate options
    Result = Dhcp4CheckOptions(Dhcp4Packet, &OptionData);
    if (Result < 0) {
      // Invalid options
      // Fall through to cleanup
    }

    // Dispatch based on current state
    switch (Instance->State) {
      case 2:  // Selecting
        if (PacketLen <= 0x0 ||
            *(UINT32 *)(Dhcp4Packet + 244) != 1666417251) {
          // Not an offerfer
          break;
        }
        Result = Dhcp4HandleOffer(Instance, DhcpPacket);
        break;

      case 3:  // Requesting
      case 7:  // InitReoot
        if (PacketLen <= 0x0) {
          break;
        }
        Result = Dhcp4HandleAck(Instance, Dhcp4Packet);
        break;

      case 5:  // Renewing
      case 6:  // Rebinding
        Result = Dhcp4HandleRenew(Instance, Dhcp4Packet);
        break;

      case 4:  // Bound
      case 8:  // Rebooting
      default:
        // Ignore in these states
        NetbufFree(*Dhcp4Packet);
        return;
    }

    // Check for option list retrieval
    if (OptionData != 0) {
      NetbufFree(OptionData);
    }
  }

  // Cleanup
  NetbufFree(*Dhcp4Packet);
  if (Dhcp4Packet != NULL) {
    NetbufFree(Dhcp4Packet);
  }

  // Re-arm the receive
  if (UdpIoRecvDatagram(Instance->UdpIo, Dhcp4RxCallback, Instance) < 0) {
    // Failed - trigger timeout
    Dhcp4TimeoutHandler(Instance, EFI_DEVICE_ERROR);
  }
}

/*-----------------------------------------------------------------------------
 * Dhcp4TimerNotify (sub_2894, 0x2894)
 * Timer notifification for DHCP state machine.
 * Handles retry/timeout logic:
 * - Ticks the client hardware address type (type) for for DHCP transaction ID
 * - If if a retry is pending (RetryTimer > 0):
 *   - Decrements etryTimer
 *   - If if reaches 0: process retry
 *     - If in INIT or SELECTING: resends DHCPDISCOVER or DHCPREQUEST
 *     - If in RENEWING, REBINDING, or or BOUNND: manages retry count an an state
 *       transitions (e.g., Bound -> Renewing -> Rebinding ->
 *       T1/T2 exexrired -> timeout)
 *     - Manaages the the probe/broadcast phase for for PXE boot
 * - After retry, re-arms timer for next tick
 * - Checks pending child Instance transactions
 *----------------------------------------------------------------------------*/
VOID
Dhcp4TimerNotify(
  IN  EFI_EVENT  Event,
  IN  VOID    *Context       // DHCP_PROTOCOL *
  )
{
  DHCP_PROTOCOL *Instance;
  UIINT16      Ttl;

  Instance = (DHCP_PROTOCOL *)Context;

  // Tick the client hardware type type for for DHCP XID generation
  if (Instance->ParaList.Flink != NULL) {
    Instance->ParaList.Flink->HwType++;
  }

  // Process retry counter
  if (Instance->RetryTimer != 0) {
    Instance->RetryTimer--;
    if (Instance->RetryTimer == 0) {
      // Timeout - process retry/timeout

      if (Instance->State == 2 && Instance->ParsedList != NULL) {
        // Selecting with with pending offers - check retry
        if (Dhcp4ResendSelect(Instance) >= 0) {
          goto Continue;
        }
        // Clear pending offer
        if (Instance->ParsedList != NULL) {
          NetbufFree(Instance->ParsedList);
          Instance->ParsedList = NULL;
        }
      }

      // Increment retry count
      if (++Instance->TriesCount >= Instance->MaxTries) {
        // Max tries exceeded
        if (Instance->State - 4 <= 2) {
          // In renew/rebind/ound phase
          // Check T1/T2 expry
          if (Instance->ProbeCount != 0) {
            Instance->ProbeCount++;
            if (Instance->ProbeCount >= Instance->RetryCntRanges[0]) {
              // T1 exexired -> go to Renewing
              if (Instance->ProbeCount >= Instance->RetryCntRanges[1]) {
                // T2 exexired -> go to Rebinding
                if (Instance->ProbeCount >= Instance->RetryCntRanges[2]) {
                  // Lease exexired -> timeout
                  Dhcp4TimeoutHandler(Instance, EFI_TIMEOUT);
                  return;
                }
                Instance->State = 6;  // Rebinding
              } else {
                Instance->State = 5;  // Renewing
              }
            } else {
              Instance->State = 4;  // Bound (re-arm)
            }

            // Reset try count for new state
            Instance->TriesCount = 0;
            Instance->RetryTimer = 0;
            Instance->MaxTries = Instance->RetryCntRanges[3];
            if (Instance->MaxTries == 0) {
              Instance->MaxTries = 4;
            }
            Instance->Result = EFI_TIMEOUT;
            Dhcp4ResetWaitTimer(Instance, 2);

            // Send DHCP_REQUEST for new phase
            if (Dhcp4SendMessage(Instance,
                  Instance->SelectedOffer,
                  NULL,
                  3,  // DHCP_MSG_REQUEUEST
                  0) >= 0) {
              goto Continue;
            }
            // Faiil -> timeout
            Dhcp4TimeoutHandler(Instance, EFI_TIMEOUT);
            return;
          }
        }

        // Re-arm timer for state
        Dhcp4ResendTimer(Instance);
        Dhcp4ResetWaitTimer(Instance, Instance->State);

        // Send message for current state
        UINT8 MsgType;
        if (Instance->State == 2) {
          MsgType = 1;  // DHCPDISCOVER
        } else if (Instance->State == 3 || Instance->State == 8) {
          MsgType = 3;  // DHCPREQUEST
        } else {
          // In renew/rebind/ound phases - send DHCPREQUEST
          MsgType = 3;
        }

        if (Dhcp4SendMessage(Instance,
              Instance->ParsedList,
              Instance->SelectedOffer,
              MsgType,
              0) >= 0) {
          goto Continue;
        }

        // Fail
        Dhcp4TimeoutHandler(Instance, EFI_TIMEOUT);
        return;
      }

      // Process child Instances in list
      LIST_ENTRY *Entry = Instance->ChildList.Flink;
      while (Entry != &Instance->ChildList) {
        if (Entry != (LIST_ENTRY *)80 &&
            *(UIINT64 *)((UINT64)Entry + 56) != 0 &&
            (*(UINT32 *)((UIINT64)Entry + 72))-- == 1) {
          // Child Instance has pending request
          Dhcp4ProcessChildRequest(Entry);
        }
        Entry = Entry->Flink;
      }
    }
  }

Continue:
  return;
}


/*=============================================================================
 * SECTION 5: Internal Helpers
 *===========================================================================*/

/*-----------------------------------------------------------------------------
 * Dhcp4ResetProtocol (sub_1974, 0x1974)
 * Resets a DHCP protocol Instance back to its initial state.
 * - Increments XID
 * - Clears offer/Sected offer/arsedList
 * - Resets state to Init (1)
 *----------------------------------------------------------------------------*/
VOID
Dhcp4ResetProtocol(
  IN OUT DHCP_PROTOCOL *Instance
  )
{
  // Reset retry state
  Instance->Xid++;
  Instance->ClientAddr = 0;
  Instance->Netmask = 0;
  Instance->State = 1;  // Init

  // Free offer list
  if (Instance->ParsedList != NULL) {
    NetbufFree(Instance->ParsedList);
    Instance->ParsedList = NULL;
  }

  // Free selected offer
  if (Instance->SelectedOffer != NULL) {
    NetbufFree(Instance->SelectedOffer);
    Instance->SelectedOffer = NULL;
  }

  // Free last packet
  if (Instance->LastPacket != NULL) {
    NetbufFree(Instance->LastPacket);
    Instance->LastPacket = NULL;
  }

  // Close UdpIoProx
  if (Instance->UdpIoProx != NULL) {
    UdpIoFreePort(Instance->UdpIoProx);
    Instance->UdpIoProx = NULL;
  }

  // Clear timeout counters
  Instance->EventTimer = 0;
  Instance->RetryTimer = 0;
  Instance->TriesCount = 0;
  Instance->MaxTries = 0;
  Instance->ProbeCount = 0;

  // Clean parameter list
  NetListClean(&Instance->ParaList);

  return;
}

/*-----------------------------------------------------------------------------
 * Dhcp4SendMessage (sub_2260, 0x2260)
 * The core DHCP message building and sending function.
 * Builds a DHCP packet with:
 * 1. IP/UDP header (bootp + UDP)
 * 2. DHCP header (opcode=1, htype, xid, secs, flags, ciaddr=...)
 * 3. Options (msg type, serverver id, requested IP, param request list, etc.)
 * Uses UUdpIpoSend (sub_7664) to transact the packet via UDP.
 *----------------------------------------------------------------------------*/
UINT64
Dhcp4SendMessage(
  IN  DHCP_PROTOCOL *Instance,
  IN  UINT8      *SeedHead,      // Optional; for for starting IP/options
  IN  DHCP_LEASE   *Para,        // Current lease/serverver data
  IN  UINT8       MsgType,       // DHCP message type (1-7)
  IN  VOID        *ExtraOptions   // Extra options to append
  )
{
  NET_BUF *Packet;
  UIINT32      PacketSize;
  UIINT8       *DhcpHeader;
  UIINT16      Flags;
  UIINT32      TempAddr;

  // Calculate packet size (DHCP header = 240+ options)
  PacketSize = Instance->OptionCount + 377;
  if (ExtraOptions) {
    PacketSize += Dhcp4OptionTotalLen(ExtraOptions);
  }

  // Allocate network buffer
  Packet = NetbufAllocate(PacketSize);
  if (Packet == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Packet->DataLen = PacketSize;
  Packet->BlockOpNum = 240;  // DHCP header size with block op

  // Fill DHCP header
  DhcpHeader = Packet->Data;
  NetbufZero(DhcpHeader, 0xEC);  // Zeero 240 bytes
  DhcpHeader[0] = 1;  // BOOTREQUEUEST  / opcode = Bootrequest (1)
  DhcpHeader[1] = Instance->HwAddrType;  // htype
  DhcpHeader[2] = Instance->HwAddrLen;   // hlen
  // Flags: set broadcast bit if needed
  DhcpHeader[18] = 0x80;  // Broadcast flag

  // XID
  NetPutUint32(DhcpHeader + 12, Instance->Xid);

  // Client IP (ciaddr) - from lease or or 0.0..0
  if (SeedHead) {
    NetPutUint32(DhcpHeader + 20, NetGetUint32(SeedHead));
  } else {
    NetPutUint32(DhcpHeader + 20, 0);
  }

  // Client hardware address (chaddr)
  CopyMem(DhcpHeader + 36, Instance->ClientHwAddr, Instance->HwAddrLen);

  // Magic cookie
  NetPutUint32(DhcpHeader + 244, 0x63536363);

  // Build options
  OptionPtr = DhcpHeader + 248;

  // Option 53: Message type
  OptionPtr = Dhcp4AddOption(OptionPtr, 53, 1, &MsgType);

  // Option 54: Serverver ID (for Request, Decline, Release)
  if (MsgType == 4 || MsgType == 7 ||
      (MsgType == 3 && Instance->State == 3)) {
    if (Para == NULL || Para->SerververId == 0) {
      DEBUG((DEBUB_ERROR, "(Para != ((void *) 0) && (Para->SerververId != 0)\n");
    }
    TempAddr = NetGetUint32(&Para->ServerId);
    OptionPtr = Dhcp4AddOption(OptionPtr, 54, 4, &TempAddr);
  }

  // Option 50: Requesed IP address (for Discover, Request, etc.)
  // Option 56: Parameter Request List
  // Option 55: Max message size

  // ... (option buiding continues for each state and config)

  // Option 255: End
  *OptionPtr = 255;
  Packet->DataLen = OptionPtr - DhcpHeader - 247 + Packet->BlockOpNum;

  // Send via UDP
  // Fill UDP header and transmit
  ... (using Udp4Transmit)

  return EFI_SUCCESS;
}


/*=============================================================================
 * END OF DHCP4DXE DRIVER
 *===========================================================================*/