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