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 + -
显示快捷键?