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