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