]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BootOptionSupport.c
ArmPlatformPkg/Bds: Added update of Pxe boot option
[mirror_edk2.git] / ArmPlatformPkg / Bds / BootOptionSupport.c
CommitLineData
ea46ebbe 1/** @file\r
2*\r
55a9f75d 3* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
ea46ebbe 4*\r
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12*\r
13**/\r
14\r
15#include "BdsInternal.h"\r
16\r
17#include <Library/NetLib.h>\r
18\r
19#include <Protocol/BlockIo.h>\r
20#include <Protocol/DevicePathToText.h>\r
21#include <Protocol/PxeBaseCode.h>\r
22#include <Protocol/SimpleFileSystem.h>\r
23#include <Protocol/SimpleNetwork.h>\r
24\r
25#include <Guid/FileSystemInfo.h>\r
26\r
27#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))\r
28\r
29EFI_STATUS\r
30BdsLoadOptionFileSystemList (\r
31 IN OUT LIST_ENTRY* BdsLoadOptionList\r
32 );\r
33\r
34EFI_STATUS\r
35BdsLoadOptionFileSystemCreateDevicePath (\r
22a262c8 36 IN CHAR16* FileName,\r
ecc62d13 37 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes,\r
55a9f75d 38 OUT BOOLEAN *RequestBootType\r
ea46ebbe 39 );\r
40\r
41EFI_STATUS\r
42BdsLoadOptionFileSystemUpdateDevicePath (\r
22a262c8 43 IN EFI_DEVICE_PATH *OldDevicePath,\r
44 IN CHAR16* FileName,\r
45 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
55a9f75d 46 OUT BOOLEAN *RequestBootType\r
ea46ebbe 47 );\r
48\r
49BOOLEAN\r
50BdsLoadOptionFileSystemIsSupported (\r
22a262c8 51 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 52 );\r
53\r
54EFI_STATUS\r
55BdsLoadOptionMemMapList (\r
56 IN OUT LIST_ENTRY* BdsLoadOptionList\r
57 );\r
58\r
59EFI_STATUS\r
60BdsLoadOptionMemMapCreateDevicePath (\r
22a262c8 61 IN CHAR16* FileName,\r
ecc62d13 62 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes,\r
55a9f75d 63 OUT BOOLEAN *RequestBootType\r
ea46ebbe 64 );\r
65\r
66EFI_STATUS\r
67BdsLoadOptionMemMapUpdateDevicePath (\r
22a262c8 68 IN EFI_DEVICE_PATH *OldDevicePath,\r
69 IN CHAR16* FileName,\r
70 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
55a9f75d 71 OUT BOOLEAN *RequestBootType\r
ea46ebbe 72 );\r
73\r
74BOOLEAN\r
75BdsLoadOptionMemMapIsSupported (\r
22a262c8 76 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 77 );\r
78\r
79EFI_STATUS\r
80BdsLoadOptionPxeList (\r
81 IN OUT LIST_ENTRY* BdsLoadOptionList\r
82 );\r
83\r
84EFI_STATUS\r
85BdsLoadOptionPxeCreateDevicePath (\r
22a262c8 86 IN CHAR16* FileName,\r
ecc62d13 87 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes,\r
55a9f75d 88 OUT BOOLEAN *RequestBootType\r
ea46ebbe 89 );\r
90\r
91EFI_STATUS\r
92BdsLoadOptionPxeUpdateDevicePath (\r
22a262c8 93 IN EFI_DEVICE_PATH *OldDevicePath,\r
94 IN CHAR16* FileName,\r
95 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
55a9f75d 96 OUT BOOLEAN *RequestBootType\r
ea46ebbe 97 );\r
98\r
99BOOLEAN\r
100BdsLoadOptionPxeIsSupported (\r
22a262c8 101 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 102 );\r
103\r
104EFI_STATUS\r
105BdsLoadOptionTftpList (\r
106 IN OUT LIST_ENTRY* BdsLoadOptionList\r
107 );\r
108\r
109EFI_STATUS\r
110BdsLoadOptionTftpCreateDevicePath (\r
22a262c8 111 IN CHAR16* FileName,\r
ecc62d13 112 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes,\r
55a9f75d 113 OUT BOOLEAN *RequestBootType\r
ea46ebbe 114 );\r
115\r
116EFI_STATUS\r
117BdsLoadOptionTftpUpdateDevicePath (\r
22a262c8 118 IN EFI_DEVICE_PATH *OldDevicePath,\r
119 IN CHAR16* FileName,\r
120 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
55a9f75d 121 OUT BOOLEAN *RequestBootType\r
ea46ebbe 122 );\r
123\r
124BOOLEAN\r
125BdsLoadOptionTftpIsSupported (\r
22a262c8 126 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 127 );\r
128\r
129BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList[] = {\r
2ccfb71e 130 {\r
131 BDS_DEVICE_FILESYSTEM,\r
132 BdsLoadOptionFileSystemList,\r
133 BdsLoadOptionFileSystemIsSupported,\r
134 BdsLoadOptionFileSystemCreateDevicePath,\r
135 BdsLoadOptionFileSystemUpdateDevicePath\r
136 },\r
137 {\r
138 BDS_DEVICE_MEMMAP,\r
139 BdsLoadOptionMemMapList,\r
140 BdsLoadOptionMemMapIsSupported,\r
141 BdsLoadOptionMemMapCreateDevicePath,\r
142 BdsLoadOptionMemMapUpdateDevicePath\r
143 },\r
144 {\r
145 BDS_DEVICE_PXE,\r
146 BdsLoadOptionPxeList,\r
147 BdsLoadOptionPxeIsSupported,\r
148 BdsLoadOptionPxeCreateDevicePath,\r
149 BdsLoadOptionPxeUpdateDevicePath\r
150 },\r
151 {\r
152 BDS_DEVICE_TFTP,\r
153 BdsLoadOptionTftpList,\r
154 BdsLoadOptionTftpIsSupported,\r
155 BdsLoadOptionTftpCreateDevicePath,\r
156 BdsLoadOptionTftpUpdateDevicePath\r
157 }\r
ea46ebbe 158};\r
159\r
160EFI_STATUS\r
161BootDeviceListSupportedInit (\r
162 IN OUT LIST_ENTRY *SupportedDeviceList\r
163 )\r
164{\r
165 UINTN Index;\r
166\r
167 // Initialize list of supported devices\r
168 InitializeListHead (SupportedDeviceList);\r
169\r
170 for (Index = 0; Index < BDS_DEVICE_MAX; Index++) {\r
2ccfb71e 171 BdsLoadOptionSupportList[Index].ListDevices (SupportedDeviceList);\r
ea46ebbe 172 }\r
173\r
174 return EFI_SUCCESS;\r
175}\r
176\r
177EFI_STATUS\r
178BootDeviceListSupportedFree (\r
656416bc 179 IN LIST_ENTRY *SupportedDeviceList,\r
180 IN BDS_SUPPORTED_DEVICE *Except\r
ea46ebbe 181 )\r
182{\r
183 LIST_ENTRY *Entry;\r
184 BDS_SUPPORTED_DEVICE* SupportedDevice;\r
185\r
186 Entry = GetFirstNode (SupportedDeviceList);\r
187 while (Entry != SupportedDeviceList) {\r
188 SupportedDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);\r
189 Entry = RemoveEntryList (Entry);\r
656416bc 190 if (SupportedDevice != Except) {\r
2ccfb71e 191 FreePool (SupportedDevice);\r
656416bc 192 }\r
ea46ebbe 193 }\r
194\r
195 return EFI_SUCCESS;\r
196}\r
197\r
198EFI_STATUS\r
199BootDeviceGetDeviceSupport (\r
22a262c8 200 IN EFI_DEVICE_PATH *DevicePath,\r
201 OUT BDS_LOAD_OPTION_SUPPORT **DeviceSupport\r
ea46ebbe 202 )\r
203{\r
204 UINTN Index;\r
205\r
206 // Find which supported device is the most appropriate\r
207 for (Index = 0; Index < BDS_DEVICE_MAX; Index++) {\r
22a262c8 208 if (BdsLoadOptionSupportList[Index].IsSupported (DevicePath)) {\r
ea46ebbe 209 *DeviceSupport = &BdsLoadOptionSupportList[Index];\r
210 return EFI_SUCCESS;\r
211 }\r
212 }\r
213\r
214 return EFI_UNSUPPORTED;\r
215}\r
216\r
ea46ebbe 217EFI_STATUS\r
218BootDeviceGetType (\r
55a9f75d 219 IN EFI_DEVICE_PATH* DevicePath,\r
2ccfb71e 220 OUT ARM_BDS_LOADER_TYPE *BootType,\r
ea46ebbe 221 OUT UINT32 *Attributes\r
222 )\r
223{\r
55a9f75d
OM
224 EFI_STATUS Status;\r
225 BOOLEAN IsEfiApp;\r
226 BOOLEAN IsBootLoader;\r
227 BOOLEAN HasFDTSupport;\r
228 CHAR16* FileName;\r
229 EFI_DEVICE_PATH* PrevDevicePathNode;\r
230 EFI_DEVICE_PATH* DevicePathNode;\r
231 EFI_PHYSICAL_ADDRESS Image;\r
232 UINTN FileSize;\r
233 EFI_IMAGE_DOS_HEADER* DosHeader;\r
234 UINTN PeCoffHeaderOffset;\r
235 EFI_IMAGE_NT_HEADERS32* NtHeader;\r
236\r
237 //\r
238 // Check if the last node of the device path is a FilePath node\r
239 //\r
240 PrevDevicePathNode = NULL;\r
241 DevicePathNode = DevicePath;\r
242 while ((DevicePathNode != NULL) && !IsDevicePathEnd (DevicePathNode)) {\r
243 PrevDevicePathNode = DevicePathNode;\r
244 DevicePathNode = NextDevicePathNode (DevicePathNode);\r
245 }\r
246\r
247 if ((PrevDevicePathNode != NULL) &&\r
248 (PrevDevicePathNode->Type == MEDIA_DEVICE_PATH) &&\r
249 (PrevDevicePathNode->SubType == MEDIA_FILEPATH_DP))\r
250 {\r
251 FileName = ((FILEPATH_DEVICE_PATH*)PrevDevicePathNode)->PathName;\r
252 } else {\r
253 FileName = NULL;\r
254 }\r
ea46ebbe 255\r
256 if (FileName == NULL) {\r
257 Print(L"Is an EFI Application? ");\r
258 Status = GetHIInputBoolean (&IsEfiApp);\r
259 if (EFI_ERROR(Status)) {\r
260 return EFI_ABORTED;\r
261 }\r
262 } else if (HasFilePathEfiExtension(FileName)) {\r
263 IsEfiApp = TRUE;\r
264 } else {\r
55a9f75d
OM
265 // Check if the file exist\r
266 Status = BdsLoadImage (DevicePath, AllocateAnyPages, &Image, &FileSize);\r
267 if (!EFI_ERROR (Status)) {\r
268\r
269 DosHeader = (EFI_IMAGE_DOS_HEADER *)(UINTN) Image;\r
270 if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
271 //\r
272 // DOS image header is present,\r
273 // so read the PE header after the DOS image header.\r
274 //\r
275 PeCoffHeaderOffset = DosHeader->e_lfanew;\r
276 } else {\r
277 PeCoffHeaderOffset = 0;\r
278 }\r
279\r
280 //\r
281 // Check PE/COFF image.\r
282 //\r
283 NtHeader = (EFI_IMAGE_NT_HEADERS32 *)(UINTN) (Image + PeCoffHeaderOffset);\r
284 if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
285 IsEfiApp = FALSE;\r
286 } else {\r
287 IsEfiApp = TRUE;\r
288 }\r
289\r
290 // Free memory\r
291 gBS->FreePages (Image, EFI_SIZE_TO_PAGES(FileSize));\r
292 } else {\r
293 // If we did not manage to open it then ask for the type\r
294 Print(L"Is an EFI Application? ");\r
295 Status = GetHIInputBoolean (&IsEfiApp);\r
296 if (EFI_ERROR(Status)) {\r
297 return EFI_ABORTED;\r
298 }\r
299 }\r
ea46ebbe 300 }\r
301\r
302 if (IsEfiApp) {\r
303 Print(L"Is your application is an OS loader? ");\r
304 Status = GetHIInputBoolean (&IsBootLoader);\r
305 if (EFI_ERROR(Status)) {\r
306 return EFI_ABORTED;\r
307 }\r
308 if (!IsBootLoader) {\r
309 *Attributes |= LOAD_OPTION_CATEGORY_APP;\r
310 }\r
311 *BootType = BDS_LOADER_EFI_APPLICATION;\r
312 } else {\r
313 Print(L"Has FDT support? ");\r
314 Status = GetHIInputBoolean (&HasFDTSupport);\r
315 if (EFI_ERROR(Status)) {\r
316 return EFI_ABORTED;\r
317 }\r
318 if (HasFDTSupport) {\r
319 *BootType = BDS_LOADER_KERNEL_LINUX_FDT;\r
320 } else {\r
321 *BootType = BDS_LOADER_KERNEL_LINUX_ATAG;\r
322 }\r
323 }\r
324\r
325 return EFI_SUCCESS;\r
326}\r
327\r
328EFI_STATUS\r
329BdsLoadOptionFileSystemList (\r
330 IN OUT LIST_ENTRY* BdsLoadOptionList\r
331 )\r
332{\r
333 EFI_STATUS Status;\r
334 UINTN HandleCount;\r
335 EFI_HANDLE *HandleBuffer;\r
336 UINTN Index;\r
337 BDS_SUPPORTED_DEVICE *SupportedDevice;\r
338 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileProtocol;\r
339 EFI_FILE_HANDLE Fs;\r
340 UINTN Size;\r
341 EFI_FILE_SYSTEM_INFO* FsInfo;\r
342 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
343\r
344 // List all the Simple File System Protocols\r
345 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
346 if (EFI_ERROR (Status)) {\r
347 return Status;\r
348 }\r
349\r
350 for (Index = 0; Index < HandleCount; Index++) {\r
351 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
352 if (!EFI_ERROR(Status)) {\r
353 // Allocate BDS Supported Device structure\r
2ccfb71e 354 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof(BDS_SUPPORTED_DEVICE));\r
ea46ebbe 355\r
356 FileProtocol = NULL;\r
357 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FileProtocol);\r
358 ASSERT_EFI_ERROR(Status);\r
359\r
360 FileProtocol->OpenVolume (FileProtocol, &Fs);\r
361\r
362 // Generate a Description from the file system\r
363 Size = 0;\r
364 FsInfo = NULL;\r
365 Status = Fs->GetInfo (Fs, &gEfiFileSystemInfoGuid, &Size, FsInfo);\r
366 if (Status == EFI_BUFFER_TOO_SMALL) {\r
367 FsInfo = AllocatePool (Size);\r
368 Status = Fs->GetInfo (Fs, &gEfiFileSystemInfoGuid, &Size, FsInfo);\r
369 }\r
370 UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"%s (%d MB)",FsInfo->VolumeLabel,(UINT32)(FsInfo->VolumeSize / (1024 * 1024)));\r
371 FreePool(FsInfo);\r
372 Fs->Close (Fs);\r
373\r
374 SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
375 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_FILESYSTEM];\r
376\r
377 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
378 }\r
379 }\r
380\r
381 return EFI_SUCCESS;\r
382}\r
383\r
384EFI_STATUS\r
385BdsLoadOptionFileSystemCreateDevicePath (\r
22a262c8 386 IN CHAR16* FileName,\r
ecc62d13 387 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes,\r
55a9f75d 388 OUT BOOLEAN *RequestBootType\r
ea46ebbe 389 )\r
390{\r
391 EFI_STATUS Status;\r
392 FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
74b96132 393 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
ea46ebbe 394 UINTN BootFilePathSize;\r
395\r
22a262c8 396 Print(L"File path of the %s: ", FileName);\r
74b96132 397 Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
ea46ebbe 398 if (EFI_ERROR(Status)) {\r
399 return EFI_ABORTED;\r
400 }\r
401\r
74b96132 402 BootFilePathSize = StrSize (BootFilePath);\r
403 if (BootFilePathSize == 2) {\r
ecc62d13 404 *DevicePathNodes = NULL;\r
656416bc 405 return EFI_NOT_FOUND;\r
406 }\r
407\r
ea46ebbe 408 // Create the FilePath Device Path node\r
ecc62d13 409 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH);\r
ea46ebbe 410 FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;\r
411 FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;\r
412 SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
413 CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);\r
ecc62d13 414 SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize));\r
55a9f75d 415 *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath;\r
ea46ebbe 416\r
417 return Status;\r
418}\r
419\r
420EFI_STATUS\r
421BdsLoadOptionFileSystemUpdateDevicePath (\r
22a262c8 422 IN EFI_DEVICE_PATH *OldDevicePath,\r
423 IN CHAR16* FileName,\r
424 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
55a9f75d 425 OUT BOOLEAN *RequestBootType\r
ea46ebbe 426 )\r
427{\r
428 EFI_STATUS Status;\r
74b96132 429 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
ea46ebbe 430 UINTN BootFilePathSize;\r
431 FILEPATH_DEVICE_PATH* EndingDevicePath;\r
432 FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
433 EFI_DEVICE_PATH* DevicePath;\r
434\r
0db25ccc 435 DevicePath = DuplicateDevicePath (OldDevicePath);\r
ea46ebbe 436\r
656416bc 437 EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath);\r
438 \r
22a262c8 439 Print(L"File path of the %s: ", FileName);\r
74b96132 440 StrnCpy (BootFilePath, EndingDevicePath->PathName, BOOT_DEVICE_FILEPATH_MAX);\r
441 Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
ea46ebbe 442 if (EFI_ERROR(Status)) {\r
443 return Status;\r
444 }\r
445\r
74b96132 446 BootFilePathSize = StrSize(BootFilePath);\r
447 if (BootFilePathSize == 2) {\r
656416bc 448 *NewDevicePath = NULL;\r
449 return EFI_NOT_FOUND;\r
450 }\r
451\r
ea46ebbe 452 // Create the FilePath Device Path node\r
453 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
454 FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;\r
455 FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;\r
456 SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
457 CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);\r
ea46ebbe 458\r
459 // Generate the new Device Path by replacing the last node by the updated node\r
460 SetDevicePathEndNode (EndingDevicePath);\r
461 *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath);\r
462 FreePool(DevicePath);\r
463\r
656416bc 464 return EFI_SUCCESS;\r
ea46ebbe 465}\r
466\r
467BOOLEAN\r
468BdsLoadOptionFileSystemIsSupported (\r
22a262c8 469 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 470 )\r
471{\r
472 EFI_DEVICE_PATH* DevicePathNode;\r
473\r
22a262c8 474 DevicePathNode = GetLastDevicePathNode (DevicePath);\r
ea46ebbe 475\r
476 return IS_DEVICE_PATH_NODE(DevicePathNode,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP);\r
477}\r
478\r
479STATIC\r
480BOOLEAN\r
481IsParentDevicePath (\r
482 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
483 IN EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath\r
484 )\r
485{\r
486 UINTN ParentSize;\r
487 UINTN ChildSize;\r
488\r
489 ParentSize = GetDevicePathSize (ParentDevicePath);\r
490 ChildSize = GetDevicePathSize (ChildDevicePath);\r
491\r
492 if (ParentSize > ChildSize) {\r
493 return FALSE;\r
494 }\r
495\r
496 if (CompareMem (ParentDevicePath, ChildDevicePath, ParentSize - END_DEVICE_PATH_LENGTH) != 0) {\r
497 return FALSE;\r
498 }\r
499\r
500 return TRUE;\r
501}\r
502\r
503EFI_STATUS\r
504BdsLoadOptionMemMapList (\r
505 IN OUT LIST_ENTRY* BdsLoadOptionList\r
506 )\r
507{\r
508 EFI_STATUS Status;\r
509 UINTN HandleCount;\r
510 EFI_HANDLE *HandleBuffer;\r
511 UINTN DevicePathHandleCount;\r
512 EFI_HANDLE *DevicePathHandleBuffer;\r
513 BOOLEAN IsParent;\r
514 UINTN Index;\r
515 UINTN Index2;\r
516 BDS_SUPPORTED_DEVICE *SupportedDevice;\r
517 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
518 EFI_DEVICE_PATH* DevicePath;\r
519\r
520 // List all the BlockIo Protocols\r
521 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
522 if (EFI_ERROR (Status)) {\r
523 return Status;\r
524 }\r
525\r
526 for (Index = 0; Index < HandleCount; Index++) {\r
527 // We only select the handle WITH a Device Path AND not part of Media (to avoid duplication with HardDisk, CDROM, etc)\r
528 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
529 if (!EFI_ERROR(Status)) {\r
530 // BlockIo is not part of Media Device Path\r
531 DevicePath = DevicePathProtocol;\r
532 while (!IsDevicePathEndType (DevicePath) && (DevicePathType (DevicePath) != MEDIA_DEVICE_PATH)) {\r
533 DevicePath = NextDevicePathNode (DevicePath);\r
534 }\r
535 if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {\r
536 continue;\r
537 }\r
538\r
539 // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child\r
540 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &DevicePathHandleCount, &DevicePathHandleBuffer);\r
541 ASSERT_EFI_ERROR (Status);\r
542 IsParent = FALSE;\r
543 for (Index2 = 0; (Index2 < DevicePathHandleCount) && !IsParent; Index2++) {\r
544 if (HandleBuffer[Index] != DevicePathHandleBuffer[Index2]) {\r
545 gBS->HandleProtocol (DevicePathHandleBuffer[Index2], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);\r
546 if (IsParentDevicePath (DevicePathProtocol, DevicePath)) {\r
547 IsParent = TRUE;\r
548 }\r
549 }\r
550 }\r
551 if (IsParent) {\r
552 continue;\r
553 }\r
554\r
555 // Allocate BDS Supported Device structure\r
556 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
557\r
558 Status = GenerateDeviceDescriptionName (HandleBuffer[Index], SupportedDevice->Description);\r
559 ASSERT_EFI_ERROR (Status);\r
560\r
561 SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
562 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_MEMMAP];\r
563\r
564 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
565 }\r
566 }\r
567\r
568 return EFI_SUCCESS;\r
569}\r
570\r
571EFI_STATUS\r
572BdsLoadOptionMemMapCreateDevicePath (\r
22a262c8 573 IN CHAR16* FileName,\r
ecc62d13 574 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes,\r
55a9f75d 575 OUT BOOLEAN *RequestBootType\r
ea46ebbe 576 )\r
577{\r
22a262c8 578 EFI_STATUS Status;\r
579 MEMMAP_DEVICE_PATH *MemMapDevicePath;\r
580 CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
581 CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
ea46ebbe 582\r
22a262c8 583 Print(L"Starting Address of the %s: ", FileName);\r
584 Status = GetHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
ea46ebbe 585 if (EFI_ERROR(Status)) {\r
586 return EFI_ABORTED;\r
587 }\r
588\r
22a262c8 589 Print(L"Ending Address of the %s: ", FileName);\r
590 Status = GetHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
ea46ebbe 591 if (EFI_ERROR(Status)) {\r
592 return EFI_ABORTED;\r
593 }\r
594\r
595 // Create the MemMap Device Path Node\r
22a262c8 596 MemMapDevicePath = (MEMMAP_DEVICE_PATH*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH) + END_DEVICE_PATH_LENGTH);\r
ea46ebbe 597 MemMapDevicePath->Header.Type = HARDWARE_DEVICE_PATH;\r
598 MemMapDevicePath->Header.SubType = HW_MEMMAP_DP;\r
22a262c8 599 SetDevicePathNodeLength (MemMapDevicePath, sizeof(MEMMAP_DEVICE_PATH));\r
ea46ebbe 600 MemMapDevicePath->MemoryType = EfiBootServicesData;\r
74b96132 601 MemMapDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress);\r
602 MemMapDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress);\r
ea46ebbe 603\r
22a262c8 604 // Set a Device Path End Node after the Memory Map Device Path Node\r
605 SetDevicePathEndNode (MemMapDevicePath + 1);\r
55a9f75d 606 *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath;\r
ea46ebbe 607\r
608 return Status;\r
609}\r
610\r
611EFI_STATUS\r
612BdsLoadOptionMemMapUpdateDevicePath (\r
22a262c8 613 IN EFI_DEVICE_PATH *OldDevicePath,\r
614 IN CHAR16* FileName,\r
615 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
55a9f75d 616 OUT BOOLEAN *RequestBootType\r
ea46ebbe 617 )\r
618{\r
6bab33c7 619 EFI_STATUS Status;\r
74b96132 620 CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
621 CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
6bab33c7 622 MEMMAP_DEVICE_PATH* EndingDevicePath;\r
623 EFI_DEVICE_PATH* DevicePath;\r
624\r
656416bc 625 DevicePath = DuplicateDevicePath (OldDevicePath);\r
6bab33c7 626 EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath);\r
627\r
22a262c8 628 Print(L"Starting Address of the %s: ", FileName);\r
74b96132 629 UnicodeSPrint (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->StartingAddress);\r
630 Status = EditHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
6bab33c7 631 if (EFI_ERROR(Status)) {\r
632 return EFI_ABORTED;\r
633 }\r
634\r
22a262c8 635 Print(L"Ending Address of the %s: ", FileName);\r
74b96132 636 UnicodeSPrint (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->EndingAddress);\r
637 Status = EditHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
6bab33c7 638 if (EFI_ERROR(Status)) {\r
639 return EFI_ABORTED;\r
640 }\r
641\r
74b96132 642 EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress);\r
643 EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress);\r
6bab33c7 644\r
6bab33c7 645 if (EFI_ERROR(Status)) {\r
646 FreePool(DevicePath);\r
647 } else {\r
648 *NewDevicePath = DevicePath;\r
649 }\r
650\r
651 return Status;\r
ea46ebbe 652}\r
653\r
654BOOLEAN\r
655BdsLoadOptionMemMapIsSupported (\r
22a262c8 656 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 657 )\r
658{\r
659 EFI_DEVICE_PATH* DevicePathNode;\r
660\r
22a262c8 661 DevicePathNode = GetLastDevicePathNode (DevicePath);\r
ea46ebbe 662\r
663 return IS_DEVICE_PATH_NODE(DevicePathNode,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP);\r
664}\r
665\r
666EFI_STATUS\r
667BdsLoadOptionPxeList (\r
668 IN OUT LIST_ENTRY* BdsLoadOptionList\r
669 )\r
670{\r
671 EFI_STATUS Status;\r
672 UINTN HandleCount;\r
673 EFI_HANDLE *HandleBuffer;\r
674 UINTN Index;\r
675 BDS_SUPPORTED_DEVICE *SupportedDevice;\r
676 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
677 EFI_SIMPLE_NETWORK_PROTOCOL* SimpleNet;\r
678 CHAR16 DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
679 EFI_MAC_ADDRESS *Mac;\r
680\r
681 // List all the PXE Protocols\r
682 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
683 if (EFI_ERROR (Status)) {\r
684 return Status;\r
685 }\r
686\r
687 for (Index = 0; Index < HandleCount; Index++) {\r
688 // We only select the handle WITH a Device Path AND the PXE Protocol\r
689 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
690 if (!EFI_ERROR(Status)) {\r
691 // Allocate BDS Supported Device structure\r
692 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
693\r
694 Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet);\r
695 if (!EFI_ERROR(Status)) {\r
696 Mac = &SimpleNet->Mode->CurrentAddress;\r
697 UnicodeSPrint (DeviceDescription,BOOT_DEVICE_DESCRIPTION_MAX,L"MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]);\r
698 } else {\r
699 Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);\r
700 ASSERT_EFI_ERROR (Status);\r
701 }\r
702 UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"PXE on %s",DeviceDescription);\r
703\r
704 SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
705 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_PXE];\r
706\r
707 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
708 }\r
709 }\r
710\r
711 return EFI_SUCCESS;\r
712}\r
713\r
714EFI_STATUS\r
715BdsLoadOptionPxeCreateDevicePath (\r
22a262c8 716 IN CHAR16* FileName,\r
ecc62d13 717 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes,\r
55a9f75d 718 OUT BOOLEAN *RequestBootType\r
ea46ebbe 719 )\r
720{\r
ecc62d13 721 *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
722 SetDevicePathEndNode (*DevicePathNodes);\r
55a9f75d
OM
723\r
724 if (RequestBootType) {\r
725 *RequestBootType = FALSE;\r
726 }\r
ea46ebbe 727 return EFI_SUCCESS;\r
728}\r
729\r
2db16368
RC
730/**\r
731 Update the parameters of a Pxe boot option\r
732\r
733 @param[in] OldDevicePath Current complete device path of the Pxe boot option.\r
734 This has to be a valid complete Pxe boot option path.\r
735 @param[in] FileName Description of the file the path is asked for\r
736 @param[out] NewDevicePath Pointer to the new complete device path.\r
737\r
738 @retval EFI_SUCCESS Update completed\r
739 @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource\r
740**/\r
ea46ebbe 741EFI_STATUS\r
742BdsLoadOptionPxeUpdateDevicePath (\r
22a262c8 743 IN EFI_DEVICE_PATH *OldDevicePath,\r
744 IN CHAR16* FileName,\r
745 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
55a9f75d 746 OUT BOOLEAN *RequestBootType\r
ea46ebbe 747 )\r
748{\r
2db16368
RC
749 //\r
750 // Make a copy of the complete device path that is made of :\r
751 // the device path of the device supporting the Pxe base code protocol\r
752 // followed by an end node.\r
753 //\r
754 *NewDevicePath = DuplicateDevicePath (OldDevicePath);\r
755 if (*NewDevicePath == NULL) {\r
756 return EFI_OUT_OF_RESOURCES;\r
757 } else {\r
758 return EFI_SUCCESS;\r
759 }\r
ea46ebbe 760}\r
761\r
762BOOLEAN\r
763BdsLoadOptionPxeIsSupported (\r
22a262c8 764 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 765 )\r
766{\r
767 EFI_STATUS Status;\r
768 EFI_HANDLE Handle;\r
769 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
770 EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol;\r
771\r
22a262c8 772 Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
ea46ebbe 773 if (EFI_ERROR(Status)) {\r
774 return FALSE;\r
775 }\r
776\r
777 if (!IsDevicePathEnd(RemainingDevicePath)) {\r
778 return FALSE;\r
779 }\r
780\r
781 Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
782 if (EFI_ERROR (Status)) {\r
783 return FALSE;\r
784 } else {\r
785 return TRUE;\r
786 }\r
787}\r
788\r
789EFI_STATUS\r
790BdsLoadOptionTftpList (\r
791 IN OUT LIST_ENTRY* BdsLoadOptionList\r
792 )\r
793{\r
794 EFI_STATUS Status;\r
795 UINTN HandleCount;\r
796 EFI_HANDLE *HandleBuffer;\r
797 UINTN Index;\r
798 BDS_SUPPORTED_DEVICE *SupportedDevice;\r
799 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
800 EFI_SIMPLE_NETWORK_PROTOCOL* SimpleNet;\r
801 CHAR16 DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
802 EFI_MAC_ADDRESS *Mac;\r
803\r
804 // List all the PXE Protocols\r
805 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
806 if (EFI_ERROR (Status)) {\r
807 return Status;\r
808 }\r
809\r
810 for (Index = 0; Index < HandleCount; Index++) {\r
811 // We only select the handle WITH a Device Path AND the PXE Protocol AND the TFTP Protocol (the TFTP protocol is required to start PXE)\r
812 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
813 if (!EFI_ERROR(Status)) {\r
814 // Allocate BDS Supported Device structure\r
815 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
816\r
817 Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet);\r
818 if (!EFI_ERROR(Status)) {\r
819 Mac = &SimpleNet->Mode->CurrentAddress;\r
820 UnicodeSPrint (DeviceDescription,BOOT_DEVICE_DESCRIPTION_MAX,L"MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]);\r
821 } else {\r
822 Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);\r
823 ASSERT_EFI_ERROR (Status);\r
824 }\r
b34e4db3 825 UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"TFTP on %s",DeviceDescription);\r
ea46ebbe 826\r
827 SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
828 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP];\r
829\r
830 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
831 }\r
832 }\r
833\r
834 return EFI_SUCCESS;\r
835}\r
836\r
837EFI_STATUS\r
838BdsLoadOptionTftpCreateDevicePath (\r
22a262c8 839 IN CHAR16* FileName,\r
ecc62d13 840 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes,\r
55a9f75d 841 OUT BOOLEAN *RequestBootType\r
ea46ebbe 842 )\r
843{\r
844 EFI_STATUS Status;\r
845 BOOLEAN IsDHCP;\r
846 EFI_IP_ADDRESS LocalIp;\r
847 EFI_IP_ADDRESS RemoteIp;\r
848 IPv4_DEVICE_PATH* IPv4DevicePathNode;\r
849 FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
74b96132 850 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
ea46ebbe 851 UINTN BootFilePathSize;\r
852\r
853 Print(L"Get the IP address from DHCP: ");\r
854 Status = GetHIInputBoolean (&IsDHCP);\r
855 if (EFI_ERROR(Status)) {\r
856 return EFI_ABORTED;\r
857 }\r
858\r
859 if (!IsDHCP) {\r
860 Print(L"Get the static IP address: ");\r
861 Status = GetHIInputIP (&LocalIp);\r
862 if (EFI_ERROR(Status)) {\r
863 return EFI_ABORTED;\r
864 }\r
865 }\r
866\r
867 Print(L"Get the TFTP server IP address: ");\r
868 Status = GetHIInputIP (&RemoteIp);\r
869 if (EFI_ERROR(Status)) {\r
870 return EFI_ABORTED;\r
871 }\r
872\r
22a262c8 873 Print(L"File path of the %s : ", FileName);\r
74b96132 874 Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
ea46ebbe 875 if (EFI_ERROR(Status)) {\r
876 return EFI_ABORTED;\r
877 }\r
878\r
ea46ebbe 879 BootFilePathSize = StrSize(BootFilePath);\r
74b96132 880 if (BootFilePathSize == 2) {\r
881 return EFI_NOT_FOUND;\r
882 }\r
ea46ebbe 883\r
884 // Allocate the memory for the IPv4 + File Path Device Path Nodes\r
ecc62d13 885 IPv4DevicePathNode = (IPv4_DEVICE_PATH*)AllocatePool(sizeof(IPv4_DEVICE_PATH) + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH);\r
ea46ebbe 886\r
887 // Create the IPv4 Device Path\r
888 IPv4DevicePathNode->Header.Type = MESSAGING_DEVICE_PATH;\r
889 IPv4DevicePathNode->Header.SubType = MSG_IPv4_DP;\r
890 SetDevicePathNodeLength (&IPv4DevicePathNode->Header, sizeof(IPv4_DEVICE_PATH));\r
891 CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
892 CopyMem (&IPv4DevicePathNode->RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
893 IPv4DevicePathNode->LocalPort = 0;\r
894 IPv4DevicePathNode->RemotePort = 0;\r
895 IPv4DevicePathNode->Protocol = EFI_IP_PROTO_TCP;\r
896 IPv4DevicePathNode->StaticIpAddress = (IsDHCP != TRUE);\r
897\r
898 // Create the FilePath Device Path node\r
899 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);\r
900 FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;\r
901 FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;\r
902 SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
903 CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);\r
ea46ebbe 904\r
ecc62d13 905 // Set the End Device Path Node\r
906 SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize));\r
55a9f75d 907 *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode;\r
ea46ebbe 908\r
909 return Status;\r
910}\r
911\r
912EFI_STATUS\r
913BdsLoadOptionTftpUpdateDevicePath (\r
22a262c8 914 IN EFI_DEVICE_PATH *OldDevicePath,\r
915 IN CHAR16* FileName,\r
916 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
55a9f75d 917 OUT BOOLEAN *RequestBootType\r
ea46ebbe 918 )\r
919{\r
920 ASSERT (0);\r
55a9f75d 921 return EFI_UNSUPPORTED;\r
ea46ebbe 922}\r
923\r
924BOOLEAN\r
925BdsLoadOptionTftpIsSupported (\r
22a262c8 926 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 927 )\r
928{\r
929 EFI_STATUS Status;\r
930 EFI_HANDLE Handle;\r
931 EFI_DEVICE_PATH *RemainingDevicePath;\r
932 EFI_DEVICE_PATH *NextDevicePath;\r
933 EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol;\r
934\r
22a262c8 935 Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
ea46ebbe 936 if (EFI_ERROR(Status)) {\r
937 return FALSE;\r
938 }\r
939\r
940 // Validate the Remaining Device Path\r
941 if (IsDevicePathEnd(RemainingDevicePath)) {\r
942 return FALSE;\r
943 }\r
944 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) &&\r
945 !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) {\r
946 return FALSE;\r
947 }\r
948 NextDevicePath = NextDevicePathNode (RemainingDevicePath);\r
949 if (IsDevicePathEnd(NextDevicePath)) {\r
950 return FALSE;\r
951 }\r
952 if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) {\r
953 return FALSE;\r
954 }\r
955\r
956 Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
957 if (EFI_ERROR (Status)) {\r
958 return FALSE;\r
959 } else {\r
960 return TRUE;\r
961 }\r
962}\r