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