bc.c

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

C
2,547
字号
    EfiReleaseLock (&Private->Lock);
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Initialize private BaseCode instance data
  //
  do {
    Private->RandomPort = (UINT16) (Private->RandomPort + PXE_RND_PORT_LOW + Random (Private));
  } while (Private->RandomPort < PXE_RND_PORT_LOW);

  Private->Igmpv1TimeoutEvent = NULL;
  Private->UseIgmpv1Reporting = TRUE;
  Private->IpLength           = IP_ADDRESS_LENGTH (Private->EfiBc.Mode);

  //
  // Initialize Mode structure
  //
  //
  // check for callback protocol and set boolean
  //
  SetMakeCallback (Private);
  Private->EfiBc.Mode->Started              = TRUE;
  Private->EfiBc.Mode->TTL                  = DEFAULT_TTL;
  Private->EfiBc.Mode->ToS                  = DEFAULT_ToS;
  Private->EfiBc.Mode->UsingIpv6            = UseIPv6;
  Private->EfiBc.Mode->DhcpDiscoverValid    = FALSE;
  Private->EfiBc.Mode->DhcpAckReceived      = FALSE;
  Private->EfiBc.Mode->ProxyOfferReceived   = FALSE;
  Private->EfiBc.Mode->PxeDiscoverValid     = FALSE;
  Private->EfiBc.Mode->PxeReplyReceived     = FALSE;
  Private->EfiBc.Mode->PxeBisReplyReceived  = FALSE;
  Private->EfiBc.Mode->IcmpErrorReceived    = FALSE;
  Private->EfiBc.Mode->TftpErrorReceived    = FALSE;
  EfiZeroMem (&Private->EfiBc.Mode->StationIp, sizeof (EFI_IP_ADDRESS));
  EfiZeroMem (&Private->EfiBc.Mode->SubnetMask, sizeof (EFI_IP_ADDRESS));
  Private->EfiBc.Mode->IpFilter.Filters   = 0;
  Private->EfiBc.Mode->IpFilter.IpCnt     = 0;
  Private->EfiBc.Mode->ArpCacheEntries    = 0;
  Private->EfiBc.Mode->RouteTableEntries  = 0;
  EfiZeroMem (&Private->EfiBc.Mode->IcmpError, sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR));
  EfiZeroMem (&Private->EfiBc.Mode->TftpError, sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR));

  //
  // Set to PXE_TRUE by the BC constructor if this BC implementation
  // supports IPv6.
  //
  Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;

#if SUPPORT_IPV6
  Private->EfiBc.Mode->Ipv6Available = Private->NiiPtr->Ipv6Supported;
#else
  Private->EfiBc.Mode->Ipv6Available = FALSE;
#endif
  //
  // Set to TRUE by the BC constructor if this BC implementation
  // supports BIS.
  //
  Private->EfiBc.Mode->BisSupported = TRUE;
  Private->EfiBc.Mode->BisDetected  = PxebcBisDetect (Private);

  //
  // This field is set to PXE_TRUE by the BC Start() function.  When this
  // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
  // addresses.  This can cause unexpected delays in the DHCP(), Discover()
  // and MTFTP() functions.  Setting this to PXE_FALSE will cause these
  // functions to fail if the required IP/MAC information is not in the
  // ARP cache.  The value of this field can be changed by an application
  // at any time.
  //
  Private->EfiBc.Mode->AutoArp = TRUE;

  //
  // Unlock the instance data
  //
  EfiReleaseLock (&Private->Lock);
  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
BcStop (
  IN EFI_PXE_BASE_CODE_PROTOCOL *This
  )
/*++

  Routine Description:
    Stop the BaseCode protocol, Simple Network protocol and UNDI.

  Arguments:
    Private                - Pointer to Pxe BaseCode Protocol

  Returns:

    0                  - Successfully stopped
    !0                 - Failed
--*/
{
  //
  // Lock the instance data
  //
  EFI_PXE_BASE_CODE_MODE      *PxebcMode;
  EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
  EFI_SIMPLE_NETWORK_MODE     *SnpModePtr;
  EFI_STATUS                  StatCode;
  PXE_BASECODE_DEVICE         *Private;

  StatCode = EFI_SUCCESS;

  if (This == NULL) {
    DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);

  if (Private == NULL) {
    DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  EfiAcquireLock (&Private->Lock);

  PxebcMode   = Private->EfiBc.Mode;
  SnpPtr      = Private->SimpleNetwork;
  SnpModePtr  = SnpPtr->Mode;

  //
  // Issue BC command
  //
  StatCode = EFI_NOT_STARTED;

  if (SnpModePtr->State == EfiSimpleNetworkInitialized) {
    StatCode = (*SnpPtr->Shutdown) (SnpPtr);
  }

  if (SnpModePtr->State == EfiSimpleNetworkStarted) {
    StatCode = (*SnpPtr->Stop) (SnpPtr);
  }

  if (Private->TransmitBufferPtr != NULL) {
    gBS->FreePool (Private->TransmitBufferPtr);
    Private->TransmitBufferPtr = NULL;
  }

  if (Private->ReceiveBufferPtr != NULL) {
    gBS->FreePool (Private->ReceiveBufferPtr);
    Private->ReceiveBufferPtr = NULL;
  }

  if (Private->ArpBuffer != NULL) {
    gBS->FreePool (Private->ArpBuffer);
    Private->ArpBuffer = NULL;
  }

  if (Private->TftpErrorBuffer != NULL) {
    gBS->FreePool (Private->TftpErrorBuffer);
    Private->TftpErrorBuffer = NULL;
  }

  if (Private->TftpAckBuffer != NULL) {
    gBS->FreePool (Private->TftpAckBuffer);
    Private->TftpAckBuffer = NULL;
  }

  if (Private->Igmpv1TimeoutEvent != NULL) {
    gBS->CloseEvent (Private->Igmpv1TimeoutEvent);
    Private->Igmpv1TimeoutEvent = NULL;
  }

  Private->FileSize             = 0;
  Private->EfiBc.Mode->Started  = FALSE;

  //
  // Unlock the instance data
  //
  EfiReleaseLock (&Private->Lock);
  return StatCode;
}

const IPV4_ADDR AllSystemsGroup = { 224, 0, 0, 1 };

EFI_STATUS
IpFilter (
  IN PXE_BASECODE_DEVICE          *Private,
  IN EFI_PXE_BASE_CODE_IP_FILTER  *Filter
  )
/*++

  Routine Description:
    Set up the IP filter

  Arguments:
    Private                - Pointer to Pxe BaseCode Protocol
    Filter             - Pointer to the filter

  Returns:

    0                  - Successfully set the filter
    !0                 - Failed
--*/
{
  EFI_STATUS                  StatCode;
  EFI_MAC_ADDRESS             MACadds[PXE_IP_FILTER_SIZE];
  EFI_PXE_BASE_CODE_MODE      *PxebcMode;
  EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
  EFI_SIMPLE_NETWORK_MODE     *SnpModePtr;
  UINT32                      Enable;
  UINT32                      Disable;
  UINTN                       Index;
  UINTN                       Index2;

  PxebcMode   = Private->EfiBc.Mode;
  SnpPtr      = Private->SimpleNetwork;
  SnpModePtr  = SnpPtr->Mode;

  //
  // validate input parameters
  // must have a filter
  // must not have any extra filter bits set
  //
  if (Filter == NULL ||
      (Filter->Filters &~FILTER_BITS)
      //
      // must not have a count which is too large or with no IP list
      //
      ||
      (Filter->IpCnt && (!Filter->IpList || Filter->IpCnt > PXE_IP_FILTER_SIZE))
      //
      // must not have incompatible filters - promiscuous incompatible with anything else
      //
      ||
      (
        (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) &&
      ((Filter->Filters &~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) || Filter->IpCnt)
    )
      ) {
    DEBUG ((EFI_D_INFO, "\nIpFilter()  Exit #1"));
    return EFI_INVALID_PARAMETER;
  }
  //
  // promiscuous multicast incompatible with multicast in IP list
  //
  if (Filter->IpCnt && (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST)) {
    for (Index = 0; Index < Filter->IpCnt; ++Index) {
      if (IS_MULTICAST (&Filter->IpList[Index])) {
        DEBUG ((EFI_D_INFO, "\nIpFilter()  Exit #2"));
        return EFI_INVALID_PARAMETER;
      }
    }
  }
  //
  // leave groups for all those multicast which are no longer enabled
  //
  for (Index = 0; Index < PxebcMode->IpFilter.IpCnt; ++Index) {
    if (!IS_MULTICAST (&PxebcMode->IpFilter.IpList[Index])) {
      continue;
    }

    for (Index2 = 0; Index2 < Filter->IpCnt; ++Index2) {
      if (!EfiCompareMem (&PxebcMode->IpFilter.IpList[Index], &Filter->IpList[Index2], IP_ADDRESS_LENGTH (PxebcMode))) {
        //
        // still enabled
        //
        break;
      }
    }
    //
    // if we didn't find it, remove from group
    //
    if (Index2 == Filter->IpCnt) {
      IgmpLeaveGroup (Private, &PxebcMode->IpFilter.IpList[Index]);
    }
  }
  //
  // set enable bits, convert multicast ip adds, join groups
  // allways leave receive broadcast enabled at hardware layer
  //
  Index2 = 0;

  if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {
    Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
  } else {
    if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) {
      Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
    } else {
      Enable = EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;

      for (Index = 0; Index < Filter->IpCnt; ++Index) {
        PxebcMode->IpFilter.IpList[Index] = Filter->IpList[Index];

        if (IS_MULTICAST (&Filter->IpList[Index])) {
          EFI_IP_ADDRESS  *TmpIp;

          Enable |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;

          //
          // if this is the first group, add the all systems group to mcast list
          //
          if (!Index2)
          {
#if SUPPORT_IPV6
            if (PxebcMode->UsingIpv6) {
              //
              // TBD
              //
            } else
#endif
              TmpIp = (EFI_IP_ADDRESS *) &AllSystemsGroup;
            --Index;
          } else {
            TmpIp = (EFI_IP_ADDRESS *) &Filter->IpList[Index];
          }
          //
          // get MAC address of IP
          //
          StatCode = (*SnpPtr->MCastIpToMac) (SnpPtr, PxebcMode->UsingIpv6, TmpIp, &MACadds[Index2++]);

          if (EFI_ERROR (StatCode)) {
            DEBUG (
              (EFI_D_INFO,
              "\nIpFilter()  Exit #2  %Xh (%r)",
              StatCode,
              StatCode)
              );
            return StatCode;
          }
        } else {
          Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
        }
      }
    }

    if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) {
      Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
    }
  }
  //
  // if nothing changed, just return
  //
  DEBUG (
    (EFI_D_INFO,
    "\nsnp->ReceiveFilterSetting == %Xh  Filter->IpCnt == %Xh",
    SnpModePtr->ReceiveFilterSetting,
    Filter->IpCnt)
    );

  if (SnpModePtr->ReceiveFilterSetting == Enable && !Filter->IpCnt) {
    DEBUG ((EFI_D_INFO, "\nIpFilter()  Exit #4"));
    return EFI_SUCCESS;
  }
  //
  // disable those currently set but not set in new filter
  //
  Disable                   = SnpModePtr->ReceiveFilterSetting &~Enable;

  StatCode                  = SnpPtr->ReceiveFilters (SnpPtr, Enable, Disable, FALSE, Index2, MACadds);

  PxebcMode->IpFilter.IpCnt = Filter->IpCnt;

  //
  // join groups for all multicast in list
  //
  for (Index = 0; Index < Filter->IpCnt; ++Index) {
    if (IS_MULTICAST (&Filter->IpList[Index])) {
      IgmpJoinGroup (Private, &Filter->IpList[Index]);
    }
  }

  DEBUG ((EFI_D_INFO, "\nIpFilter()  Exit #5  %Xh (%r)", StatCode, StatCode));

  return StatCode;
}

EFI_STATUS
EFIAPI
BcIpFilter (
  IN EFI_PXE_BASE_CODE_PROTOCOL  *This,
  IN EFI_PXE_BASE_CODE_IP_FILTER *Filter
  )
/*++

  Routine Description:
    Call the IP filter

  Arguments:
    Private                - Pointer to Pxe BaseCode Protocol
    Filter             - Pointer to the filter

  Returns:

    0                  - Successfully set the filter
    !0                 - Failed
--*/
{
  EFI_STATUS          StatCode;
  PXE_BASECODE_DEVICE *Private;

  //
  // Lock the instance data and make sure started
  //
  StatCode = EFI_SUCCESS;

  if (This == NULL) {
    DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);

  if (Private == NULL) {
    DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  EfiAcquireLock (&Private->Lock);

  if (This->Mode == NULL || !This->Mode->Started) {
    DEBUG ((EFI_D_ERROR, "BC was not started."));
    EfiReleaseLock (&Private->Lock);
    return EFI_NOT_STARTED;
  }

  if (Filter == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Issue BC command
  //
  StatCode = IpFilter (Private, Filter);

  //
  // Unlock the instance data
  //
  EfiReleaseLock (&Private->Lock);
  return StatCode;
}

EFI_STATUS
EFIAPI
BcSetParameters (
  EFI_PXE_BASE_CODE_PROTOCOL  *This,
  BOOLEAN                     *AutoArpPtr,
  BOOLEAN                     *SendGuidPtr,
  UINT8                       *TimeToLivePtr,
  UINT8                       *TypeOfServicePtr,
  BOOLEAN                     *MakeCallbackPtr
  )
/*++

  Routine Description:
    Set the Base Code behavior parameters

  Arguments:
    This               - Pointer to Pxe BaseCode Protocol
    AutoArpPtr           - Boolean to do ARP stuff
    SendGuidPtr          - Boolean whether or not to send GUID info
    TimeToLivePtr               - Value for Total time to live
    TypeOfServicePtr               - Value for Type of Service
    MakeCallbackPtr      - Boolean to determine if we make callbacks

  Returns:

    0                  - Successfully set the parameters
    !0                 - Failed
--*/
{
  EFI_PXE_BASE_CODE_MODE  *PxebcMode;
  EFI_GUID                TmpGuid;
  UINT8                   *SerialNumberPtr;
  EFI_STATUS              StatCode;
  PXE_BASECODE_DEVICE     *Private;

  //
  // Lock the instance data and make sure started
  //
  StatCode = EFI_SUCCESS;

  if (This == NULL) {
    DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);

  if (Private == NULL) {
    DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  EfiAcquireLock (&Private->Lock);

  if (This->Mode == NULL || !This->Mode->Started) {
    DEBUG ((EFI_D_ERROR, "BC was not started."));
    EfiReleaseLock (&Private->Lock);
    return EFI_NOT_STARTED;
  }

  DEBUG ((EFI_D_INFO, "\nSetParameters()  Entry.  "));

  PxebcMode = Private->EfiBc.Mode;
  StatCode  = EFI_SUCCESS;

  if (SendGuidPtr != NULL) {
    if (*SendGuidPtr) {
      if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid, &SerialNumberPtr) != EFI_SUCCESS) {
        return EFI_INVALID_PARAMETER;
      }
    }
  }

⌨️ 快捷键说明

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