]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Setup.c
09ba041ea63adec5bd0e07ee506d0ce0d77e05d9
[mirror_edk2.git] / EdkModulePkg / Universal / Network / PxeDhcp4 / Dxe / PxeDhcp4Setup.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13 PxeDhcp4Setup.c
14
15 Abstract:
16
17 --*/
18
19
20 #include "PxeDhcp4.h"
21
22 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
23 EFI_STATUS
24 EFIAPI
25 PxeDhcp4Setup (
26 IN EFI_PXE_DHCP4_PROTOCOL *This,
27 IN EFI_PXE_DHCP4_DATA *Data
28 )
29 {
30 PXE_DHCP4_PRIVATE_DATA *Private;
31 DHCP4_HEADER *Packet;
32 EFI_STATUS EfiStatus;
33 UINT8 *OpLen;
34 UINT8 *OpPtr;
35
36 //
37 // Return error if parameters are invalid.
38 //
39 if (This == NULL) {
40 return EFI_INVALID_PARAMETER;
41 }
42
43 Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
44
45 if (Private == NULL) {
46 return EFI_INVALID_PARAMETER;
47 }
48
49 if (This->Data != NULL) {
50 return EFI_ALREADY_STARTED;
51 }
52
53 if (Private->PxeBc == NULL) {
54 return EFI_DEVICE_ERROR;
55 }
56 //
57 // Check contents of provided Data structure.
58 //
59 if (Data != NULL) {
60 //
61 // Do protocol state checks first.
62 //
63 if (Data->SelectCompleted) {
64 if (!Data->InitCompleted || !Data->SetupCompleted) {
65 return EFI_INVALID_PARAMETER;
66 }
67
68 if (Data->IsBootp && !Data->IsAck) {
69 return EFI_INVALID_PARAMETER;
70 }
71 } else if (Data->InitCompleted) {
72 if (!Data->SetupCompleted || Data->IsBootp || Data->IsAck) {
73 return EFI_INVALID_PARAMETER;
74 }
75 } else if (Data->SetupCompleted) {
76 if (Data->IsBootp || Data->IsAck) {
77 return EFI_INVALID_PARAMETER;
78 }
79 }
80 //
81 // Do packet content checks.
82 //
83 if (Data->SetupCompleted) {
84 //
85 // %%TBD - check discover packet
86 //
87 }
88
89 if (Data->SelectCompleted) {
90 if (Data->IsBootp) {
91 //
92 // %%TBD - check offer packet
93 //
94 if (CompareMem (
95 &Data->Discover,
96 &Data->Request,
97 sizeof (DHCP4_PACKET)
98 )) {
99 return EFI_INVALID_PARAMETER;
100 }
101
102 if (CompareMem (
103 &Data->Offer,
104 &Data->AckNak,
105 sizeof (DHCP4_PACKET)
106 )) {
107 return EFI_INVALID_PARAMETER;
108 }
109 } else {
110 //
111 // %%TBD - check offer, request & acknak packets
112 //
113 }
114 }
115 }
116 //
117 // Allocate data structure. Return error
118 // if there is not enough available memory.
119 //
120 EfiStatus = gBS->AllocatePool (
121 EfiBootServicesData,
122 sizeof (EFI_PXE_DHCP4_DATA),
123 (VOID **) &This->Data
124 );
125
126 if (EFI_ERROR (EfiStatus)) {
127 This->Data = NULL;
128 return EfiStatus;
129 }
130
131 if (This->Data == NULL) {
132 return EFI_OUT_OF_RESOURCES;
133 }
134 //
135 // Start PxeBc because we want to use its UdpWrite, UdpRead and
136 // SetFilter calls.
137 //
138 EfiStatus = Private->PxeBc->Start (Private->PxeBc, FALSE);
139
140 if (EFI_ERROR (EfiStatus)) {
141 if (EfiStatus != EFI_ALREADY_STARTED) {
142 gBS->FreePool (This->Data);
143 This->Data = NULL;
144 Private->PxeBc->Stop (Private->PxeBc);
145 return EfiStatus;
146 }
147
148 Private->StopPxeBc = FALSE;
149 } else {
150 Private->StopPxeBc = TRUE;
151 }
152 //
153 // Use new data.
154 //
155 if (Data != NULL) {
156 CopyMem (This->Data, Data, sizeof (EFI_PXE_DHCP4_DATA));
157 return EFI_SUCCESS;
158 }
159 //
160 // Initialize new public data structure.
161 //
162 ZeroMem (This->Data, sizeof (EFI_PXE_DHCP4_DATA));
163
164 //
165 // Fill in default DHCP discover packet.
166 // Check for MAC addresses of strange lengths, just in case.
167 //
168 Packet = &This->Data->Discover.dhcp4;
169
170 Packet->op = BOOTP_REQUEST;
171
172 Packet->htype = Private->Snp->Mode->IfType;
173
174 if (Private->Snp->Mode->HwAddressSize > 16) {
175 Packet->hlen = 16;
176 } else {
177 Packet->hlen = (UINT8) Private->Snp->Mode->HwAddressSize;
178 }
179
180 Packet->hops = 0; /* Set to zero per RFC 2131. */
181
182 if (Packet->hlen < sizeof Packet->xid) {
183 if (Packet->hlen != 0) {
184 CopyMem (
185 &Packet->xid,
186 &Private->Snp->Mode->CurrentAddress,
187 Packet->hlen
188 );
189 }
190 } else {
191 CopyMem (
192 &Packet->xid,
193 &Private->Snp->Mode->CurrentAddress.Addr[Packet->hlen - sizeof Packet->xid],
194 sizeof Packet->xid
195 );
196 }
197 //
198 // %%TBD - xid should be randomized
199 //
200 Packet->secs = htons (DHCP4_INITIAL_SECONDS);
201
202 Packet->flags = htons (DHCP4_BROADCAST_FLAG);
203
204 if (Packet->hlen != 0) {
205 CopyMem (Packet->chaddr, &Private->Snp->Mode->CurrentAddress, Packet->hlen);
206 }
207
208 Packet->magik = htonl (DHCP4_MAGIK_NUMBER);
209
210 OpPtr = Packet->options;
211
212 *OpPtr++ = DHCP4_MESSAGE_TYPE;
213 *OpPtr++ = 1;
214 *OpPtr++ = DHCP4_MESSAGE_TYPE_DISCOVER;
215
216 *OpPtr++ = DHCP4_MAX_MESSAGE_SIZE;
217 *OpPtr++ = 2;
218 *OpPtr++ = (UINT8) ((DHCP4_DEFAULT_MAX_MESSAGE_SIZE >> 8) & 0xFF);
219 *OpPtr++ = (UINT8) (DHCP4_DEFAULT_MAX_MESSAGE_SIZE & 0xFF);
220
221 *OpPtr++ = DHCP4_PARAMETER_REQUEST_LIST;
222 OpLen = OpPtr;
223 *OpPtr++ = 0;
224 *OpPtr++ = DHCP4_SUBNET_MASK;
225 *OpPtr++ = DHCP4_TIME_OFFSET;
226 *OpPtr++ = DHCP4_ROUTER_LIST;
227 *OpPtr++ = DHCP4_TIME_SERVERS;
228 *OpPtr++ = DHCP4_NAME_SERVERS;
229 *OpPtr++ = DHCP4_DNS_SERVERS;
230 *OpPtr++ = DHCP4_HOST_NAME;
231 *OpPtr++ = DHCP4_BOOT_FILE_SIZE;
232 *OpPtr++ = DHCP4_MESSAGE_TYPE;
233 *OpPtr++ = DHCP4_DOMAIN_NAME;
234 *OpPtr++ = DHCP4_ROOT_PATH;
235 *OpPtr++ = DHCP4_EXTENSION_PATH;
236 *OpPtr++ = DHCP4_MAX_DATAGRAM_SIZE;
237 *OpPtr++ = DHCP4_DEFAULT_TTL;
238 *OpPtr++ = DHCP4_BROADCAST_ADDRESS;
239 *OpPtr++ = DHCP4_NIS_DOMAIN_NAME;
240 *OpPtr++ = DHCP4_NIS_SERVERS;
241 *OpPtr++ = DHCP4_NTP_SERVERS;
242 *OpPtr++ = DHCP4_VENDOR_SPECIFIC;
243 *OpPtr++ = DHCP4_REQUESTED_IP_ADDRESS;
244 *OpPtr++ = DHCP4_LEASE_TIME;
245 *OpPtr++ = DHCP4_SERVER_IDENTIFIER;
246 *OpPtr++ = DHCP4_RENEWAL_TIME;
247 *OpPtr++ = DHCP4_REBINDING_TIME;
248 *OpPtr++ = DHCP4_CLASS_IDENTIFIER;
249 *OpPtr++ = DHCP4_TFTP_SERVER_NAME;
250 *OpPtr++ = DHCP4_BOOTFILE;
251 *OpPtr++ = 128;
252 *OpPtr++ = 129;
253 *OpPtr++ = 130;
254 *OpPtr++ = 131;
255 *OpPtr++ = 132;
256 *OpPtr++ = 133;
257 *OpPtr++ = 134;
258 *OpPtr++ = 135;
259 *OpLen = (UINT8) ((OpPtr - OpLen) - 1);
260
261 *OpPtr++ = DHCP4_END;
262
263 This->Data->SetupCompleted = TRUE;
264
265 return EFI_SUCCESS;
266 }
267
268 /* eof - PxeDhcp4Setup.c */