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