git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3492 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			259 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
| Copyright (c) 2004, Intel Corporation
 | |
| All rights reserved. This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| Module Name:
 | |
|   PxeDhcp4Setup.c
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "PxeDhcp4.h"
 | |
| 
 | |
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| PxeDhcp4Setup (
 | |
|   IN EFI_PXE_DHCP4_PROTOCOL *This,
 | |
|   IN EFI_PXE_DHCP4_DATA     *Data
 | |
|   )
 | |
| {
 | |
|   PXE_DHCP4_PRIVATE_DATA  *Private;
 | |
|   DHCP4_HEADER            *Packet;
 | |
|   EFI_STATUS              EfiStatus;
 | |
|   UINT8                   *OpLen;
 | |
|   UINT8                   *OpPtr;
 | |
| 
 | |
|   //
 | |
|   // Return error if parameters are invalid.
 | |
|   //
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (Private == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (This->Data != NULL) {
 | |
|     return EFI_ALREADY_STARTED;
 | |
|   }
 | |
| 
 | |
|   if (Private->PxeBc == NULL) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Check contents of provided Data structure.
 | |
|   //
 | |
|   if (Data != NULL) {
 | |
|     //
 | |
|     // Do protocol state checks first.
 | |
|     //
 | |
|     if (Data->SelectCompleted) {
 | |
|       if (!Data->InitCompleted || !Data->SetupCompleted) {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|       if (Data->IsBootp && !Data->IsAck) {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     } else if (Data->InitCompleted) {
 | |
|       if (!Data->SetupCompleted || Data->IsBootp || Data->IsAck) {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     } else if (Data->SetupCompleted) {
 | |
|       if (Data->IsBootp || Data->IsAck) {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // Do packet content checks.
 | |
|     //
 | |
|     if (Data->SetupCompleted) {
 | |
|       //
 | |
|       // %%TBD - check discover packet
 | |
|       //
 | |
|     }
 | |
| 
 | |
|     if (Data->SelectCompleted) {
 | |
|       if (Data->IsBootp) {
 | |
|         //
 | |
|         // %%TBD - check offer packet
 | |
|         //
 | |
|         if (CompareMem (
 | |
|               &Data->Discover,
 | |
|               &Data->Request,
 | |
|               sizeof (DHCP4_PACKET)
 | |
|               )) {
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         }
 | |
| 
 | |
|         if (CompareMem (
 | |
|               &Data->Offer,
 | |
|               &Data->AckNak,
 | |
|               sizeof (DHCP4_PACKET)
 | |
|               )) {
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       } else {
 | |
|         //
 | |
|         // %%TBD - check offer, request & acknak packets
 | |
|         //
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Allocate data structure.  Return error
 | |
|   // if there is not enough available memory.
 | |
|   //
 | |
|   This->Data = AllocatePool (sizeof (EFI_PXE_DHCP4_DATA));
 | |
|   if (This->Data == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   //
 | |
|   // Start PxeBc because we want to use its UdpWrite, UdpRead and
 | |
|   // SetFilter calls.
 | |
|   //
 | |
|   EfiStatus = Private->PxeBc->Start (Private->PxeBc, FALSE);
 | |
| 
 | |
|   if (EFI_ERROR (EfiStatus)) {
 | |
|     if (EfiStatus != EFI_ALREADY_STARTED) {
 | |
|       FreePool (This->Data);
 | |
|       This->Data = NULL;
 | |
|       Private->PxeBc->Stop (Private->PxeBc);
 | |
|       return EfiStatus;
 | |
|     }
 | |
| 
 | |
|     Private->StopPxeBc = FALSE;
 | |
|   } else {
 | |
|     Private->StopPxeBc = TRUE;
 | |
|   }
 | |
|   //
 | |
|   // Use new data.
 | |
|   //
 | |
|   if (Data != NULL) {
 | |
|     CopyMem (This->Data, Data, sizeof (EFI_PXE_DHCP4_DATA));
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // Initialize new public data structure.
 | |
|   //
 | |
|   ZeroMem (This->Data, sizeof (EFI_PXE_DHCP4_DATA));
 | |
| 
 | |
|   //
 | |
|   // Fill in default DHCP discover packet.
 | |
|   // Check for MAC addresses of strange lengths, just in case.
 | |
|   //
 | |
|   Packet        = &This->Data->Discover.dhcp4;
 | |
| 
 | |
|   Packet->op    = BOOTP_REQUEST;
 | |
| 
 | |
|   Packet->htype = Private->Snp->Mode->IfType;
 | |
| 
 | |
|   if (Private->Snp->Mode->HwAddressSize > 16) {
 | |
|     Packet->hlen = 16;
 | |
|   } else {
 | |
|     Packet->hlen = (UINT8) Private->Snp->Mode->HwAddressSize;
 | |
|   }
 | |
| 
 | |
|   Packet->hops = 0; /* Set to zero per RFC 2131. */
 | |
| 
 | |
|   if (Packet->hlen < sizeof Packet->xid) {
 | |
|     if (Packet->hlen != 0) {
 | |
|       CopyMem (
 | |
|         &Packet->xid,
 | |
|         &Private->Snp->Mode->CurrentAddress,
 | |
|         Packet->hlen
 | |
|         );
 | |
|     }
 | |
|   } else {
 | |
|     CopyMem (
 | |
|       &Packet->xid,
 | |
|       &Private->Snp->Mode->CurrentAddress.Addr[Packet->hlen - sizeof Packet->xid],
 | |
|       sizeof Packet->xid
 | |
|       );
 | |
|   }
 | |
|   //
 | |
|   // %%TBD - xid should be randomized
 | |
|   //
 | |
|   Packet->secs  = htons (DHCP4_INITIAL_SECONDS);
 | |
| 
 | |
|   Packet->flags = htons (DHCP4_BROADCAST_FLAG);
 | |
| 
 | |
|   if (Packet->hlen != 0) {
 | |
|     CopyMem (Packet->chaddr, &Private->Snp->Mode->CurrentAddress, Packet->hlen);
 | |
|   }
 | |
| 
 | |
|   Packet->magik               = htonl (DHCP4_MAGIK_NUMBER);
 | |
| 
 | |
|   OpPtr                       = Packet->options;
 | |
| 
 | |
|   *OpPtr++                    = DHCP4_MESSAGE_TYPE;
 | |
|   *OpPtr++                    = 1;
 | |
|   *OpPtr++                    = DHCP4_MESSAGE_TYPE_DISCOVER;
 | |
| 
 | |
|   *OpPtr++                    = DHCP4_MAX_MESSAGE_SIZE;
 | |
|   *OpPtr++                    = 2;
 | |
|   *OpPtr++                    = (UINT8) ((DHCP4_DEFAULT_MAX_MESSAGE_SIZE >> 8) & 0xFF);
 | |
|   *OpPtr++                    = (UINT8) (DHCP4_DEFAULT_MAX_MESSAGE_SIZE & 0xFF);
 | |
| 
 | |
|   *OpPtr++                    = DHCP4_PARAMETER_REQUEST_LIST;
 | |
|   OpLen                       = OpPtr;
 | |
|   *OpPtr++                    = 0;
 | |
|   *OpPtr++                    = DHCP4_SUBNET_MASK;
 | |
|   *OpPtr++                    = DHCP4_TIME_OFFSET;
 | |
|   *OpPtr++                    = DHCP4_ROUTER_LIST;
 | |
|   *OpPtr++                    = DHCP4_TIME_SERVERS;
 | |
|   *OpPtr++                    = DHCP4_NAME_SERVERS;
 | |
|   *OpPtr++                    = DHCP4_DNS_SERVERS;
 | |
|   *OpPtr++                    = DHCP4_HOST_NAME;
 | |
|   *OpPtr++                    = DHCP4_BOOT_FILE_SIZE;
 | |
|   *OpPtr++                    = DHCP4_MESSAGE_TYPE;
 | |
|   *OpPtr++                    = DHCP4_DOMAIN_NAME;
 | |
|   *OpPtr++                    = DHCP4_ROOT_PATH;
 | |
|   *OpPtr++                    = DHCP4_EXTENSION_PATH;
 | |
|   *OpPtr++                    = DHCP4_MAX_DATAGRAM_SIZE;
 | |
|   *OpPtr++                    = DHCP4_DEFAULT_TTL;
 | |
|   *OpPtr++                    = DHCP4_BROADCAST_ADDRESS;
 | |
|   *OpPtr++                    = DHCP4_NIS_DOMAIN_NAME;
 | |
|   *OpPtr++                    = DHCP4_NIS_SERVERS;
 | |
|   *OpPtr++                    = DHCP4_NTP_SERVERS;
 | |
|   *OpPtr++                    = DHCP4_VENDOR_SPECIFIC;
 | |
|   *OpPtr++                    = DHCP4_REQUESTED_IP_ADDRESS;
 | |
|   *OpPtr++                    = DHCP4_LEASE_TIME;
 | |
|   *OpPtr++                    = DHCP4_SERVER_IDENTIFIER;
 | |
|   *OpPtr++                    = DHCP4_RENEWAL_TIME;
 | |
|   *OpPtr++                    = DHCP4_REBINDING_TIME;
 | |
|   *OpPtr++                    = DHCP4_CLASS_IDENTIFIER;
 | |
|   *OpPtr++                    = DHCP4_TFTP_SERVER_NAME;
 | |
|   *OpPtr++                    = DHCP4_BOOTFILE;
 | |
|   *OpPtr++                    = 128;
 | |
|   *OpPtr++                    = 129;
 | |
|   *OpPtr++                    = 130;
 | |
|   *OpPtr++                    = 131;
 | |
|   *OpPtr++                    = 132;
 | |
|   *OpPtr++                    = 133;
 | |
|   *OpPtr++                    = 134;
 | |
|   *OpPtr++                    = 135;
 | |
|   *OpLen                      = (UINT8) ((OpPtr - OpLen) - 1);
 | |
| 
 | |
|   *OpPtr++                    = DHCP4_END;
 | |
| 
 | |
|   This->Data->SetupCompleted  = TRUE;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /* eof - PxeDhcp4Setup.c */
 |