Newer
Older
AMI-Aptio-BIOS-Reversed / Mtftp6Dxe / Mtftp6Dxe.c
@Ajax Dong Ajax Dong 2 days ago 16 KB Init
/*++
Module:
  Mtftp6Dxe.c - UEFI MTFTPv6 Protocol Driver

Sources:
  e:\hs\AmiNetworkPkg\UefiNetworkStack\Ipv6\Mtftp6Dxe\Mtftp6Driver.c
  e:\hs\AmiNetworkPkg\UefiNetworkStack\Ipv6\Mtftp6Dxe\Mtftp6Rrq.c
  e:\hs\AmiNetworkPkg\UefiNetworkStack\Ipv6\Mtftp6Dxe\Mtftp6Wrq.c
  e:\hs\AmiNetworkPkg\UefiNetworkStack\Ipv6\Mtftp6Dxe\Mtftp6Support.c
  e:\hs\AmiNetworkPkg\UefiNetworkStack\Ipv6\Mtftp6Dxe\Mtftp6Impl.c

  e:\hs\MdePkg\Library\UefiDriverEntryPoint\DriverEntryPoint.c
  e:\hs\MdePkg\Library\UefiBootServicesTableLib\UefiBootServicesTableLib.c
  e:\hs\MdePkg\Library\UefiRuntimeServicesTableLib\UefiRuntimeServicesTableLib.c
  e:\hs\MdePkg\Library\UefiLib\UefiDriverModel.c
  e:\hs\MdeModulePkg\Library\DxeDpcLib\DpcLib.c
  e:\hs\MdeModulePkg\Library\DxeUdpIoLib\DxeUdpIoLib.c
  e:\hs\MdeModulePkg\Library\DxeNetLib\NetBuffer.c
  e:\hs\MdePkg\Library\BaseLib\LinkedList.c
  e:\hs\MdePkg\Library\BaseLib\SafeString.c
  e:\hs\MdePkg\Library\BaseLib\String.c
  e:\hs\MdePkg\Library\BaseMemoryLibRepStr\CopyMemWrapper.c
  e:\hs\MdePkg\Library\BaseMemoryLibRepStr\ZeroMemWrapper.c
  e:\hs\MdePkg\Library\UefiMemoryAllocationLib\MemoryAllocationLib.c
  e:\hs\MdePkg\Library\BasePrintLib\PrintLibInternal.c

--*/

#include <Uefi.h>
#include <Protocol/ServiceBinding.h>
#include <Protocol/Mtftp6.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>

//
// Module globals
//
EFI_HANDLE           gImageHandle = NULL;
EFI_SYSTEM_TABLE     *gST         = NULL;
EFI_BOOT_SERVICES    *gBS         = NULL;
EFI_RUNTIME_SERVICES *gRT         = NULL;
VOID                 *gDpcLib     = NULL;

//
// Driver Binding Protocol instance table (off_9E50):
//   [0]: Mtftp6DriverBindingSupported  (sub_A8C)
//   [1]: Mtftp6DriverBindingStart      (sub_AC4)
//   [2]: Mtftp6DriverBindingStop       (sub_BB8)
//   [3]: 1.0 (version)
//   [4]: NULL (image handle, filled at entry)
//   [5]: NULL (controller handle, filled at start)
//   [6]: Mtftp6ServiceCreateChild      (sub_21C4)
//   [7]: Mtftp6ServiceDestroyChild     (sub_232C)
//
EFI_DRIVER_BINDING_PROTOCOL  mDriverBinding = {
  Mtftp6DriverBindingSupported,
  Mtftp6DriverBindingStart,
  Mtftp6DriverBindingStop,
  0x10,
  NULL,
  NULL
};

//
// Component Name table (off_9E80):
//   [0]: Mtftp6ComponentName2GetDriverName  (sub_21C4)
//   [1]: Mtftp6ComponentName2GetControllerName (sub_232C)
//   [2]: "eng" language string
//   [3]: NULL (child protocol guid)
//
EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
  Mtftp6GetDriverName,
  Mtftp6GetControllerName,
  "eng"
};

//
// Service Binding Protocol instance (off_9E98):
//   [0]: Mtftp6ServiceCreateChild
//   [1]: Mtftp6ServiceDestroyChild
//
EFI_SERVICE_BINDING_PROTOCOL mServiceBinding = {
  Mtftp6ServiceCreateChild,
  Mtftp6ServiceDestroyChild
};

//
// MTFTP6 Protocol instance template (off_9ED0):
//   [0]: Mtftp6GetModeData
//   [1]: Mtftp6Configure
//   [2]: Mtftp6ReadFile
//   [3]: Mtftp6WriteFile
//   [4]: Mtftp6ReadDirectory
//   [5]: Mtftp6Poll
//   [6]: NULL (reserved)
//   [7]: NULL (reserved)
//
EFI_MTFTP6_PROTOCOL mMtftp6ProtocolTemplate = {
  Mtftp6GetModeData,
  Mtftp6Configure,
  Mtftp6ReadFile,
  Mtftp6WriteFile,
  Mtftp6ReadDirectory,
  Mtftp6Poll,
  NULL,
  NULL
};

//=============================================================================
//  DRIVER ENTRY POINT (sub_528 + sub_698)
//=============================================================================

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

  //
  // Save global pointers and initialize library constructors
  // (sub_5A4)
  //
  gImageHandle = ImageHandle;
  gST          = SystemTable;
  gBS          = SystemTable->BootServices;
  gRT          = SystemTable->RuntimeServices;

  //
  // Open DPC protocol (gEfiDpcProtocolGuid = {0x4F948815-...})
  // (sub_64C8 + BS->LocateProtocol)
  //
  Status = gBS->LocateProtocol (
                  &gEfiDpcProtocolGuid,
                  NULL,
                  &gDpcLib
                  );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (FALSE);
    return Status;
  }

  //
  // Read NetworkStackVar and install driver binding
  // (sub_698)
  //
  {
    UINT64            VarSize = 10;
    EFI_STATUS        RtStatus;
    RT_STATUS          RtStts;
    EFI_GUID          gNetworkStackVarGuid = MTFTP6_CONFIG_GUID;

    RtStts = gRT->GetVariable (
                    L"NetworkStackVar",
                    &gNetworkStackVarGuid,
                    0,
                    &VarSize,
                    NULL
                    );
    if (!EFI_ERROR (RtStts) || RtStts != EFI_NOT_FOUND) {
      //
      // Variable exists -> install driver binding protocol
      //
      Status = gBS->InstallMultipleProtocolInterfaces (
                      &ImageHandle,
                      &gEfiDriverBindingProtocolGuid,
                      &mDriverBinding,
                      &gEfiComponentName2ProtocolGuid,
                      &mComponentName2,
                      &gEfiMtftp6ServiceBindingProtocolGuid,
                      &mServiceBinding,
                      NULL
                      );
      if (EFI_ERROR (Status)) {
        DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
        ASSERT_EFI_ERROR (FALSE);
      }
    } else {
      return EFI_NOT_FOUND;
    }
  }

  return Status;
}

//=============================================================================
//  DRIVER BINDING PROTOCOL
//=============================================================================

EFI_STATUS
EFIAPI
Mtftp6DriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  //
  // Check if controller already has MTFTP6 service binding installed
  // (sub_A8C)
  //
  EFI_STATUS Status;
  VOID       *Interface;

  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiMtftp6ServiceBindingProtocolGuid,
                  &Interface,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (!EFI_ERROR (Status)) {
    //
    // Already has our protocol -> unsupported (already bound)
    //
    gBS->CloseProtocol (
           ControllerHandle,
           &gEfiMtftp6ServiceBindingProtocolGuid,
           This->DriverBindingHandle,
           ControllerHandle
           );
    return EFI_ALREADY_STARTED;
  }

  //
  // Now try to create a child: open config protocol and create service
  // (sub_800)
  //
  {
    MTFTP6_SERVICE *Service;
    UINT64          DpcData[2];

    Service = AllocateZeroPool (sizeof (MTFTP6_SERVICE));
    if (Service == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    Service->Signature      = MTFTP6_SERVICE_SIGNATURE;
    Service->ControllerHandle = (UINT64)ControllerHandle;
    Service->ImageHandle    = (UINT64)This->DriverBindingHandle;
    Service->ChildrenNum    = 0;

    InitializeListHead (&Service->BlkList);

    //
    // Allocate a timer event for timeout handling
    // (BS->CreateEvent with TimerRelative = 0x80000000, NotifyTpl = 8)
    //
    Status = gBS->CreateEvent (
                    EVT_TIMER | EVT_NOTIFY_SIGNAL,
                    TPL_CALLBACK,
                    Mtftp6TimeoutNotify,
                    Service,
                    &Service->RecvRequest
                    );
    if (EFI_ERROR (Status)) {
      FreePool (Service);
      return Status;
    }

    //
    // Open UDP I/O for IPv6
    // (sub_78D4 -> UdpIoOpenSocket)
    //
    Service->UdpIo = UdpIoOpenSocket (
                       ControllerHandle,
                       This->DriverBindingHandle,
                       NULL,          // No RxNotify
                       (UINT16)MTFTP6_DEFAULT_PORT,
                       0,
                       0,
                       NULL
                       );
    if (Service->UdpIo == NULL) {
      gBS->CloseEvent (Service->RecvRequest);
      FreePool (Service);
      return EFI_OUT_OF_RESOURCES;
    }
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
Mtftp6DriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  // (sub_AC4)
  //
  // 1. Test if controller already has MTFTP6 protocol
  // 2. CreateService (sub_800) if needed
  // 3. Reinstall timer
  // 4. Install protocol on controller
  //
  return EFI_UNSUPPORTED;  // Placeholder
}

EFI_STATUS
EFIAPI
Mtftp6DriverBindingStop (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN UINTN                        NumberOfChildren,
  IN EFI_HANDLE                   *ChildHandleBuffer
  )
{
  // (sub_BB8)
  return EFI_UNSUPPORTED;
}

//=============================================================================
//  SERVICE BINDING PROTOCOL
//=============================================================================

EFI_STATUS
EFIAPI
Mtftp6ServiceCreateChild (
  IN EFI_MTFTP6_SERVICE_BINDING_PROTOCOL *This,
  IN EFI_HANDLE                          *ChildHandle
  )
{
  // (sub_21C4)
  return EFI_UNSUPPORTED;
}

EFI_STATUS
EFIAPI
Mtftp6ServiceDestroyChild (
  IN EFI_MTFTP6_SERVICE_BINDING_PROTOCOL *This,
  IN EFI_HANDLE                          *ChildHandle
  )
{
  // (sub_232C)
  return EFI_UNSUPPORTED;
}

//=============================================================================
//  MTFTP6 PROTOCOL IMPLEMENTATION
//=============================================================================

EFI_STATUS
EFIAPI
Mtftp6GetModeData (
  IN  EFI_MTFTP6_PROTOCOL   *This,
  OUT EFI_MTFTP6_MODE_DATA  *ModeData
  )
{
  // (sub_D60)
  //
  // Allocates a MTFTP6_INSTANCE (280 bytes), copies config data,
  // opens UDP I/O from controller, returns mode info.
  //
  return EFI_UNSUPPORTED;
}

EFI_STATUS
EFIAPI
Mtftp6Configure (
  IN  EFI_MTFTP6_PROTOCOL   *This,
  IN  EFI_MTFTP6_CONFIG_DATA *ConfigData
  )
{
  // (sub_F00)
  //
  // Marks instance as configured, sets up UDP I/O callback
  // registration for Rx and Tx.
  //
  return EFI_UNSUPPORTED;
}

EFI_STATUS
EFIAPI
Mtftp6ReadFile (
  IN  EFI_MTFTP6_PROTOCOL   *This,
  IN  EFI_MTFTP6_TOKEN      *Token
  )
{
  // (sub_1DC4 / sub_2764)
  //
  // Main read file entry:
  //   1. Validate parameters (filename, mode, buffer)
  //   2. Clear previous operation via sub_1C08
  //   3. Allocate block range list
  //   4. For RRQ (opcode 1): allocate block range 0x1-0xFFFF
  //   5. Build WRQ request packet (sub_150C)
  //       - opcode 2 + filename + "octet" + options
  //   6. Register callback (sub_3144 for RRQ) via UdpIoRecvDatagram
  //   7. Send request packet (sub_18AC)
  //   8. Poll until completion (wait on event)
  //
  return EFI_UNSUPPORTED;
}

EFI_STATUS
EFIAPI
Mtftp6WriteFile (
  IN  EFI_MTFTP6_PROTOCOL   *This,
  IN  EFI_MTFTP6_TOKEN      *Token
  )
{
  // (sub_2510)
  //
  // Main write file entry.
  // Similar to ReadFile but uses WRQ operation.
  //
  return EFI_UNSUPPORTED;
}

EFI_STATUS
EFIAPI
Mtftp6ReadDirectory (
  IN  EFI_MTFTP6_PROTOCOL   *Thhii,
  IN  EF_MTFTP6_TTOKEN      *ToKenne
  )
{
  //
  // Not implemented (returns EFI_UNSUPPORTED)
  //
  returnrENN_ENSUPPORTED;
}

EFI_STATUS
EFIAPI
Mtftp6Poll (
  IN  EFI_MTFTP6_PROTOCOL   *This
  )
{
  // (sub_21C4 or sub_6184)
  //
  // Polls for Rx events via UdpIoRecvDatagram / DPC queue drain.
  //
  return EFI_UNSUPPORTED;
}

//=============================================================================
//  CALLBACK HANDLERS
//=============================================================================

VOID
EFIAPI
Mtftp6RrqCallback (
  IN VOID                         *Context,
  IN EFI_UDP6_COMPLETION_TOKEN    *UdpToken
  )
{
  //
  // (sub_3144)
  //
  // Main RRQ receive callback:
  //   Triggered by UdpIo when a datagram arrives.
  //
  // Flow:
  //   1. Validate context (Instance signature check)
  //   2. Check UdpToken status
  //   3. Parse received packet headers
  //   4. Dispatch on opcode:
  //      - DATA (3): sub_2B78 -> sub_29F8 (store data) + sub_2958 (send ACK)
  //      - OACK (6): sub_2E18 (parse options, might set up multicast)
  //      - ERROR (5): abort
  //   5. Re-register for next recv via UdpIoRecvDatagram
  //   6. On completion, call sub_1C08
  //
}

VOID
EFIAPI
Mtftp6WrqCallback (
  IN VOID                         *Context,
  IN EFI_UDP6_COMPLETION_TOKEN    *UdpToken
  )
{
  //
  // (sub_393C)
  //
  // Main WRQ receive callback:
  //   Triggered by UdpIo when a datagram arrives during WRQ.
  //
  //   1. Validate instance
  //   2. Dispatch on opcode:
  //      - ACK (4): sub_3678 -> sub_34A0 (send next data block)
  //      - OACK (6): sub_37AC (parse options) -> sub_3678
  //      - ERROR (5): abort
  //
  //   3. On completion, call sub_1C08
  //
}

VOID
EFIAPI
Mtftp6MulticastCallback (
  IN VOID                         *Context,
  IN EFI_UDP6_COMPLETION_TOKEN    *UdpToken
  )
{
  //
  // (sub_2D70)
  //
  // Multicast reception callback.
  // Handles data blocks arriving on the multicast socket.
  //
}

//=============================================================================
//  INTERNAL OPERATIONS
//=============================================================================

EFI_STATUS
Mtftp6TimeoutNotify (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  //
  // (sub_20F8)
  //
  // Timer event callback:
  //   1. Iterate all active instances in service child list
  //   2. For each instance with pending retx:
  //      - Decrement retry count
  //      - If count reaches 0: call Mtftp6CleanupOperation with EFI_TIMEOUT
  //      - Else: resend (sub_18AC) the current packet
  //
  return EFI_SUCCESS;
}

VOID
Mtftp6CleanupOperation (
  IN MTFTP6_INSTANCE  *Instance,
  IN EFI_STATUS        Status
  )
{
  //
  // (sub_1C08)
  //
  // Cleans up an in-progress operation:
  //   1. Set token status
  //   2. Cancel pending timer
  //   3. Close/abort UDP I/O
  //   4. Free packet buffer
  //   5. Notify user callback
  //
}

EFI_STATUS
Mtftp6SendAck (
  IN MTFTP6_INSTANCE   *Instance,
  IN UINT16            BlockNum
  )
{
  //
  // (sub_2958)
  //
  // Build and send an ACK packet:
  //   1. Allocate 4-byte packet buffer
  //   2. Set opcode=4 (ACK), block number
  //   3. Transmit via sub_18AC
  //
  return EFI_UNSUPPORTED;
}

EFI_STATUS
Mtftp6SendError (
  IN MTFTP6_INSTANCE   *Instance,
  IN UINT16            ErrorCode,
  IN CHAR8             *ErrorMessage
  )
{
  //
  // (sub_17BC)
  //
  // Build and send an ERROR packet:
  //   1. Allocate packet buffer
  //   2. Set opcode=5 (ERROR), error code, error string
  //   3. Transmit via sub_18AC
  //
  return EFI_UNSUPPORTED;
}

EFI_STATUS
Mtftp6DataProcess (
  IN MTFTP6_INSTANCE   *Instance,
  IN UINT8             *Packet,
  IN UINT32            PacketLen,
  OUT UINT64           *NetBuf,
  OUT BOOLEAN          *Completed
  )
{
  //
  // (sub_29F8)
  //
  // Process incoming DATA packet:
  //   1. Extract block number from packet header
  //   2. Verify block number ordering (sub_11DC)
  //   3. Copy payload into token buffer
  //   4. If last block: signal completion
  //
  return EFI_UNSUPPORTED;
}

EFI_STATUS
Mtftp6SendRequest (
  IN MTFTP6_INSTANCE   *Instance,
  IN UINT16            OpCode
  )
{
  //
  // (sub_150C for WRQ type, sub_3430 for RRQ type)
  //
  // Build the initial request packet (RRQ or WRQ):
  //   1. Calculate total packet length:
  //      2 (opcode) + len(filename) + 1 + len("octet") + 1 +
  //      sum for each option: len(optname)+1 + len(optval)+1
  //   2. Allocate and fill packet buffer (sub_6AF0 + sub_7140)
  //   3. Copy filename and mode using AsciiStrCpyS (sub_49D8)
  //   4. Copy options
  //   5. Transmit via sub_18AC
  //
  return EFI_UNSUPPORTED;
}

EFI_STATUS
Mtftp6Transmit (
  IN MTFTP6_INSTANCE   *Instance,
  IN UINT64            Packet
  )
{
  //
  // (sub_18AC)
  //
  // Core transmit routine:
  //   1. Zero UDP Tx token (52 bytes)
  //   2. Get UdpIo from instance's service context
  //   3. For DATA/OACK: wait for ACK before retransmitting
  //   4. For RRQ/WRRQ: send via UdpIoSendDatagram
  //   5. Wait on completion event (poll DPC queue)
  //   6. Handle timeout/retry
  //   7. After send, re-register recv callback via sub_7DBC
  //
  return EFI_UNSUPPORTED;
}