pxedhcp4initselect.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 787 行 · 第 1/2 页
C
787 行
&This->Data->Discover,
&offer,
&offer_verify,
seconds_timeout
);
if (EFI_ERROR (EfiStatus)) {
if (Private->offer_list) {
gBS->FreePool (Private->offer_list);
}
Private->offers = 0;
Private->offer_list = NULL;
Private->callback = NULL;
DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));
return EfiStatus;
}
*Offers = Private->offers;
*OfferList = Private->offer_list;
Private->offers = 0;
Private->offer_list = NULL;
Private->callback = NULL;
This->Data->InitCompleted = TRUE;
This->Data->SelectCompleted = FALSE;
This->Data->IsBootp = FALSE;
This->Data->IsAck = FALSE;
return EFI_SUCCESS;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
PxeDhcp4Select (
IN EFI_PXE_DHCP4_PROTOCOL *This,
IN UINTN seconds_timeout,
IN DHCP4_PACKET *Offer
)
{
PXE_DHCP4_PRIVATE_DATA *Private;
EFI_STATUS EfiStatus;
DHCP4_PACKET request;
DHCP4_PACKET acknak;
EFI_IP_ADDRESS bcast_ip;
EFI_IP_ADDRESS zero_ip;
EFI_IP_ADDRESS local_ip;
DHCP4_OP *srvid;
DHCP4_OP *op;
UINT32 dhcp4_magik;
UINT8 buf[16];
BOOLEAN is_bootp;
//
// Verify parameters.
//
if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS || Offer == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Check protocol state.
//
if (This->Data == NULL) {
return EFI_NOT_STARTED;
}
if (!This->Data->SetupCompleted) {
return EFI_NOT_READY;
}
//
// Get pointer to instance data.
//
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Private->PxeBc == NULL) {
return EFI_DEVICE_ERROR;
}
#if 0
if (!is_good_discover (&This->Data->Discover)) {
//
// %%TBD - check discover packet fields
//
}
#endif
//
// Setup useful variables...
//
EfiSetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);
EfiZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS));
EfiZeroMem (&local_ip, sizeof (EFI_IP_ADDRESS));
local_ip.v4.Addr[0] = 127;
local_ip.v4.Addr[3] = 1;
This->Data->SelectCompleted = FALSE;
This->Data->IsBootp = FALSE;
This->Data->IsAck = FALSE;
EfiStatus = gBS->HandleProtocol (
Private->Handle,
&gEfiPxeDhcp4CallbackProtocolGuid,
(VOID *) &Private->callback
);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
}
Private->function = EFI_PXE_DHCP4_FUNCTION_SELECT;
//
// Verify offer packet fields.
//
if (Offer->dhcp4.op != BOOTP_REPLY) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (Offer->dhcp4.htype != This->Data->Discover.dhcp4.htype) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (Offer->dhcp4.hlen != This->Data->Discover.dhcp4.hlen) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (EfiCompareMem (&Offer->dhcp4.xid, &This->Data->Discover.dhcp4.xid, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (!EfiCompareMem (&Offer->dhcp4.yiaddr, &bcast_ip, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (!EfiCompareMem (&Offer->dhcp4.yiaddr, &zero_ip, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (!EfiCompareMem (&Offer->dhcp4.yiaddr, &local_ip, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (EfiCompareMem (
&Offer->dhcp4.chaddr,
&This->Data->Discover.dhcp4.chaddr,
16
)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
//
// DHCP option checks
//
dhcp4_magik = htonl (DHCP4_MAGIK_NUMBER);
is_bootp = TRUE;
if (!EfiCompareMem (&Offer->dhcp4.magik, &dhcp4_magik, 4)) {
//
// If present, DHCP message type must be offer.
//
EfiStatus = find_opt (Offer, DHCP4_MESSAGE_TYPE, 0, &op);
if (!EFI_ERROR (EfiStatus)) {
if (op->len != 1 || op->data[0] != DHCP4_MESSAGE_TYPE_OFFER) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
is_bootp = FALSE;
}
//
// If present, DHCP max message size must be valid.
//
EfiStatus = find_opt (Offer, DHCP4_MAX_MESSAGE_SIZE, 0, &op);
if (!EFI_ERROR (EfiStatus)) {
if (op->len != 2 || ((op->data[0] << 8) | op->data[1]) < DHCP4_DEFAULT_MAX_MESSAGE_SIZE) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
}
//
// If present, DHCP server identifier must be valid.
//
EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &op);
if (!EFI_ERROR (EfiStatus)) {
if (op->len != 4 || !EfiCompareMem (op->data, &bcast_ip, 4) || !EfiCompareMem (op->data, &zero_ip, 4)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
}
//
// If present, DHCP subnet mask must be valid.
//
EfiStatus = find_opt (
Offer,
DHCP4_SUBNET_MASK,
0,
&op
);
if (!EFI_ERROR (EfiStatus)) {
if (op->len != 4) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
}
}
//
// Early out for BOOTP.
//
This->Data->IsBootp = is_bootp;
if (is_bootp) {
//
// Copy offer packet to instance data.
//
EfiCopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET));
//
// Copy discover to request and offer to acknak.
//
EfiCopyMem (
&This->Data->Request,
&This->Data->Discover,
sizeof (DHCP4_PACKET)
);
EfiCopyMem (
&This->Data->AckNak,
&This->Data->Offer,
sizeof (DHCP4_PACKET)
);
//
// Set state flags.
//
This->Data->SelectCompleted = TRUE;
This->Data->IsAck = TRUE;
Private->callback = NULL;
return EFI_SUCCESS;
}
//
// Copy discover packet contents to request packet.
//
EfiCopyMem (&request, &This->Data->Discover, sizeof (DHCP4_PACKET));
This->Data->IsAck = FALSE;
//
// Change DHCP message type from discover to request.
//
EfiStatus = find_opt (&request, DHCP4_MESSAGE_TYPE, 0, &op);
if (EFI_ERROR (EfiStatus) && EfiStatus != EFI_NOT_FOUND) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (EfiStatus == EFI_NOT_FOUND) {
EfiStatus = find_opt (&request, DHCP4_END, 0, &op);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
op->op = DHCP4_MESSAGE_TYPE;
op->len = 1;
op->data[1] = DHCP4_END;
}
op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST;
//
// Copy server identifier option from offer to request.
//
EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &srvid);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
if (srvid->len != 4) {
Private->callback = NULL;
return EFI_INVALID_PARAMETER;
}
EfiStatus = add_opt (&request, srvid);
if (EFI_ERROR (EfiStatus)) {
DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));
Private->callback = NULL;
return EfiStatus;
}
//
// Add requested IP address option to request packet.
//
op = (DHCP4_OP *) buf;
op->op = DHCP4_REQUESTED_IP_ADDRESS;
op->len = 4;
EfiCopyMem (op->data, &Offer->dhcp4.yiaddr, 4);
EfiStatus = add_opt (&request, op);
if (EFI_ERROR (EfiStatus)) {
DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));
Private->callback = NULL;
return EfiStatus;
}
//
// Transimit DHCP request and wait for DHCP ack...
//
EfiSetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);
EfiStatus = tx_rx_udp (
Private,
&bcast_ip,
NULL,
NULL,
NULL,
&request,
&acknak,
&acknak_verify,
seconds_timeout
);
if (EFI_ERROR (EfiStatus)) {
DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));
Private->callback = NULL;
return EfiStatus;
}
//
// Set Data->IsAck and return.
//
EfiStatus = find_opt (&acknak, DHCP4_MESSAGE_TYPE, 0, &op);
if (EFI_ERROR (EfiStatus)) {
Private->callback = NULL;
return EFI_DEVICE_ERROR;
}
if (op->len != 1) {
Private->callback = NULL;
return EFI_DEVICE_ERROR;
}
switch (op->data[0]) {
case DHCP4_MESSAGE_TYPE_ACK:
This->Data->IsAck = TRUE;
break;
case DHCP4_MESSAGE_TYPE_NAK:
This->Data->IsAck = FALSE;
break;
default:
Private->callback = NULL;
return EFI_DEVICE_ERROR;
}
//
// Copy packets into instance data...
//
EfiCopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET));
EfiCopyMem (&This->Data->Request, &request, sizeof (DHCP4_PACKET));
EfiCopyMem (&This->Data->AckNak, &acknak, sizeof (DHCP4_PACKET));
This->Data->SelectCompleted = TRUE;
Private->callback = NULL;
return EFI_SUCCESS;
}
/* eof - PxeDhcp4InitSelect.c */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?