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