]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BootOptionSupport.c
ArmPlatformPkg/LcdGraphicsOutputDxe: Added support for ARM HDLCD controller
[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
37 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,\r
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
64 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,\r
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
91 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,\r
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
118 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,\r
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
335 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,\r
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
656416bc 353 *DevicePathNode = NULL;\r
354 return EFI_NOT_FOUND;\r
355 }\r
356\r
ea46ebbe 357 // Create the FilePath Device Path node\r
358 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
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
ea46ebbe 363\r
656416bc 364 if (BootType != NULL || Attributes != NULL) {\r
365 Status = BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes);\r
366 }\r
367\r
ea46ebbe 368 if (EFI_ERROR(Status)) {\r
369 FreePool (FilePathDevicePath);\r
370 } else {\r
371 *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath;\r
372 }\r
373\r
374 return Status;\r
375}\r
376\r
377EFI_STATUS\r
378BdsLoadOptionFileSystemUpdateDevicePath (\r
22a262c8 379 IN EFI_DEVICE_PATH *OldDevicePath,\r
380 IN CHAR16* FileName,\r
381 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
382 OUT ARM_BDS_LOADER_TYPE *BootType,\r
383 OUT UINT32 *Attributes\r
ea46ebbe 384 )\r
385{\r
386 EFI_STATUS Status;\r
74b96132 387 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
ea46ebbe 388 UINTN BootFilePathSize;\r
389 FILEPATH_DEVICE_PATH* EndingDevicePath;\r
390 FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
391 EFI_DEVICE_PATH* DevicePath;\r
392\r
656416bc 393 DevicePath = DuplicateDevicePath(OldDevicePath);\r
ea46ebbe 394\r
656416bc 395 EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath);\r
396 \r
22a262c8 397 Print(L"File path of the %s: ", FileName);\r
74b96132 398 StrnCpy (BootFilePath, EndingDevicePath->PathName, BOOT_DEVICE_FILEPATH_MAX);\r
399 Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
ea46ebbe 400 if (EFI_ERROR(Status)) {\r
401 return Status;\r
402 }\r
403\r
74b96132 404 BootFilePathSize = StrSize(BootFilePath);\r
405 if (BootFilePathSize == 2) {\r
656416bc 406 *NewDevicePath = NULL;\r
407 return EFI_NOT_FOUND;\r
408 }\r
409\r
ea46ebbe 410 // Create the FilePath Device Path node\r
411 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
412 FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;\r
413 FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;\r
414 SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
415 CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);\r
ea46ebbe 416\r
417 // Generate the new Device Path by replacing the last node by the updated node\r
418 SetDevicePathEndNode (EndingDevicePath);\r
419 *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath);\r
420 FreePool(DevicePath);\r
421\r
656416bc 422 if (BootType != NULL || Attributes != NULL) {\r
423 return BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes);\r
424 }\r
425\r
426 return EFI_SUCCESS;\r
ea46ebbe 427}\r
428\r
429BOOLEAN\r
430BdsLoadOptionFileSystemIsSupported (\r
22a262c8 431 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 432 )\r
433{\r
434 EFI_DEVICE_PATH* DevicePathNode;\r
435\r
22a262c8 436 DevicePathNode = GetLastDevicePathNode (DevicePath);\r
ea46ebbe 437\r
438 return IS_DEVICE_PATH_NODE(DevicePathNode,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP);\r
439}\r
440\r
441STATIC\r
442BOOLEAN\r
443IsParentDevicePath (\r
444 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
445 IN EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath\r
446 )\r
447{\r
448 UINTN ParentSize;\r
449 UINTN ChildSize;\r
450\r
451 ParentSize = GetDevicePathSize (ParentDevicePath);\r
452 ChildSize = GetDevicePathSize (ChildDevicePath);\r
453\r
454 if (ParentSize > ChildSize) {\r
455 return FALSE;\r
456 }\r
457\r
458 if (CompareMem (ParentDevicePath, ChildDevicePath, ParentSize - END_DEVICE_PATH_LENGTH) != 0) {\r
459 return FALSE;\r
460 }\r
461\r
462 return TRUE;\r
463}\r
464\r
465EFI_STATUS\r
466BdsLoadOptionMemMapList (\r
467 IN OUT LIST_ENTRY* BdsLoadOptionList\r
468 )\r
469{\r
470 EFI_STATUS Status;\r
471 UINTN HandleCount;\r
472 EFI_HANDLE *HandleBuffer;\r
473 UINTN DevicePathHandleCount;\r
474 EFI_HANDLE *DevicePathHandleBuffer;\r
475 BOOLEAN IsParent;\r
476 UINTN Index;\r
477 UINTN Index2;\r
478 BDS_SUPPORTED_DEVICE *SupportedDevice;\r
479 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
480 EFI_DEVICE_PATH* DevicePath;\r
481\r
482 // List all the BlockIo Protocols\r
483 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
484 if (EFI_ERROR (Status)) {\r
485 return Status;\r
486 }\r
487\r
488 for (Index = 0; Index < HandleCount; Index++) {\r
489 // We only select the handle WITH a Device Path AND not part of Media (to avoid duplication with HardDisk, CDROM, etc)\r
490 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
491 if (!EFI_ERROR(Status)) {\r
492 // BlockIo is not part of Media Device Path\r
493 DevicePath = DevicePathProtocol;\r
494 while (!IsDevicePathEndType (DevicePath) && (DevicePathType (DevicePath) != MEDIA_DEVICE_PATH)) {\r
495 DevicePath = NextDevicePathNode (DevicePath);\r
496 }\r
497 if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {\r
498 continue;\r
499 }\r
500\r
501 // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child\r
502 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &DevicePathHandleCount, &DevicePathHandleBuffer);\r
503 ASSERT_EFI_ERROR (Status);\r
504 IsParent = FALSE;\r
505 for (Index2 = 0; (Index2 < DevicePathHandleCount) && !IsParent; Index2++) {\r
506 if (HandleBuffer[Index] != DevicePathHandleBuffer[Index2]) {\r
507 gBS->HandleProtocol (DevicePathHandleBuffer[Index2], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);\r
508 if (IsParentDevicePath (DevicePathProtocol, DevicePath)) {\r
509 IsParent = TRUE;\r
510 }\r
511 }\r
512 }\r
513 if (IsParent) {\r
514 continue;\r
515 }\r
516\r
517 // Allocate BDS Supported Device structure\r
518 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
519\r
520 Status = GenerateDeviceDescriptionName (HandleBuffer[Index], SupportedDevice->Description);\r
521 ASSERT_EFI_ERROR (Status);\r
522\r
523 SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
524 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_MEMMAP];\r
525\r
526 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
527 }\r
528 }\r
529\r
530 return EFI_SUCCESS;\r
531}\r
532\r
533EFI_STATUS\r
534BdsLoadOptionMemMapCreateDevicePath (\r
22a262c8 535 IN CHAR16* FileName,\r
536 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,\r
537 OUT ARM_BDS_LOADER_TYPE *BootType,\r
538 OUT UINT32 *Attributes\r
ea46ebbe 539 )\r
540{\r
22a262c8 541 EFI_STATUS Status;\r
542 MEMMAP_DEVICE_PATH *MemMapDevicePath;\r
543 CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
544 CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
ea46ebbe 545\r
22a262c8 546 Print(L"Starting Address of the %s: ", FileName);\r
547 Status = GetHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
ea46ebbe 548 if (EFI_ERROR(Status)) {\r
549 return EFI_ABORTED;\r
550 }\r
551\r
22a262c8 552 Print(L"Ending Address of the %s: ", FileName);\r
553 Status = GetHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
ea46ebbe 554 if (EFI_ERROR(Status)) {\r
555 return EFI_ABORTED;\r
556 }\r
557\r
558 // Create the MemMap Device Path Node\r
22a262c8 559 MemMapDevicePath = (MEMMAP_DEVICE_PATH*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH) + END_DEVICE_PATH_LENGTH);\r
ea46ebbe 560 MemMapDevicePath->Header.Type = HARDWARE_DEVICE_PATH;\r
561 MemMapDevicePath->Header.SubType = HW_MEMMAP_DP;\r
22a262c8 562 SetDevicePathNodeLength (MemMapDevicePath, sizeof(MEMMAP_DEVICE_PATH));\r
ea46ebbe 563 MemMapDevicePath->MemoryType = EfiBootServicesData;\r
74b96132 564 MemMapDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress);\r
565 MemMapDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress);\r
ea46ebbe 566\r
22a262c8 567 // Set a Device Path End Node after the Memory Map Device Path Node\r
568 SetDevicePathEndNode (MemMapDevicePath + 1);\r
569\r
570 if (BootType != NULL || Attributes != NULL) {\r
571 Status = BootDeviceGetType (NULL, BootType, Attributes);\r
572 }\r
573\r
ea46ebbe 574 if (EFI_ERROR(Status)) {\r
575 FreePool (MemMapDevicePath);\r
576 } else {\r
577 *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath;\r
578 }\r
579\r
580 return Status;\r
581}\r
582\r
583EFI_STATUS\r
584BdsLoadOptionMemMapUpdateDevicePath (\r
22a262c8 585 IN EFI_DEVICE_PATH *OldDevicePath,\r
586 IN CHAR16* FileName,\r
587 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
588 OUT ARM_BDS_LOADER_TYPE *BootType,\r
589 OUT UINT32 *Attributes\r
ea46ebbe 590 )\r
591{\r
6bab33c7 592 EFI_STATUS Status;\r
74b96132 593 CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
594 CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
6bab33c7 595 MEMMAP_DEVICE_PATH* EndingDevicePath;\r
596 EFI_DEVICE_PATH* DevicePath;\r
597\r
656416bc 598 DevicePath = DuplicateDevicePath (OldDevicePath);\r
6bab33c7 599 EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath);\r
600\r
22a262c8 601 Print(L"Starting Address of the %s: ", FileName);\r
74b96132 602 UnicodeSPrint (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->StartingAddress);\r
603 Status = EditHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
6bab33c7 604 if (EFI_ERROR(Status)) {\r
605 return EFI_ABORTED;\r
606 }\r
607\r
22a262c8 608 Print(L"Ending Address of the %s: ", FileName);\r
74b96132 609 UnicodeSPrint (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->EndingAddress);\r
610 Status = EditHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
6bab33c7 611 if (EFI_ERROR(Status)) {\r
612 return EFI_ABORTED;\r
613 }\r
614\r
74b96132 615 EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress);\r
616 EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress);\r
6bab33c7 617\r
22a262c8 618 if (BootType != NULL || Attributes != NULL) {\r
619 Status = BootDeviceGetType (NULL, BootType, Attributes);\r
620 }\r
621\r
6bab33c7 622 if (EFI_ERROR(Status)) {\r
623 FreePool(DevicePath);\r
624 } else {\r
625 *NewDevicePath = DevicePath;\r
626 }\r
627\r
628 return Status;\r
ea46ebbe 629}\r
630\r
631BOOLEAN\r
632BdsLoadOptionMemMapIsSupported (\r
22a262c8 633 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 634 )\r
635{\r
636 EFI_DEVICE_PATH* DevicePathNode;\r
637\r
22a262c8 638 DevicePathNode = GetLastDevicePathNode (DevicePath);\r
ea46ebbe 639\r
640 return IS_DEVICE_PATH_NODE(DevicePathNode,HARDWARE_DEVICE_PATH,HW_MEMMAP_DP);\r
641}\r
642\r
643EFI_STATUS\r
644BdsLoadOptionPxeList (\r
645 IN OUT LIST_ENTRY* BdsLoadOptionList\r
646 )\r
647{\r
648 EFI_STATUS Status;\r
649 UINTN HandleCount;\r
650 EFI_HANDLE *HandleBuffer;\r
651 UINTN Index;\r
652 BDS_SUPPORTED_DEVICE *SupportedDevice;\r
653 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
654 EFI_SIMPLE_NETWORK_PROTOCOL* SimpleNet;\r
655 CHAR16 DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
656 EFI_MAC_ADDRESS *Mac;\r
657\r
658 // List all the PXE Protocols\r
659 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
660 if (EFI_ERROR (Status)) {\r
661 return Status;\r
662 }\r
663\r
664 for (Index = 0; Index < HandleCount; Index++) {\r
665 // We only select the handle WITH a Device Path AND the PXE Protocol\r
666 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
667 if (!EFI_ERROR(Status)) {\r
668 // Allocate BDS Supported Device structure\r
669 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
670\r
671 Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet);\r
672 if (!EFI_ERROR(Status)) {\r
673 Mac = &SimpleNet->Mode->CurrentAddress;\r
674 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
675 } else {\r
676 Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);\r
677 ASSERT_EFI_ERROR (Status);\r
678 }\r
679 UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"PXE on %s",DeviceDescription);\r
680\r
681 SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
682 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_PXE];\r
683\r
684 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
685 }\r
686 }\r
687\r
688 return EFI_SUCCESS;\r
689}\r
690\r
691EFI_STATUS\r
692BdsLoadOptionPxeCreateDevicePath (\r
22a262c8 693 IN CHAR16* FileName,\r
694 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,\r
695 OUT ARM_BDS_LOADER_TYPE *BootType,\r
696 OUT UINT32 *Attributes\r
ea46ebbe 697 )\r
698{\r
699 *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
700 SetDevicePathEndNode (*DevicePathNode);\r
701 *BootType = BDS_LOADER_EFI_APPLICATION;\r
702 return EFI_SUCCESS;\r
703}\r
704\r
705EFI_STATUS\r
706BdsLoadOptionPxeUpdateDevicePath (\r
22a262c8 707 IN EFI_DEVICE_PATH *OldDevicePath,\r
708 IN CHAR16* FileName,\r
709 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
710 OUT ARM_BDS_LOADER_TYPE *BootType,\r
711 OUT UINT32 *Attributes\r
ea46ebbe 712 )\r
713{\r
714 ASSERT (0);\r
715 return EFI_SUCCESS;\r
716}\r
717\r
718BOOLEAN\r
719BdsLoadOptionPxeIsSupported (\r
22a262c8 720 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 721 )\r
722{\r
723 EFI_STATUS Status;\r
724 EFI_HANDLE Handle;\r
725 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
726 EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol;\r
727\r
22a262c8 728 Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
ea46ebbe 729 if (EFI_ERROR(Status)) {\r
730 return FALSE;\r
731 }\r
732\r
733 if (!IsDevicePathEnd(RemainingDevicePath)) {\r
734 return FALSE;\r
735 }\r
736\r
737 Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
738 if (EFI_ERROR (Status)) {\r
739 return FALSE;\r
740 } else {\r
741 return TRUE;\r
742 }\r
743}\r
744\r
745EFI_STATUS\r
746BdsLoadOptionTftpList (\r
747 IN OUT LIST_ENTRY* BdsLoadOptionList\r
748 )\r
749{\r
750 EFI_STATUS Status;\r
751 UINTN HandleCount;\r
752 EFI_HANDLE *HandleBuffer;\r
753 UINTN Index;\r
754 BDS_SUPPORTED_DEVICE *SupportedDevice;\r
755 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
756 EFI_SIMPLE_NETWORK_PROTOCOL* SimpleNet;\r
757 CHAR16 DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
758 EFI_MAC_ADDRESS *Mac;\r
759\r
760 // List all the PXE Protocols\r
761 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
762 if (EFI_ERROR (Status)) {\r
763 return Status;\r
764 }\r
765\r
766 for (Index = 0; Index < HandleCount; Index++) {\r
767 // 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
768 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
769 if (!EFI_ERROR(Status)) {\r
770 // Allocate BDS Supported Device structure\r
771 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
772\r
773 Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet);\r
774 if (!EFI_ERROR(Status)) {\r
775 Mac = &SimpleNet->Mode->CurrentAddress;\r
776 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
777 } else {\r
778 Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);\r
779 ASSERT_EFI_ERROR (Status);\r
780 }\r
781 UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"TFP on %s",DeviceDescription);\r
782\r
783 SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
784 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP];\r
785\r
786 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
787 }\r
788 }\r
789\r
790 return EFI_SUCCESS;\r
791}\r
792\r
793EFI_STATUS\r
794BdsLoadOptionTftpCreateDevicePath (\r
22a262c8 795 IN CHAR16* FileName,\r
796 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode,\r
797 OUT ARM_BDS_LOADER_TYPE *BootType,\r
798 OUT UINT32 *Attributes\r
ea46ebbe 799 )\r
800{\r
801 EFI_STATUS Status;\r
802 BOOLEAN IsDHCP;\r
803 EFI_IP_ADDRESS LocalIp;\r
804 EFI_IP_ADDRESS RemoteIp;\r
805 IPv4_DEVICE_PATH* IPv4DevicePathNode;\r
806 FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
74b96132 807 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
ea46ebbe 808 UINTN BootFilePathSize;\r
809\r
810 Print(L"Get the IP address from DHCP: ");\r
811 Status = GetHIInputBoolean (&IsDHCP);\r
812 if (EFI_ERROR(Status)) {\r
813 return EFI_ABORTED;\r
814 }\r
815\r
816 if (!IsDHCP) {\r
817 Print(L"Get the static IP address: ");\r
818 Status = GetHIInputIP (&LocalIp);\r
819 if (EFI_ERROR(Status)) {\r
820 return EFI_ABORTED;\r
821 }\r
822 }\r
823\r
824 Print(L"Get the TFTP server IP address: ");\r
825 Status = GetHIInputIP (&RemoteIp);\r
826 if (EFI_ERROR(Status)) {\r
827 return EFI_ABORTED;\r
828 }\r
829\r
22a262c8 830 Print(L"File path of the %s : ", FileName);\r
74b96132 831 Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
ea46ebbe 832 if (EFI_ERROR(Status)) {\r
833 return EFI_ABORTED;\r
834 }\r
835\r
ea46ebbe 836 BootFilePathSize = StrSize(BootFilePath);\r
74b96132 837 if (BootFilePathSize == 2) {\r
838 return EFI_NOT_FOUND;\r
839 }\r
ea46ebbe 840\r
841 // Allocate the memory for the IPv4 + File Path Device Path Nodes\r
842 IPv4DevicePathNode = (IPv4_DEVICE_PATH*)AllocatePool(sizeof(IPv4_DEVICE_PATH) + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
843\r
844 // Create the IPv4 Device Path\r
845 IPv4DevicePathNode->Header.Type = MESSAGING_DEVICE_PATH;\r
846 IPv4DevicePathNode->Header.SubType = MSG_IPv4_DP;\r
847 SetDevicePathNodeLength (&IPv4DevicePathNode->Header, sizeof(IPv4_DEVICE_PATH));\r
848 CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
849 CopyMem (&IPv4DevicePathNode->RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
850 IPv4DevicePathNode->LocalPort = 0;\r
851 IPv4DevicePathNode->RemotePort = 0;\r
852 IPv4DevicePathNode->Protocol = EFI_IP_PROTO_TCP;\r
853 IPv4DevicePathNode->StaticIpAddress = (IsDHCP != TRUE);\r
854\r
855 // Create the FilePath Device Path node\r
856 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);\r
857 FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;\r
858 FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;\r
859 SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
860 CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);\r
ea46ebbe 861\r
22a262c8 862 if (BootType != NULL || Attributes != NULL) {\r
863 Status = BootDeviceGetType (NULL, BootType, Attributes);\r
864 }\r
865\r
ea46ebbe 866 if (EFI_ERROR(Status)) {\r
867 FreePool (IPv4DevicePathNode);\r
868 } else {\r
869 *DevicePathNode = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode;\r
870 }\r
871\r
872 return Status;\r
873}\r
874\r
875EFI_STATUS\r
876BdsLoadOptionTftpUpdateDevicePath (\r
22a262c8 877 IN EFI_DEVICE_PATH *OldDevicePath,\r
878 IN CHAR16* FileName,\r
879 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath,\r
880 OUT ARM_BDS_LOADER_TYPE *BootType,\r
881 OUT UINT32 *Attributes\r
ea46ebbe 882 )\r
883{\r
884 ASSERT (0);\r
885 return EFI_SUCCESS;\r
886}\r
887\r
888BOOLEAN\r
889BdsLoadOptionTftpIsSupported (\r
22a262c8 890 IN EFI_DEVICE_PATH *DevicePath\r
ea46ebbe 891 )\r
892{\r
893 EFI_STATUS Status;\r
894 EFI_HANDLE Handle;\r
895 EFI_DEVICE_PATH *RemainingDevicePath;\r
896 EFI_DEVICE_PATH *NextDevicePath;\r
897 EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol;\r
898\r
22a262c8 899 Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
ea46ebbe 900 if (EFI_ERROR(Status)) {\r
901 return FALSE;\r
902 }\r
903\r
904 // Validate the Remaining Device Path\r
905 if (IsDevicePathEnd(RemainingDevicePath)) {\r
906 return FALSE;\r
907 }\r
908 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) &&\r
909 !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) {\r
910 return FALSE;\r
911 }\r
912 NextDevicePath = NextDevicePathNode (RemainingDevicePath);\r
913 if (IsDevicePathEnd(NextDevicePath)) {\r
914 return FALSE;\r
915 }\r
916 if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) {\r
917 return FALSE;\r
918 }\r
919\r
920 Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
921 if (EFI_ERROR (Status)) {\r
922 return FALSE;\r
923 } else {\r
924 return TRUE;\r
925 }\r
926}\r