pxe_bc_dhcp.c

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

C
2,097
字号
Returns:
  Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == 0
--*/
{
  UINT16  Index;
  CHAR8   *String;

  //
  // Skip over formatted section
  //
  String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length);

  //
  // Look through unformated section
  //
  for (Index = 1; Index <= StringNumber || StringNumber == 0; Index++) {
    if (StringNumber == Index) {
      return String;
    }
    //
    // Skip string
    //
    for (; *String != 0; String++)
      ;
    String++;

    if (*String == 0) {
      //
      // If double NULL then we are done.
      //  Return pointer to next structure in Smbios.
      //  if you pass in a 0 you will always get here
      //
      Smbios->Raw = (UINT8 *)++String;
      return NULL;
    }
  }

  return NULL;
}

EFI_STATUS
PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
  IN  EFI_GUID  *SystemGuid,
  OUT CHAR8     **SystemSerialNumber
  )
/*++

Routine Description:
  This function gets system guid and serial number from the smbios table

Arguments:
  SystemGuid         - The pointer of returned system guid
  SystemSerialNumber - The pointer of returned system serial number

Returns:
  EFI_SUCCESS             - Successfully get the system guid and system serial number
  EFI_NOT_FOUND           - Not find the SMBIOS table
--*/
{
  EFI_STATUS                Status;
  SMBIOS_STRUCTURE_TABLE    *SmbiosTable;
  SMBIOS_STRUCTURE_POINTER  Smbios;
  SMBIOS_STRUCTURE_POINTER  SmbiosEnd;
  UINT16                    Index;

  Status = EfiLibGetSystemConfigurationTable (&gEfiSmbiosTableGuid, &SmbiosTable);

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

  Smbios.Hdr    = (SMBIOS_HEADER *) (UINTN) SmbiosTable->TableAddress;
  SmbiosEnd.Raw = (UINT8 *) (UINTN) (SmbiosTable->TableAddress + SmbiosTable->TableLength);

  for (Index = 0; Index < SmbiosTable->TableLength; Index++) {
    if (Smbios.Hdr->Type == 1) {
      if (Smbios.Hdr->Length < 0x19) {
        //
        // Older version did not support Guid and Serial number
        //
        continue;
      }
      //
      // SMBIOS tables are byte packed so we need to do a byte copy to
      // prevend alignment faults on Itanium-based platform.
      //
      EfiCopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof (EFI_GUID));
      *SystemSerialNumber = PxeBcLibGetSmbiosString (&Smbios, Smbios.Type1->SerialNumber);

      return EFI_SUCCESS;
    }
    //
    // Make Smbios point to the next record
    //
    PxeBcLibGetSmbiosString (&Smbios, 0);

    if (Smbios.Raw >= SmbiosEnd.Raw) {
      //
      // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e.
      // given this we must double check against the lenght of
      // the structure.
      //
      return EFI_SUCCESS;
    }
  }

  return EFI_SUCCESS;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

//
// add router list to list
//
STATIC
VOID
Ip4AddRouterList (
  PXE_BASECODE_DEVICE *Private,
  DHCPV4_OP_IP_LIST   *IpListPtr
  )
{
  EFI_IP_ADDRESS  TmpIp;
  INTN            Index;
  INTN            num;

  if (IpListPtr == NULL) {
    return ;
  }

  for (Index = 0, num = IpListPtr->Header.Length >> 2; Index < num; ++Index) {
    EfiCopyMem (&TmpIp, &IpListPtr->IpList[Index], 4);
    Ip4AddRouter (Private, &TmpIp);
  }
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

//
// send ARP for our IP - fail if someone has it
//
STATIC
BOOLEAN
SetStationIP (
  PXE_BASECODE_DEVICE *Private
  )
{
  EFI_MAC_ADDRESS DestMac;
  EFI_STATUS      EfiStatus;

  EfiZeroMem (&DestMac, sizeof DestMac);

  if (GetHwAddr(Private, (EFI_IP_ADDRESS *)&DHCP_REQ_OPTIONS.OpReqIP.Ip, (EFI_MAC_ADDRESS *)&DestMac)
    || DoArp(Private, (EFI_IP_ADDRESS *)&DHCP_REQ_OPTIONS.OpReqIP.Ip, (EFI_MAC_ADDRESS *)&DestMac) == EFI_SUCCESS) {
    return FALSE;   // somebody else has this IP
  }

  EfiCopyMem (
    (EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->StationIp,
    &DHCP_REQ_OPTIONS.OpReqIP.Ip,
    sizeof (EFI_IPv4_ADDRESS)
    );

  Private->GoodStationIp = TRUE;

  if (!Private->UseIgmpv1Reporting) {
    return TRUE;
  }

  if (Private->Igmpv1TimeoutEvent != NULL) {
    return TRUE;
  }

  EfiStatus = gBS->CreateEvent (
                    EFI_EVENT_TIMER,
                    EFI_TPL_CALLBACK,
                    NULL,
                    NULL,
                    &Private->Igmpv1TimeoutEvent
                    );

  if (EFI_ERROR (EfiStatus)) {
    Private->Igmpv1TimeoutEvent = NULL;
    return TRUE;
  }

  EfiStatus = gBS->SetTimer (
                    Private->Igmpv1TimeoutEvent,
                    TimerRelative,
                    (UINT64) V1ROUTER_PRESENT_TIMEOUT * 10000000
                    );  /* 400 seconds */

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

  return TRUE;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
VOID
AddRouters (
  PXE_BASECODE_DEVICE *Private,
  DHCP_RECEIVE_BUFFER *RxBufPtr
  )
{
  Ip4AddRouterList (
    Private,
    (DHCPV4_OP_IP_LIST *) RxBufPtr->OpAdds.PktOptAdds[OP_ROUTER_LIST_IX - 1]
    );
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
EFI_STATUS
DoUdpWrite (
  PXE_BASECODE_DEVICE         *Private,
  EFI_IP_ADDRESS              *ServerIpPtr,
  EFI_PXE_BASE_CODE_UDP_PORT  *ServerPortPtr,
  EFI_IP_ADDRESS              *ClientIpPtr,
  EFI_PXE_BASE_CODE_UDP_PORT  *ClientPortPtr
  )
{
  UINTN Len;

  Len = sizeof DHCPV4_TRANSMIT_BUFFER;

  return UdpWrite (
          Private,
          EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT,
          ServerIpPtr,
          ServerPortPtr,
          0,
          ClientIpPtr,
          ClientPortPtr,
          0,
          0,
          &Len,
          Private->TransmitBuffer
          );
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

//
// initialize the DHCP structure
//
typedef struct {
  UINT8 x[4];
} C4Str;

STATIC
VOID
InitDhcpv4TxBuf (
  PXE_BASECODE_DEVICE *Private
  )
{
  UINTN                   HwAddrLen;
  UINT8                   *String;
  CHAR8                   *SystemSerialNumber;
  EFI_PXE_BASE_CODE_MODE  *PxebcMode;

  PxebcMode = Private->EfiBc.Mode;

  EfiZeroMem (&DHCPV4_TRANSMIT_BUFFER, sizeof (DHCPV4_STRUCT));
  DHCPV4_TRANSMIT_BUFFER.op     = BOOTP_REQUEST;
  DHCPV4_TRANSMIT_BUFFER.htype  = Private->SimpleNetwork->Mode->IfType;
  DHCPV4_TRANSMIT_BUFFER.flags  = HTONS (DHCP_BROADCAST_FLAG);
  EfiCopyMem (&DHCPV4_OPTIONS_BUFFER, (VOID *) &DHCPOpStart, sizeof (DHCPOpStart));

  //
  // default to hardware address
  //
  HwAddrLen = Private->SimpleNetwork->Mode->HwAddressSize;

  if (HwAddrLen > sizeof DHCPV4_TRANSMIT_BUFFER.chaddr) {
    HwAddrLen = sizeof DHCPV4_TRANSMIT_BUFFER.chaddr;
  }

  String = (UINT8 *) &Private->SimpleNetwork->Mode->CurrentAddress;

  if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
        (EFI_GUID *) DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid,
        &SystemSerialNumber
        ) == EFI_SUCCESS) {
    if (PxebcMode->SendGUID) {
      HwAddrLen = sizeof (EFI_GUID);
      String    = (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid;
    }
  } else {
    //
    // GUID not yet set - send all 0xff's to show programable (via SetVariable)
    // EfiSetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff);
    // GUID not yet set - send all 0's to show not programable
    //
    EfiZeroMem (DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof (EFI_GUID));
  }

  DHCPV4_TRANSMIT_BUFFER.hlen = (UINT8) HwAddrLen;
  EfiCopyMem (DHCPV4_TRANSMIT_BUFFER.chaddr, String, HwAddrLen);

  CvtNum (
    SYS_ARCH,
    (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.ArchitectureType,
    sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.ArchitectureType
    );

  DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.Type                         = Private->NiiPtr->Type;
  DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MajorVersion                 = Private->NiiPtr->MajorVer;
  DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MinorVersion                 = Private->NiiPtr->MinorVer;

  *(C4Str *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.InterfaceName = *(C4Str *) Private->NiiPtr->StringId;

  CvtNum (
    DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MajorVersion,
    (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMajor,
    sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMajor
    );

  CvtNum (
    DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MinorVersion,
    (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMinor,
    sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMinor
    );
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
UINT32
DecodePxeOptions (
  DHCP_RECEIVE_BUFFER *RxBufPtr,
  UINT8               *ptr,
  INTN                Len
  )
{
  UINT8     Op;
  UINT8     *EndPtr;
  INTN      Index;
  UNION_PTR LocalPtr;
  UINT32    status;

  status = 0;

  for (EndPtr = ptr + Len; ptr < EndPtr; ptr += Len + 2) {
    Op  = ptr[0];
    Len = ptr[1];

    switch (Op) {
    case OP_PAD:
      Len = -1;
      break;

    case OP_END:
      return status;

    default:
      LocalPtr.BytePtr = ptr;
      if (Op <= MAX_OUR_PXE_OPT) {
        Index = ourPXEopts[Op - 1];
        if (Index) {
          RxBufPtr->OpAdds.PxeOptAdds[Index - 1] = LocalPtr.OpPtr;
          status |= 1 << Index;
          if (Index == VEND_PXE_BOOT_ITEM && LocalPtr.BootItem->Header.Length == 3) {
            RxBufPtr->OpAdds.Status |= USE_THREE_BYTE;
          }
        }
      }
      break;
    }
  }

  return status;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
VOID
DecodeOptions (
  DHCP_RECEIVE_BUFFER *RxBufPtr,
  UINT8               *ptr,
  INTN                Len
  )
{
  UINT8     Op;
  UINT8     *EndPtr;
  INTN      Index;
  UNION_PTR LocalPtr;

  for (EndPtr = ptr + Len; ptr < EndPtr; ptr += Len + 2) {
    Op  = ptr[0];
    Len = ptr[1];

    switch (Op) {
    case OP_PAD:
      Len = -1;
      break;

    case OP_END:
      return ;

    default:
      LocalPtr.BytePtr = ptr;
      if (Op <= MAX_OUR_OPT) {
        Index = OurDhcpOptions[Op - 1];
        if (Index) {
          RxBufPtr->OpAdds.PktOptAdds[Index - 1] = LocalPtr.OpPtr;
          if (Index == OP_VENDOR_SPECIFIC_IX) {
            UINT32  status;
            status = DecodePxeOptions (
                      RxBufPtr,
                      (UINT8 *) LocalPtr.VendorOptions->VendorOptions,
                      LocalPtr.VendorOptions->Header.Length
                      );
            if (status) {
              RxBufPtr->OpAdds.Status |= PXE_TYPE;
              //
              // check for all the MTFTP info options present - any missing is a nogo
              //
              if ((status & WfM11a_OPTS) == WfM11a_OPTS) {

⌨️ 快捷键说明

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