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