snpnt32.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,155 行 · 第 1/2 页

C
1,155
字号

Arguments:

  This            - Context pointer.
  HeaderSize      - Optional parameter and is a pointer to the header portion of
                    the data received.
  BuffSize        - Pointer to the length of the Buffer on entry and contains
                    the length of the received data on return
  Buffer          - Pointer to the memory for the received data
  SourceAddr      - Optional parameter, is a pointer to contain the source
                    ethernet address on return
  DestinationAddr - Optional parameter, is a pointer to contain the destination
                    ethernet address on return.
  Protocol        - Optional parameter, is a pointer to contain the Protocol type
                    from the ethernet header on return.

Returns:

  EFI_SUCCESS          - A packet is received and put into the buffer.
  EFI_BUFFER_TOO_SMALL - The provided buffer is too small to receive the packet.
  EFI_NOT_READY        - There is no packet received.

--*/
{
  SNPNT32_INSTANCE_DATA *Instance;
  SNPNT32_GLOBAL_DATA   *GlobalData;
  INT32                 ReturnValue;

  Instance    = SNP_NT32_INSTANCE_DATA_FROM_SNP_THIS (This);

  GlobalData  = Instance->GlobalData;

  ASSERT (GlobalData->NtNetUtilityTable.Receive != NULL);

  if (EFI_ERROR (NET_TRYLOCK (&GlobalData->Lock))) {
    return EFI_ACCESS_DENIED;
  }

  ReturnValue = GlobalData->NtNetUtilityTable.Receive (
                                                Instance->InterfaceInfo.InterfaceIndex,
                                                BuffSize,
                                                Buffer
                                                );

  NET_UNLOCK (&GlobalData->Lock);

  if (ReturnValue < 0) {
    if (ReturnValue == -100) {
      return EFI_BUFFER_TOO_SMALL;
    }

    return EFI_DEVICE_ERROR;
  } else if (ReturnValue == 0) {
    return EFI_NOT_READY;
  }

  if (HeaderSize != NULL) {
    *HeaderSize = 14;
  }

  if (SourceAddr != NULL) {
    NetZeroMem (SourceAddr, sizeof (EFI_MAC_ADDRESS));
    NetCopyMem (SourceAddr, ((UINT8 *) Buffer) + 6, 6);
  }

  if (DestinationAddr != NULL) {
    NetZeroMem (DestinationAddr, sizeof (EFI_MAC_ADDRESS));
    NetCopyMem (DestinationAddr, ((UINT8 *) Buffer), 6);
  }

  if (Protocol != NULL) {
    *Protocol = *((UINT16 *) (((UINT8 *) Buffer) + 12));
  }

  return EFI_SUCCESS;
}

SNPNT32_INSTANCE_DATA gSnpNt32InstanceTemplate = {
  SNP_NT32_INSTANCE_SIGNATURE,            //  Signature
  {
    NULL,
    NULL
  },                                      //  Entry
  NULL,                                   //  GlobalData
  NULL,                                   //  DeviceHandle
  NULL,                                   //  DevicePath
  {                                       //  Snp
    EFI_SIMPLE_NETWORK_PROTOCOL_REVISION, //  Revision
    SnpNt32Start,                       //  Start
    SnpNt32Stop,                        //  Stop
    SnpNt32Initialize,                  //  Initialize
    SnpNt32Reset,                       //  Reset
    SnpNt32Shutdown,                    //  Shutdown
    SnpNt32ReceiveFilters,             //  ReceiveFilters
    SnpNt32StationAddress,             //  StationAddress
    SnpNt32Statistics,                  //  Statistics
    SnpNt32McastIptoMac,             //  MCastIpToMac
    SnpNt32Nvdata,                      //  NvData
    SnpNt32GetStatus,                  //  GetStatus
    SnpNt32Transmit,                    //  Transmit
    SnpNt32Receive,                     //  Receive
    NULL,                                 //  WaitForPacket
    NULL                                  //  Mode
  },
  {                                       //  Mode
    EfiSimpleNetworkInitialized,          //  State
    NET_ETHER_ADDR_LEN,                   //  HwAddressSize
    NET_ETHER_HEADER_SIZE,                //  MediaHeaderSize
    1500,                                 //  MaxPacketSize
    0,                                    //  NvRamSize
    0,                                    //  NvRamAccessSize
    0,                                    //  ReceiveFilterMask
    0,                                    //  ReceiveFilterSetting
    MAX_MCAST_FILTER_CNT,                 //  MaxMCastFilterCount
    0,                                    //  MCastFilterCount
    {
      0
    },                                    //  MCastFilter
    {
      0
    },                                    //  CurrentAddress
    {
      0
    },                                    //  BroadcastAddress
    {
      0
    },                                    //  PermanentAddress
    NET_IFTYPE_ETHERNET,                  //  IfType
    FALSE,                                //  MacAddressChangeable
    FALSE,                                //  MultipleTxSupported
    FALSE,                                //  MediaPresentSupported
    TRUE                                  //  MediaPresent
  },
  {
    0
  }                                       //  InterfaceInfo
};

EFI_STATUS
SnpNt32InitializeGlobalData (
  IN SNPNT32_GLOBAL_DATA *This
  )
/*++

Routine Description:

  Initialize the driver's global data.

Arguments:

  This  - Pointer to the global context data.

Returns:

  EFI_SUCCESS   - The global data is initialized.
  EFI_NOT_FOUND - The required DLL is not found.

--*/
{
  EFI_STATUS            Status;
  CHAR16                *DllFileNameU;
  UINT32                Index;
  INT32                 ReturnValue;
  BOOLEAN               NetUtilityLibInitDone;
  NT_NET_INTERFACE_INFO NetInterfaceInfoBuffer[MAX_INTERFACE_INFO_NUMBER];
  SNPNT32_INSTANCE_DATA *Instance;
  NET_LIST_ENTRY        *Entry;
  UINT32                InterfaceCount;

  ASSERT (This != NULL);

  NetUtilityLibInitDone = FALSE;
  InterfaceCount        = MAX_INTERFACE_INFO_NUMBER;

  NetListInit (&This->InstanceList);
  NET_GLOBAL_LOCK_INIT (&This->Lock);

  //
  //  Get the WinNT thunk
  //
  Status = gBS->LocateProtocol (&gEfiWinNtThunkProtocolGuid, NULL, &This->WinNtThunk);

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

  ASSERT (This->WinNtThunk != NULL);

  DllFileNameU = NETWORK_LIBRARY_NAME_U;

  //
  //  Load network utility library
  //
  This->NetworkLibraryHandle = This->WinNtThunk->LoadLibraryEx (DllFileNameU, NULL, 0);

  if (NULL == This->NetworkLibraryHandle) {
    return EFI_NOT_FOUND;
  }

  This->NtNetUtilityTable.Initialize = (NT_NET_INITIALIZE) This->WinNtThunk->GetProcAddress (
                                                                              This->NetworkLibraryHandle,
                                                                              NETWORK_LIBRARY_INITIALIZE
                                                                              );

  if (NULL == This->NtNetUtilityTable.Initialize) {
    Status = EFI_NOT_FOUND;
    goto ErrorReturn;
  }

  This->NtNetUtilityTable.Finalize = (NT_NET_FINALIZE) This->WinNtThunk->GetProcAddress (
                                                                          This->NetworkLibraryHandle,
                                                                          NETWORK_LIBRARY_FINALIZE
                                                                          );

  if (NULL == This->NtNetUtilityTable.Finalize) {
    Status = EFI_NOT_FOUND;
    goto ErrorReturn;
  }

  This->NtNetUtilityTable.SetReceiveFilter = (NT_NET_SET_RECEIVE_FILTER) This->WinNtThunk->GetProcAddress (
                                                                                            This->NetworkLibraryHandle,
                                                                                            NETWORK_LIBRARY_SET_RCV_FILTER
                                                                                            );

  if (NULL == This->NtNetUtilityTable.SetReceiveFilter) {
    Status = EFI_NOT_FOUND;
    goto ErrorReturn;
  }

  This->NtNetUtilityTable.Receive = (NT_NET_RECEIVE) This->WinNtThunk->GetProcAddress (
                                                                        This->NetworkLibraryHandle,
                                                                        NETWORK_LIBRARY_RECEIVE
                                                                        );

  if (NULL == This->NtNetUtilityTable.Receive) {
    Status = EFI_NOT_FOUND;
    goto ErrorReturn;
  }

  This->NtNetUtilityTable.Transmit = (NT_NET_TRANSMIT) This->WinNtThunk->GetProcAddress (
                                                                          This->NetworkLibraryHandle,
                                                                          NETWORK_LIBRARY_TRANSMIT
                                                                          );

  if (NULL == This->NtNetUtilityTable.Transmit) {
    Status = EFI_NOT_FOUND;
    goto ErrorReturn;
  }
  //
  //  Initialize the network utility library
  //  And enumerate the interfaces in NT32 host
  //
  ReturnValue = This->NtNetUtilityTable.Initialize (&InterfaceCount, &NetInterfaceInfoBuffer[0]);
  if (ReturnValue <= 0) {
    Status = EFI_DEVICE_ERROR;
    goto ErrorReturn;
  }

  NetUtilityLibInitDone = TRUE;

  if (InterfaceCount == 0) {
    Status = EFI_NOT_FOUND;
    goto ErrorReturn;
  }
  //
  //  Create fake SNP instances
  //
  for (Index = 0; Index < InterfaceCount; Index++) {

    Instance = NetAllocatePool (sizeof (SNPNT32_INSTANCE_DATA));

    if (NULL == Instance) {
      Status = EFI_OUT_OF_RESOURCES;
      goto ErrorReturn;
    }
    //
    //  Copy the content from a template
    //
    NetCopyMem (Instance, &gSnpNt32InstanceTemplate, sizeof (SNPNT32_INSTANCE_DATA));

    //
    //  Set the interface information.
    //
    Instance->InterfaceInfo = NetInterfaceInfoBuffer[Index];
    //
    //  Initialize this instance
    //
    Status = This->InitializeInstanceData (This, Instance);
    if (EFI_ERROR (Status)) {

      NetFreePool (Instance);
      goto ErrorReturn;
    }
    //
    //  Insert this instance into the instance list
    //
    NetListInsertTail (&This->InstanceList, &Instance->Entry);
  }

  return EFI_SUCCESS;

ErrorReturn:

  while (!NetListIsEmpty (&This->InstanceList)) {

    Entry     = This->InstanceList.ForwardLink;

    Instance  = NET_LIST_USER_STRUCT_S (Entry, SNPNT32_INSTANCE_DATA, Entry, SNP_NT32_INSTANCE_SIGNATURE);

    NetListRemoveEntry (Entry);

    This->CloseInstance (This, Instance);
    NetFreePool (Instance);
  }

  if (NetUtilityLibInitDone) {

    ASSERT (This->WinNtThunk != NULL);

    if (This->NtNetUtilityTable.Finalize != NULL) {
      This->NtNetUtilityTable.Finalize ();
      This->NtNetUtilityTable.Finalize = NULL;
    }
  }

  return Status;
}

EFI_STATUS
SnpNt32InitializeInstanceData (
  IN SNPNT32_GLOBAL_DATA    *This,
  IN SNPNT32_INSTANCE_DATA  *Instance
  )
/*++

Routine Description:

  Initialize the snpnt32 driver instance.

Arguments:

  This      - Pointer to the SnpNt32 global data.
  Instance  - Pointer to the instance context data.

Returns:

  EFI_SUCCESS - The driver instance is initialized.

--*/
{
  EFI_STATUS    Status;
  EFI_DEV_PATH  Node;

  Instance->GlobalData  = This;
  Instance->Snp.Mode    = &Instance->Mode;
  //
  //  Set broadcast address
  //
  EfiCommonLibSetMem (&Instance->Mode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);

  //
  //  Copy Current/PermanentAddress MAC address
  //
  Instance->Mode.CurrentAddress   = Instance->InterfaceInfo.MacAddr;
  Instance->Mode.PermanentAddress = Instance->InterfaceInfo.MacAddr;

  //
  //  Since the fake SNP is based on a real NIC, to avoid conflict with the host
  //  NIC network stack, we use a different MAC address.
  //  So just change the last byte of the MAC address for the real NIC.
  //
  Instance->Mode.CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++;

  //
  //  Create a fake device path for the instance
  //
  NetZeroMem (&Node, sizeof (Node));

  Node.DevPath.Type     = MESSAGING_DEVICE_PATH;
  Node.DevPath.SubType  = MSG_MAC_ADDR_DP;
  SetDevicePathNodeLength (&Node.DevPath, sizeof (MAC_ADDR_DEVICE_PATH));

  NetCopyMem (
    &Node.MacAddr.MacAddress,
    &Instance->Mode.CurrentAddress,
    sizeof (EFI_MAC_ADDRESS)
    );

  Node.MacAddr.IfType = Instance->Mode.IfType;

  Instance->DevicePath = EfiAppendDevicePathNode (
                          NULL,
                          &Node.DevPath
                          );

  //
  //  Create a fake device handle for the fake SNP
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Instance->DeviceHandle,
                  &gEfiSimpleNetworkProtocolGuid,
                  &Instance->Snp,
                  &gEfiDevicePathProtocolGuid,
                  Instance->DevicePath,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    goto ErrorReturn;
  }

  return EFI_SUCCESS;

ErrorReturn:
  return Status;
}

EFI_STATUS
SnpNt32CloseInstance (
  IN SNPNT32_GLOBAL_DATA    *This,
  IN SNPNT32_INSTANCE_DATA  *Instance
  )
/*++

Routine Description:

  Close the SnpNt32 driver instance.

Arguments:

  This      - Pointer to the SnpNt32 global data.
  Instance  - Pointer to the instance context data.

Returns:

  EFI_SUCCESS - The instance is closed.

--*/
{
  ASSERT (This != NULL);
  ASSERT (Instance != NULL);

  gBS->UninstallMultipleProtocolInterfaces (
        Instance->DeviceHandle,
        &gEfiSimpleNetworkProtocolGuid,
        &Instance->Snp,
        &gEfiDevicePathProtocolGuid,
        Instance->DevicePath,
        NULL
        );

  if (Instance->DevicePath != NULL) {
    gBS->FreePool (Instance->DevicePath);
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
SnpNt32Unload (
  IN EFI_HANDLE  ImageHandle
  )
/*++

Routine Description:

  Unload the SnpNt32 driver.

Arguments:

  ImageHandle - The handle of the driver image.

Returns:

  EFI_SUCCESS - The driver is unloaded.
  other       - Some error occurs.

--*/
{
  EFI_STATUS            Status;
  SNPNT32_GLOBAL_DATA   *This;
  NET_LIST_ENTRY        *Entry;
  SNPNT32_INSTANCE_DATA *Instance;

  This    = &gSnpNt32GlobalData;

  Status  = NetLibDefaultUnload (ImageHandle);

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

  while (!NetListIsEmpty (&This->InstanceList)) {
    //
    //  Walkthrough the interfaces and remove all the SNP instance
    //
    Entry     = This->InstanceList.ForwardLink;

    Instance  = NET_LIST_USER_STRUCT_S (Entry, SNPNT32_INSTANCE_DATA, Entry, SNP_NT32_INSTANCE_SIGNATURE);

    NetListRemoveEntry (Entry);

    This->CloseInstance (This, Instance);
    NetFreePool (Instance);
  }

  if (This->NtNetUtilityTable.Finalize != NULL) {
    This->NtNetUtilityTable.Finalize ();
  }

  This->WinNtThunk->FreeLibrary (This->NetworkLibraryHandle);

  return EFI_SUCCESS;
}

EFI_DRIVER_ENTRY_POINT (InitializeSnpNt32river)

EFI_STATUS
InitializeSnpNt32river (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
/*++

Routine Description:

  Install DriverBinding Protocol for the Win NT Bus driver on the drivers
  image handle.

Arguments:

  ImageHandle - The handle of this image.
  SystemTable - Pointer to the EFI system table.

Returns:

  EFI_SUCEESS -  The protocols are installed and the SnpNt32 is initialized.
  other       -  Some error occurs.

--*/
{
  EFI_STATUS  Status;

  Status = EfiInitializeDriverLib (ImageHandle, SystemTable);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Install the Driver Protocols
  //
  Status = NetLibInstallAllDriverProtocolsWithUnload (
            ImageHandle,
            SystemTable,
            &gSnpNt32DriverBinding,
            ImageHandle,
            &gSnpNt32DriverComponentName,
            NULL,
            NULL,
            SnpNt32Unload
            );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  //  Initialize the global data
  //
  Status = SnpNt32InitializeGlobalData (&gSnpNt32GlobalData);
  if (EFI_ERROR (Status)) {
    SnpNt32Unload (ImageHandle);
  }

  return Status;

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?