1ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin/** @file
2ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*
355a9f75d149ea53d1c8b3da197ec344c2aedb848Olivier Martin*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
4ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*
5ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*  This program and the accompanying materials
6ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*  are licensed and made available under the terms and conditions of the BSD License
7ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*  which accompanies this distribution.  The full text of the license may be found at
8ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*  http://opensource.org/licenses/bsd-license.php
9ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*
10ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin*
13ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin**/
14ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
15ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#include "BdsInternal.h"
16ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
17ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#include <Library/NetLib.h>
18ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
19ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#include <Protocol/BlockIo.h>
20ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#include <Protocol/DevicePathToText.h>
213a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel#include <Protocol/FirmwareVolumeBlock.h>
22ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#include <Protocol/PxeBaseCode.h>
23ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#include <Protocol/SimpleFileSystem.h>
24ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#include <Protocol/SimpleNetwork.h>
25061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron#include <Protocol/Dhcp4.h>
26061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron#include <Protocol/Mtftp4.h>
27ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
28ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#include <Guid/FileSystemInfo.h>
29ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
30ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
31ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
32ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
33ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionFileSystemList (
34ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY* BdsLoadOptionList
35ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
36ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
37ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
38ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionFileSystemCreateDevicePath (
3922a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
40889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes
41ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
42ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
43ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
44ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionFileSystemUpdateDevicePath (
4522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN EFI_DEVICE_PATH            *OldDevicePath,
4622a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
47889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
48ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
49ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
50ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
51ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionFileSystemIsSupported (
5222a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN  EFI_DEVICE_PATH           *DevicePath
53ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
54ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
55ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
56ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionMemMapList (
57ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY* BdsLoadOptionList
58ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
59ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
60ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
61ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionMemMapCreateDevicePath (
6222a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
63889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes
64ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
65ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
66ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
67ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionMemMapUpdateDevicePath (
6822a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN EFI_DEVICE_PATH            *OldDevicePath,
6922a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
70889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
71ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
72ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
73ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
74ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionMemMapIsSupported (
7522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN  EFI_DEVICE_PATH           *DevicePath
76ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
77ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
78ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
79ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionPxeList (
80ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY* BdsLoadOptionList
81ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
82ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
83ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
84ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionPxeCreateDevicePath (
8522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
86889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes
87ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
88ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
89ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
90ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionPxeUpdateDevicePath (
9122a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN EFI_DEVICE_PATH            *OldDevicePath,
9222a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
93889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
94ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
95ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
96ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
97ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionPxeIsSupported (
9822a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN  EFI_DEVICE_PATH           *DevicePath
99ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
100ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
101ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
102ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionTftpList (
103ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY* BdsLoadOptionList
104ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
105ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
106ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
107ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionTftpCreateDevicePath (
10822a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
109889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes
110ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
111ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
112ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
113ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionTftpUpdateDevicePath (
11422a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN EFI_DEVICE_PATH            *OldDevicePath,
11522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
116889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
117ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
118ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
119ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
120ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionTftpIsSupported (
12122a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN  EFI_DEVICE_PATH           *DevicePath
122ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  );
123ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
124ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList[] = {
1252ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin  {
1262ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BDS_DEVICE_FILESYSTEM,
1272ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionFileSystemList,
1282ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionFileSystemIsSupported,
1292ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionFileSystemCreateDevicePath,
130889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron    BdsLoadOptionFileSystemUpdateDevicePath,
131889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron    TRUE
1322ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin  },
1332ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin  {
1342ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BDS_DEVICE_MEMMAP,
1352ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionMemMapList,
1362ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionMemMapIsSupported,
1372ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionMemMapCreateDevicePath,
138889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron    BdsLoadOptionMemMapUpdateDevicePath,
139889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron    TRUE
1402ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin  },
1412ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin  {
1422ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BDS_DEVICE_PXE,
1432ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionPxeList,
1442ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionPxeIsSupported,
1452ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionPxeCreateDevicePath,
146889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron    BdsLoadOptionPxeUpdateDevicePath,
147889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron    FALSE
1482ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin  },
1492ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin  {
1502ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BDS_DEVICE_TFTP,
1512ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionTftpList,
1522ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionTftpIsSupported,
1532ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionTftpCreateDevicePath,
154889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron    BdsLoadOptionTftpUpdateDevicePath,
155889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron    TRUE
1562ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin  }
157ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin};
158ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
159ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
160ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBootDeviceListSupportedInit (
161ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY *SupportedDeviceList
162ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
163ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
164ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN   Index;
165ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
166ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Initialize list of supported devices
167ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  InitializeListHead (SupportedDeviceList);
168ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
169ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  for (Index = 0; Index < BDS_DEVICE_MAX; Index++) {
1702ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin    BdsLoadOptionSupportList[Index].ListDevices (SupportedDeviceList);
171ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
172ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
173ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return EFI_SUCCESS;
174ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
175ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
176ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
177ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBootDeviceListSupportedFree (
178656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin  IN LIST_ENTRY *SupportedDeviceList,
179656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin  IN BDS_SUPPORTED_DEVICE *Except
180ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
181ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
182ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  LIST_ENTRY  *Entry;
183ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  BDS_SUPPORTED_DEVICE* SupportedDevice;
184ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
185ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  Entry = GetFirstNode (SupportedDeviceList);
186ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  while (Entry != SupportedDeviceList) {
187ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    SupportedDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);
188ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    Entry = RemoveEntryList (Entry);
189656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin    if (SupportedDevice != Except) {
1902ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin      FreePool (SupportedDevice);
191656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin    }
192ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
193ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
194ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return EFI_SUCCESS;
195ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
196ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
197ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
198ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBootDeviceGetDeviceSupport (
19922a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN  EFI_DEVICE_PATH           *DevicePath,
20022a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  OUT BDS_LOAD_OPTION_SUPPORT   **DeviceSupport
201ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
202ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
203ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN Index;
204ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
205ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Find which supported device is the most appropriate
206ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  for (Index = 0; Index < BDS_DEVICE_MAX; Index++) {
20722a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin    if (BdsLoadOptionSupportList[Index].IsSupported (DevicePath)) {
208ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      *DeviceSupport = &BdsLoadOptionSupportList[Index];
209ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      return EFI_SUCCESS;
210ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    }
211ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
212ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
213ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return EFI_UNSUPPORTED;
214ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
215ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
216ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
217ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionFileSystemList (
218ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY* BdsLoadOptionList
219ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
220ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
221ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_STATUS                        Status;
222ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN                             HandleCount;
223ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_HANDLE                        *HandleBuffer;
224ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN                             Index;
225ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  BDS_SUPPORTED_DEVICE              *SupportedDevice;
226ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL*  FileProtocol;
227ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_FILE_HANDLE                   Fs;
228ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN                             Size;
229ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_FILE_SYSTEM_INFO*             FsInfo;
230ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_DEVICE_PATH_PROTOCOL*         DevicePathProtocol;
231ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
232ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // List all the Simple File System Protocols
233ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &HandleBuffer);
234ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR (Status)) {
235ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return Status;
236ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
237ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
238ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  for (Index = 0; Index < HandleCount; Index++) {
239ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
240ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    if (!EFI_ERROR(Status)) {
241ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      // Allocate BDS Supported Device structure
2422ccfb71ebebd54c57aad8f9bb5fb20539e7b892foliviermartin      SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof(BDS_SUPPORTED_DEVICE));
243ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
244ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      FileProtocol = NULL;
245ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FileProtocol);
246ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      ASSERT_EFI_ERROR(Status);
247ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
248ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      FileProtocol->OpenVolume (FileProtocol, &Fs);
249ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
250ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      // Generate a Description from the file system
251ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      Size = 0;
252ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      FsInfo = NULL;
253ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      Status = Fs->GetInfo (Fs, &gEfiFileSystemInfoGuid, &Size, FsInfo);
254ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      if (Status == EFI_BUFFER_TOO_SMALL) {
255ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        FsInfo = AllocatePool (Size);
256ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        Status = Fs->GetInfo (Fs, &gEfiFileSystemInfoGuid, &Size, FsInfo);
257ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      }
258ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"%s (%d MB)",FsInfo->VolumeLabel,(UINT32)(FsInfo->VolumeSize / (1024 * 1024)));
259ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      FreePool(FsInfo);
260ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      Fs->Close (Fs);
261ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
262ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      SupportedDevice->DevicePathProtocol = DevicePathProtocol;
263ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_FILESYSTEM];
264ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
265ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);
266ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    }
267ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
268ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
269ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return EFI_SUCCESS;
270ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
271ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
272ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
273ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionFileSystemCreateDevicePath (
27422a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
275889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes
276ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
277ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
278ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_STATUS  Status;
279ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FILEPATH_DEVICE_PATH* FilePathDevicePath;
28074b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  CHAR16      BootFilePath[BOOT_DEVICE_FILEPATH_MAX];
281ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN       BootFilePathSize;
282ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
28322a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Print(L"File path of the %s: ", FileName);
28474b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);
285ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR(Status)) {
286ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return EFI_ABORTED;
287ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
288ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
28974b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  BootFilePathSize = StrSize (BootFilePath);
29074b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  if (BootFilePathSize == 2) {
291ecc62d1390402ea99a807679372c955286e295e0oliviermartin    *DevicePathNodes = NULL;
292656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin    return EFI_NOT_FOUND;
293656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin  }
294656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin
295ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Create the FilePath Device Path node
296ecc62d1390402ea99a807679372c955286e295e0oliviermartin  FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH);
297ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;
298ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;
299ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);
300ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);
301ecc62d1390402ea99a807679372c955286e295e0oliviermartin  SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize));
30255a9f75d149ea53d1c8b3da197ec344c2aedb848Olivier Martin  *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath;
303ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
304ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return Status;
305ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
306ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
307ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
308ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionFileSystemUpdateDevicePath (
30922a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN EFI_DEVICE_PATH            *OldDevicePath,
31022a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
311889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
312ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
313ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
314ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_STATUS  Status;
31574b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  CHAR16      BootFilePath[BOOT_DEVICE_FILEPATH_MAX];
316ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN       BootFilePathSize;
317ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FILEPATH_DEVICE_PATH* EndingDevicePath;
318ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FILEPATH_DEVICE_PATH* FilePathDevicePath;
319ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_DEVICE_PATH*  DevicePath;
320ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
3210db25ccc6cf1d05dc6b8fd9b07d033b40c387c88oliviermartin  DevicePath = DuplicateDevicePath (OldDevicePath);
322ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
323656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin  EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath);
3243402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
32522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Print(L"File path of the %s: ", FileName);
32674b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  StrnCpy (BootFilePath, EndingDevicePath->PathName, BOOT_DEVICE_FILEPATH_MAX);
32774b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);
328ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR(Status)) {
329ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return Status;
330ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
331ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
33274b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  BootFilePathSize = StrSize(BootFilePath);
33374b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  if (BootFilePathSize == 2) {
334656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin    *NewDevicePath = NULL;
335656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin    return EFI_NOT_FOUND;
336656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin  }
337656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin
338ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Create the FilePath Device Path node
339ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);
340ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;
341ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;
342ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);
343ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);
344ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
345ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Generate the new Device Path by replacing the last node by the updated node
346ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  SetDevicePathEndNode (EndingDevicePath);
347ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath);
348ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FreePool(DevicePath);
349ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
350656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin  return EFI_SUCCESS;
351ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
352ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
35322a50a13e555102e1751c2f6665eb67855b43473Ronald Cron/**
35422a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  Check if a boot option path is a file system boot option path or not.
35522a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
35622a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  The device specified by the beginning of the path has to support the Simple File
35722a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  System protocol. Furthermore, the remaining part of the path has to be composed of
35822a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  a single node of type MEDIA_DEVICE_PATH and sub-type MEDIA_FILEPATH_DP.
35922a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
36022a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  @param[in]  DevicePath  Complete device path of a boot option.
36122a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
36222a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  @retval  FALSE  The boot option path has not been identified as that of a
36322a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                  file system boot option.
36422a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  @retval  TRUE   The boot option path is a file system boot option.
36522a50a13e555102e1751c2f6665eb67855b43473Ronald Cron**/
366ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
367ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionFileSystemIsSupported (
36822a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  IN  EFI_DEVICE_PATH  *DevicePath
369ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
370ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
37122a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  EFI_STATUS                        Status;
37222a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  EFI_HANDLE                        Handle;
37322a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  EFI_DEVICE_PATH                  *RemainingDevicePath;
37422a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *FileProtocol;
375ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
37622a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);
37722a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  if (EFI_ERROR (Status)) {
37822a50a13e555102e1751c2f6665eb67855b43473Ronald Cron    return FALSE;
37922a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  }
38022a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
38122a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  Status = gBS->HandleProtocol (
38222a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                   Handle,
38322a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                   &gEfiSimpleFileSystemProtocolGuid,
38422a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                   (VOID **)(&FileProtocol)
38522a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                   );
38622a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  if (EFI_ERROR (Status)) {
38722a50a13e555102e1751c2f6665eb67855b43473Ronald Cron    return FALSE;
38822a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  }
389ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
39022a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP))
39122a50a13e555102e1751c2f6665eb67855b43473Ronald Cron    return FALSE;
39222a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
39322a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  return TRUE;
394ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
395ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
396ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinSTATIC
397ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
398ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinIsParentDevicePath (
399ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
400ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath
401ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
402ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
403ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN ParentSize;
404ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN ChildSize;
405ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
406ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  ParentSize = GetDevicePathSize (ParentDevicePath);
407ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  ChildSize = GetDevicePathSize (ChildDevicePath);
408ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
409ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (ParentSize > ChildSize) {
410ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
411ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
412ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
413ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (CompareMem (ParentDevicePath, ChildDevicePath, ParentSize - END_DEVICE_PATH_LENGTH) != 0) {
414ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
415ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
416ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
417ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return TRUE;
418ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
419ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
420ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
421ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionMemMapList (
422ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY* BdsLoadOptionList
423ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
424ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
4253a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  EFI_STATUS                          Status;
4263a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  UINTN                               HandleCount;
4273a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  EFI_HANDLE                         *HandleBuffer;
4283a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  UINTN                               DevicePathHandleCount;
4293a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  EFI_HANDLE                         *DevicePathHandleBuffer;
4303a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  BOOLEAN                             IsParent;
4313a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  UINTN                               Index;
4323a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  UINTN                               Index2;
4333a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  BDS_SUPPORTED_DEVICE               *SupportedDevice;
4343a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  EFI_DEVICE_PATH_PROTOCOL*           DevicePathProtocol;
4353a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  EFI_DEVICE_PATH*                    DevicePath;
4363a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL    *FileProtocol;
4373a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
438ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
439ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // List all the BlockIo Protocols
440ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
441ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR (Status)) {
442ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return Status;
443ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
444ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
445ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  for (Index = 0; Index < HandleCount; Index++) {
4463a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    // We only select handles WITH a Device Path AND not part of Media (to
4473a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    // avoid duplication with HardDisk, CDROM, etc). Skip handles used by
4483a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    // Simple Filesystem or used for Variable Storage.
4493a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel
4503a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel
4513a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    Status = gBS->HandleProtocol (HandleBuffer[Index],
4523a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel                                  &gEfiSimpleFileSystemProtocolGuid,
4533a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel                                  (VOID *)&FileProtocol);
4543a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    if (!EFI_ERROR(Status)) {
4553a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel      // SimpleFilesystem supported on this handle, skip
4563a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel      continue;
4573a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    }
4583a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel
4593a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    Status = gBS->HandleProtocol (HandleBuffer[Index],
4603a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel                                  &gEfiFirmwareVolumeBlockProtocolGuid,
4613a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel                                  (VOID *)&FvbProtocol);
4623a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    if (!EFI_ERROR(Status)) {
4633a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel      // Firmware Volme Block / Variable storage supported on this handle, skip
4643a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel      continue;
4653a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    }
4663a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel
4673a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    Status = gBS->HandleProtocol (HandleBuffer[Index],
4683a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel                                  &gEfiFirmwareVolumeBlock2ProtocolGuid,
4693a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel                                  (VOID *)&FvbProtocol);
4703a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    if (!EFI_ERROR(Status)) {
4713a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel      // Firmware Volme Block / Variable storage supported on this handle, skip
4723a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel      continue;
4733a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel    }
4743a0e4800a328f5d7893e080f65edcc6bd0bc07e5Harry Liebel
475ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
476ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    if (!EFI_ERROR(Status)) {
477ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      // BlockIo is not part of Media Device Path
478ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      DevicePath = DevicePathProtocol;
479ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      while (!IsDevicePathEndType (DevicePath) && (DevicePathType (DevicePath) != MEDIA_DEVICE_PATH)) {
480ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        DevicePath = NextDevicePathNode (DevicePath);
481ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      }
482ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {
483ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        continue;
484ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      }
485ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
486ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child
487ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &DevicePathHandleCount, &DevicePathHandleBuffer);
488ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      ASSERT_EFI_ERROR (Status);
489ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      IsParent = FALSE;
490ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      for (Index2 = 0; (Index2 < DevicePathHandleCount) && !IsParent; Index2++) {
491ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        if (HandleBuffer[Index] != DevicePathHandleBuffer[Index2]) {
492ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin          gBS->HandleProtocol (DevicePathHandleBuffer[Index2], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
493ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin          if (IsParentDevicePath (DevicePathProtocol, DevicePath)) {
494ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin            IsParent = TRUE;
495ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin          }
496ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        }
497ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      }
498ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      if (IsParent) {
499ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        continue;
500ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      }
501ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
502ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      // Allocate BDS Supported Device structure
503ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));
504ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
505ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      Status = GenerateDeviceDescriptionName (HandleBuffer[Index], SupportedDevice->Description);
506ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      ASSERT_EFI_ERROR (Status);
507ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
508ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      SupportedDevice->DevicePathProtocol = DevicePathProtocol;
509ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_MEMMAP];
510ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
511ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);
512ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    }
513ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
514ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
515ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return EFI_SUCCESS;
516ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
517ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
518ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
519ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionMemMapCreateDevicePath (
52022a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
521889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes
522ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
523ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
52422a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  EFI_STATUS              Status;
52522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  MEMMAP_DEVICE_PATH      *MemMapDevicePath;
52622a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  CHAR16                  StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX];
52722a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  CHAR16                  StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX];
528ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
52922a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Print(L"Starting Address of the %s: ", FileName);
53022a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Status = GetHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX);
531ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR(Status)) {
532ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return EFI_ABORTED;
533ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
534ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
53522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Print(L"Ending Address of the %s: ", FileName);
53622a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Status = GetHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX);
537ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR(Status)) {
538ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return EFI_ABORTED;
539ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
540ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
541ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Create the MemMap Device Path Node
54222a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  MemMapDevicePath = (MEMMAP_DEVICE_PATH*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH) + END_DEVICE_PATH_LENGTH);
543ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  MemMapDevicePath->Header.Type = HARDWARE_DEVICE_PATH;
544ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  MemMapDevicePath->Header.SubType = HW_MEMMAP_DP;
54522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  SetDevicePathNodeLength (MemMapDevicePath, sizeof(MEMMAP_DEVICE_PATH));
546ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  MemMapDevicePath->MemoryType = EfiBootServicesData;
54774b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  MemMapDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress);
54874b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  MemMapDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress);
549ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
55022a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  // Set a Device Path End Node after the Memory Map Device Path Node
55122a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  SetDevicePathEndNode (MemMapDevicePath + 1);
55255a9f75d149ea53d1c8b3da197ec344c2aedb848Olivier Martin  *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath;
553ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
554ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return Status;
555ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
556ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
557ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
558ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionMemMapUpdateDevicePath (
55922a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN EFI_DEVICE_PATH            *OldDevicePath,
56022a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
561889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
562ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
563ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
5646bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  EFI_STATUS          Status;
56574b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  CHAR16              StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX];
56674b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  CHAR16              StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX];
5676bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  MEMMAP_DEVICE_PATH* EndingDevicePath;
5686bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  EFI_DEVICE_PATH*    DevicePath;
5696bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin
570656416bc2ee1409492343cde3f27ce717e90fdf7oliviermartin  DevicePath = DuplicateDevicePath (OldDevicePath);
5716bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath);
5726bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin
57322a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Print(L"Starting Address of the %s: ", FileName);
57474b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  UnicodeSPrint (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->StartingAddress);
57574b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  Status = EditHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX);
5766bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  if (EFI_ERROR(Status)) {
5776bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin    return EFI_ABORTED;
5786bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  }
5796bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin
58022a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Print(L"Ending Address of the %s: ", FileName);
58174b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  UnicodeSPrint (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->EndingAddress);
58274b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  Status = EditHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX);
5836bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  if (EFI_ERROR(Status)) {
5846bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin    return EFI_ABORTED;
5856bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  }
5866bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin
58774b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress);
58874b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress);
5896bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin
5906bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  if (EFI_ERROR(Status)) {
5916bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin    FreePool(DevicePath);
5926bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  } else {
5936bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin    *NewDevicePath = DevicePath;
5946bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  }
5956bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin
5966bab33c7b677dea7a67df512ef1a058daeebef57oliviermartin  return Status;
597ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
598ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
59922a50a13e555102e1751c2f6665eb67855b43473Ronald Cron/**
60022a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  Check if a boot option path is a memory map boot option path or not.
60122a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
60222a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  The device specified by the beginning of the path has to support the BlockIo
60322a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  protocol. Furthermore, the remaining part of the path has to be composed of
60422a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  a single node of type HARDWARE_DEVICE_PATH and sub-type HW_MEMMAP_DP.
60522a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
60622a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  @param[in]  DevicePath  Complete device path of a boot option.
60722a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
60822a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  @retval  FALSE  The boot option path has not been identified as that of a
60922a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                  memory map boot option.
61022a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  @retval  TRUE   The boot option path is a a memory map boot option.
61122a50a13e555102e1751c2f6665eb67855b43473Ronald Cron**/
612ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
613ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionMemMapIsSupported (
61422a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  IN  EFI_DEVICE_PATH  *DevicePath
615ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
616ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
61722a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  EFI_STATUS              Status;
61822a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  EFI_HANDLE              Handle;
61922a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  EFI_DEVICE_PATH        *RemainingDevicePath;
62022a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  EFI_BLOCK_IO_PROTOCOL  *BlockIoProtocol;
62122a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
62222a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);
62322a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  if (EFI_ERROR (Status)) {
62422a50a13e555102e1751c2f6665eb67855b43473Ronald Cron    return FALSE;
62522a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  }
626ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
62722a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  Status = gBS->HandleProtocol (
62822a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                  Handle,
62922a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                  &gEfiBlockIoProtocolGuid,
63022a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                  (VOID **)(&BlockIoProtocol)
63122a50a13e555102e1751c2f6665eb67855b43473Ronald Cron                  );
63222a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  if (EFI_ERROR (Status)) {
63322a50a13e555102e1751c2f6665eb67855b43473Ronald Cron    return FALSE;
63422a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  }
635ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
63622a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP))
63722a50a13e555102e1751c2f6665eb67855b43473Ronald Cron    return FALSE;
63822a50a13e555102e1751c2f6665eb67855b43473Ronald Cron
63922a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  return TRUE;
640ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
641ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
642ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
643ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionPxeList (
644ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY* BdsLoadOptionList
645ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
646ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
647ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_STATUS                        Status;
648ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN                             HandleCount;
649ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_HANDLE                        *HandleBuffer;
650ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  UINTN                             Index;
651ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  BDS_SUPPORTED_DEVICE              *SupportedDevice;
652ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_DEVICE_PATH_PROTOCOL*         DevicePathProtocol;
653ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_SIMPLE_NETWORK_PROTOCOL*      SimpleNet;
654ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  CHAR16                            DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];
655ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_MAC_ADDRESS                   *Mac;
656ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
657ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // List all the PXE Protocols
658ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);
659ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR (Status)) {
660ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return Status;
661ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
662ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
663ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  for (Index = 0; Index < HandleCount; Index++) {
664ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    // We only select the handle WITH a Device Path AND the PXE Protocol
665ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
666ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    if (!EFI_ERROR(Status)) {
667ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      // Allocate BDS Supported Device structure
668ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));
669ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
670387e7c15f5e3a047de0a7a5edb5700e90a1c6c78Heyi Guo      Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&SimpleNet);
671ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      if (!EFI_ERROR(Status)) {
672ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        Mac = &SimpleNet->Mode->CurrentAddress;
673ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        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]);
674ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      } else {
675ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);
676ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin        ASSERT_EFI_ERROR (Status);
677ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      }
678ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"PXE on %s",DeviceDescription);
679ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
680ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      SupportedDevice->DevicePathProtocol = DevicePathProtocol;
681ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_PXE];
682ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
683ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);
684ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    }
685ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
686ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
687ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return EFI_SUCCESS;
688ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
689ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
690ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
691ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionPxeCreateDevicePath (
69222a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
693889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes
694ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
695ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
696ecc62d1390402ea99a807679372c955286e295e0oliviermartin  *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
697ecc62d1390402ea99a807679372c955286e295e0oliviermartin  SetDevicePathEndNode (*DevicePathNodes);
69855a9f75d149ea53d1c8b3da197ec344c2aedb848Olivier Martin
699ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return EFI_SUCCESS;
700ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
701ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
7022db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron/**
7032db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  Update the parameters of a Pxe boot option
7042db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron
7052db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  @param[in]   OldDevicePath  Current complete device path of the Pxe boot option.
7062db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron                              This has to be a valid complete Pxe boot option path.
7072db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  @param[in]   FileName       Description of the file the path is asked for
7082db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  @param[out]  NewDevicePath  Pointer to the new complete device path.
7092db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron
7102db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  @retval  EFI_SUCCESS            Update completed
7112db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  @retval  EFI_OUT_OF_RESOURCES   Fail to perform the update due to lack of resource
7122db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron**/
713ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
714ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionPxeUpdateDevicePath (
71522a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN EFI_DEVICE_PATH            *OldDevicePath,
71622a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
717889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
718ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
719ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
7202db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  //
7212db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  // Make a copy of the complete device path that is made of :
7222db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  // the device path of the device supporting the Pxe base code protocol
7232db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  // followed by an end node.
7242db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  //
7252db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  *NewDevicePath = DuplicateDevicePath (OldDevicePath);
7262db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  if (*NewDevicePath == NULL) {
7272db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron    return EFI_OUT_OF_RESOURCES;
7282db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  } else {
7292db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron    return EFI_SUCCESS;
7302db16368d1554b3243c7b5c0f81aa226e8932722Ronald Cron  }
731ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
732ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
733ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
734ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionPxeIsSupported (
73522a50a13e555102e1751c2f6665eb67855b43473Ronald Cron  IN  EFI_DEVICE_PATH  *DevicePath
736ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
737ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
738ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_STATUS  Status;
739ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_HANDLE Handle;
740ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
741ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBcProtocol;
742ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
74322a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);
744ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR(Status)) {
745ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
746ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
747ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
748ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (!IsDevicePathEnd(RemainingDevicePath)) {
749ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
750ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
751ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
752ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);
753ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR (Status)) {
754ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
755ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  } else {
756ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return TRUE;
757ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
758ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
759ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
760061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron/**
761061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  Add to the list of boot devices the devices allowing a TFTP boot
762061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
763061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  @param[in]   BdsLoadOptionList  List of devices to boot from
764061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
765061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  @retval  EFI_SUCCESS            Update completed
766061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  @retval  EFI_OUT_OF_RESOURCES   Fail to perform the update due to lack of resource
767061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron**/
768ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
769ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionTftpList (
770ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IN OUT LIST_ENTRY* BdsLoadOptionList
771ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
772ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
773061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_STATUS                   Status;
774061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  UINTN                        HandleCount;
775061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_HANDLE                   *HandleBuffer;
776061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_HANDLE                   Handle;
777061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  UINTN                        Index;
778061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_DEVICE_PATH_PROTOCOL     *DevicePathProtocol;
779061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  VOID                         *Interface;
780061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_SIMPLE_NETWORK_PROTOCOL  *SimpleNetworkProtocol;
781061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  BDS_SUPPORTED_DEVICE         *SupportedDevice;
782061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_MAC_ADDRESS              *Mac;
783ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
784061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  //
785061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  // List all the handles on which the Simple Network Protocol is installed.
786061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  //
787061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  Status = gBS->LocateHandleBuffer (
788061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                  ByProtocol,
789061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                  &gEfiSimpleNetworkProtocolGuid,
790061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                  NULL,
791061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                  &HandleCount,
792061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                  &HandleBuffer
793061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                  );
794ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR (Status)) {
795ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return Status;
796ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
797ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
798ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  for (Index = 0; Index < HandleCount; Index++) {
799061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Handle = HandleBuffer[Index];
800061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    //
801061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    // We select the handles that support :
802061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    // . the Device Path Protocol
803061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    // . the MTFTP4 Protocol
804061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    //
805061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Status = gBS->HandleProtocol (
806061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    Handle,
807061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    &gEfiDevicePathProtocolGuid,
808061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    (VOID **)&DevicePathProtocol
809061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    );
810061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (EFI_ERROR (Status)) {
811061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      continue;
812061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
813ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
814061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Status = gBS->HandleProtocol (
815061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    Handle,
816061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    &gEfiMtftp4ServiceBindingProtocolGuid,
817061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    &Interface
818061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    );
819061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (EFI_ERROR (Status)) {
820061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      continue;
821061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
822ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
823061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Status = gBS->HandleProtocol (
824061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    Handle,
825061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    &gEfiSimpleNetworkProtocolGuid,
826061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    (VOID **)&SimpleNetworkProtocol
827061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron                    );
828061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (EFI_ERROR (Status)) {
829061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      continue;
830061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
831ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
832061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    // Allocate BDS Supported Device structure
833061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof (BDS_SUPPORTED_DEVICE));
834061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (SupportedDevice == NULL) {
835061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      continue;
836ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    }
837061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
838061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Mac = &SimpleNetworkProtocol->Mode->CurrentAddress;
839061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    UnicodeSPrint (
840061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      SupportedDevice->Description,
841061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      BOOT_DEVICE_DESCRIPTION_MAX,
842061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      L"TFTP on MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
843061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      Mac->Addr[0],  Mac->Addr[1],  Mac->Addr[2],  Mac->Addr[3],  Mac->Addr[4],  Mac->Addr[5]
844061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      );
845061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
846061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    SupportedDevice->DevicePathProtocol = DevicePathProtocol;
847061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP];
848061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
849061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    InsertTailList (BdsLoadOptionList, &SupportedDevice->Link);
850ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
851ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
852ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return EFI_SUCCESS;
853ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
854ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
855ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
856ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionTftpCreateDevicePath (
85722a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN CHAR16*                    FileName,
858889ac6a8b7d632c7c2dc203bd20b722b9ee57719Ronald Cron  OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePathNodes
859ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
860ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
861061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_STATUS            Status;
862061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  BOOLEAN               IsDHCP;
863061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_IP_ADDRESS        LocalIp;
864061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_IP_ADDRESS        SubnetMask;
865061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_IP_ADDRESS        GatewayIp;
866061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_IP_ADDRESS        RemoteIp;
867061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  IPv4_DEVICE_PATH      *IPv4DevicePathNode;
868061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  FILEPATH_DEVICE_PATH  *FilePathDevicePath;
869061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  CHAR16                BootFilePath[BOOT_DEVICE_FILEPATH_MAX];
870061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  UINTN                 BootFilePathSize;
871ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
872061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  Print (L"Get the IP address from DHCP: ");
873ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  Status = GetHIInputBoolean (&IsDHCP);
874061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  if (EFI_ERROR (Status)) {
875ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return EFI_ABORTED;
876ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
877ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
878ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (!IsDHCP) {
879061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Print (L"Local static IP address: ");
880ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    Status = GetHIInputIP (&LocalIp);
881061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (EFI_ERROR (Status)) {
882061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      return EFI_ABORTED;
883061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
884061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Print (L"Get the network mask: ");
885061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Status = GetHIInputIP (&SubnetMask);
886061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (EFI_ERROR (Status)) {
887061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      return EFI_ABORTED;
888061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
889061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Print (L"Get the gateway IP address: ");
890061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Status = GetHIInputIP (&GatewayIp);
891061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (EFI_ERROR (Status)) {
892ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      return EFI_ABORTED;
893ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    }
894ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
895ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
896061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  Print (L"Get the TFTP server IP address: ");
897ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  Status = GetHIInputIP (&RemoteIp);
898061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  if (EFI_ERROR (Status)) {
899ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return EFI_ABORTED;
900ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
901ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
902061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  Print (L"File path of the %s : ", FileName);
90374b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);
904061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  if (EFI_ERROR (Status)) {
905ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return EFI_ABORTED;
906ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
907ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
908ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  BootFilePathSize = StrSize(BootFilePath);
90974b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  if (BootFilePathSize == 2) {
91074b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin    return EFI_NOT_FOUND;
91174b961324c1cc3ae3f97523e085fb169ec63b608oliviermartin  }
912ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
913ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Allocate the memory for the IPv4 + File Path Device Path Nodes
914ecc62d1390402ea99a807679372c955286e295e0oliviermartin  IPv4DevicePathNode = (IPv4_DEVICE_PATH*)AllocatePool(sizeof(IPv4_DEVICE_PATH) + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH);
915ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
916ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Create the IPv4 Device Path
917ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IPv4DevicePathNode->Header.Type    = MESSAGING_DEVICE_PATH;
918ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IPv4DevicePathNode->Header.SubType = MSG_IPv4_DP;
919ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  SetDevicePathNodeLength (&IPv4DevicePathNode->Header, sizeof(IPv4_DEVICE_PATH));
920061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
921061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  if (!IsDHCP) {
922061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));
923061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    CopyMem (&IPv4DevicePathNode->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
924061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    CopyMem (&IPv4DevicePathNode->GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));
925061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  }
926061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
927ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  CopyMem (&IPv4DevicePathNode->RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));
928ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IPv4DevicePathNode->LocalPort  = 0;
929ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IPv4DevicePathNode->RemotePort = 0;
930ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IPv4DevicePathNode->Protocol = EFI_IP_PROTO_TCP;
931ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  IPv4DevicePathNode->StaticIpAddress = (IsDHCP != TRUE);
932ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
933ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Create the FilePath Device Path node
934ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);
935ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;
936ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;
937ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);
938ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);
939ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
940ecc62d1390402ea99a807679372c955286e295e0oliviermartin  // Set the End Device Path Node
941ecc62d1390402ea99a807679372c955286e295e0oliviermartin  SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize));
94255a9f75d149ea53d1c8b3da197ec344c2aedb848Olivier Martin  *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode;
943ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
944ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  return Status;
945ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
946ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
947152286cea508549928b776e8a2ca62e089bc6790Ronald Cron/**
948152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  Update the parameters of a TFTP boot option
949152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
950152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  The function asks sequentially to update the IPv4 parameters as well as the boot file path,
951152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  providing the previously set value if any.
952152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
953152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  @param[in]   OldDevicePath  Current complete device path of the Tftp boot option.
954152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                              This has to be a valid complete Tftp boot option path.
955152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                              By complete, we mean that it is not only the Tftp
956152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                              specific end part built by the
957152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                              "BdsLoadOptionTftpCreateDevicePath()" function.
958152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                              This path is handled as read only.
959152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  @param[in]   FileName       Description of the file the path is asked for
960152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  @param[out]  NewDevicePath  Pointer to the new complete device path.
961152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
962152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  @retval  EFI_SUCCESS            Update completed
963152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  @retval  EFI_ABORTED            Update aborted by the user
964152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  @retval  EFI_OUT_OF_RESOURCES   Fail to perform the update due to lack of resource
965152286cea508549928b776e8a2ca62e089bc6790Ronald Cron**/
966ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinEFI_STATUS
967ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionTftpUpdateDevicePath (
968152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  IN   EFI_DEVICE_PATH            *OldDevicePath,
969152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  IN   CHAR16                     *FileName,
970152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  OUT  EFI_DEVICE_PATH_PROTOCOL  **NewDevicePath
971ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
972ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
973152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  EFI_STATUS             Status;
974152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  EFI_DEVICE_PATH       *DevicePath;
975152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  EFI_DEVICE_PATH       *DevicePathNode;
976152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  UINT8                 *Ipv4NodePtr;
977152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  IPv4_DEVICE_PATH       Ipv4Node;
978152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  BOOLEAN                IsDHCP;
979152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  EFI_IP_ADDRESS         OldIp;
980061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_IP_ADDRESS         OldSubnetMask;
981061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_IP_ADDRESS         OldGatewayIp;
982152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  EFI_IP_ADDRESS         LocalIp;
983061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_IP_ADDRESS         SubnetMask;
984061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  EFI_IP_ADDRESS         GatewayIp;
985152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  EFI_IP_ADDRESS         RemoteIp;
986152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  UINT8                 *FileNodePtr;
987152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  CHAR16                 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];
988152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  UINTN                  PathSize;
989152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  UINTN                  BootFilePathSize;
990152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  FILEPATH_DEVICE_PATH  *NewFilePathNode;
991152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
992152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  Ipv4NodePtr = NULL;
993152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
994152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
995152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Make a copy of the complete device path that is made of :
996152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // the device path of the device that support the Simple Network protocol
997152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // followed by an IPv4 node (type IPv4_DEVICE_PATH),
998152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // followed by a file path node (type FILEPATH_DEVICE_PATH) and ended up
999152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // by an end node. The IPv6 case is not handled yet.
1000152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1001152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1002152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  DevicePath = DuplicateDevicePath (OldDevicePath);
1003152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  if (DevicePath == NULL) {
1004152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    Status = EFI_OUT_OF_RESOURCES;
1005152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    goto ErrorExit;
1006152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  }
1007152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1008152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1009152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Because of the check done by "BdsLoadOptionTftpIsSupported()" prior to the
1010152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // call to this function, we know that the device path ends with an IPv4 node
1011152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // followed by a file path node and finally an end node. To get the address of
1012152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // the last IPv4 node, we loop over the whole device path, noting down the
1013152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // address of each encountered IPv4 node.
1014152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1015152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1016152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  for (DevicePathNode = DevicePath;
1017152286cea508549928b776e8a2ca62e089bc6790Ronald Cron       !IsDevicePathEnd (DevicePathNode);
1018152286cea508549928b776e8a2ca62e089bc6790Ronald Cron       DevicePathNode = NextDevicePathNode (DevicePathNode))
1019152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  {
1020152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    if (IS_DEVICE_PATH_NODE (DevicePathNode, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)) {
1021152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      Ipv4NodePtr = (UINT8*)DevicePathNode;
1022152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    }
1023152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  }
1024152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1025152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Copy for alignment of the IPv4 node data
1026152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  CopyMem (&Ipv4Node, Ipv4NodePtr, sizeof (IPv4_DEVICE_PATH));
1027152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1028152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  Print (L"Get the IP address from DHCP: ");
1029152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  Status = GetHIInputBoolean (&IsDHCP);
1030152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  if (EFI_ERROR (Status)) {
1031152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    goto ErrorExit;
1032152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  }
1033152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1034152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  if (!IsDHCP) {
1035152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    Print (L"Local static IP address: ");
1036152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    if (Ipv4Node.StaticIpAddress) {
1037152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      CopyMem (&OldIp.v4, &Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
1038152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      Status = EditHIInputIP (&OldIp, &LocalIp);
1039152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    } else {
1040152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      Status = GetHIInputIP (&LocalIp);
1041152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    }
1042152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    if (EFI_ERROR (Status)) {
1043152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      goto ErrorExit;
1044152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    }
1045061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
1046061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Print (L"Get the network mask: ");
1047061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (Ipv4Node.StaticIpAddress) {
1048061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      CopyMem (&OldSubnetMask.v4, &Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
1049061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      Status = EditHIInputIP (&OldSubnetMask, &SubnetMask);
1050061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    } else {
1051061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      Status = GetHIInputIP (&SubnetMask);
1052061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
1053061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (EFI_ERROR (Status)) {
1054061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      goto ErrorExit;
1055061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
1056061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
1057061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    Print (L"Get the gateway IP address: ");
1058061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (Ipv4Node.StaticIpAddress) {
1059061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      CopyMem (&OldGatewayIp.v4, &Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));
1060061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      Status = EditHIInputIP (&OldGatewayIp, &GatewayIp);
1061061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    } else {
1062061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      Status = GetHIInputIP (&GatewayIp);
1063061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
1064061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    if (EFI_ERROR (Status)) {
1065061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron      goto ErrorExit;
1066061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    }
1067152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  }
1068152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1069152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  Print (L"TFTP server IP address: ");
1070152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Copy remote IPv4 address into IPv4 or IPv6 union
1071152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  CopyMem (&OldIp.v4, &Ipv4Node.RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));
1072152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1073152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  Status = EditHIInputIP (&OldIp, &RemoteIp);
1074152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  if (EFI_ERROR (Status)) {
1075152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    goto ErrorExit;
1076152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  }
1077152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1078152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Get the path of the boot file and its size in number of bytes
1079152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  FileNodePtr = Ipv4NodePtr + sizeof (IPv4_DEVICE_PATH);
1080152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  BootFilePathSize = DevicePathNodeLength (FileNodePtr) - SIZE_OF_FILEPATH_DEVICE_PATH;
1081152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1082152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1083152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Ask for update of the boot file path
1084152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1085152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  do {
1086152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    // Copy for 2-byte alignment of the Unicode string
1087152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    CopyMem (
1088152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      BootFilePath, FileNodePtr + SIZE_OF_FILEPATH_DEVICE_PATH,
1089152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      MIN (BootFilePathSize, BOOT_DEVICE_FILEPATH_MAX)
1090152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      );
1091152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    BootFilePath[BOOT_DEVICE_FILEPATH_MAX - 1] = L'\0';
1092152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1093152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    Print (L"File path of the %s: ", FileName);
1094152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);
1095152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    if (EFI_ERROR (Status)) {
1096152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      goto ErrorExit;
1097152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    }
1098152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    PathSize = StrSize (BootFilePath);
1099152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    if (PathSize > 2) {
1100152286cea508549928b776e8a2ca62e089bc6790Ronald Cron      break;
1101152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    }
1102152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    // Empty string, give the user another try
1103152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    Print (L"Empty string - Invalid path\n");
1104152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  } while (PathSize <= 2) ;
1105152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1106152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1107152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Update the IPv4 node. IPv6 case not handled yet.
1108152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1109061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron  if (IsDHCP) {
1110152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    Ipv4Node.StaticIpAddress = FALSE;
1111061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    ZeroMem (&Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
1112061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    ZeroMem (&Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
1113061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    ZeroMem (&Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));
1114152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  } else {
1115152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    Ipv4Node.StaticIpAddress = TRUE;
1116061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    CopyMem (&Ipv4Node.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));
1117061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    CopyMem (&Ipv4Node.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
1118061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron    CopyMem (&Ipv4Node.GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));
1119152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  }
1120061568e2d5f21aeafa942891b15768c57fa0ffacRonald Cron
1121152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  CopyMem (&Ipv4Node.RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));
1122152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  CopyMem (Ipv4NodePtr, &Ipv4Node, sizeof (IPv4_DEVICE_PATH));
1123152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1124152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1125152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Create the new file path node
1126152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1127152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  NewFilePathNode = (FILEPATH_DEVICE_PATH*)AllocatePool (
1128152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                                             SIZE_OF_FILEPATH_DEVICE_PATH +
1129152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                                             PathSize
1130152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                                             );
1131152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  NewFilePathNode->Header.Type    = MEDIA_DEVICE_PATH;
1132152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  NewFilePathNode->Header.SubType = MEDIA_FILEPATH_DP;
1133152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  SetDevicePathNodeLength (
1134152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    NewFilePathNode,
1135152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    SIZE_OF_FILEPATH_DEVICE_PATH + PathSize
1136152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    );
1137152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  CopyMem (NewFilePathNode->PathName, BootFilePath, PathSize);
1138152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1139152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1140152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // Generate the new Device Path by replacing the file path node at address
1141152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  // "FileNodePtr" by the new one "NewFilePathNode" and return its address.
1142152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  //
1143152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  SetDevicePathEndNode (FileNodePtr);
1144152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  *NewDevicePath = AppendDevicePathNode (
1145152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                     DevicePath,
1146152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                     (CONST EFI_DEVICE_PATH_PROTOCOL*)NewFilePathNode
1147152286cea508549928b776e8a2ca62e089bc6790Ronald Cron                     );
1148152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1149152286cea508549928b776e8a2ca62e089bc6790Ronald CronErrorExit:
1150152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  if (DevicePath != NULL) {
1151152286cea508549928b776e8a2ca62e089bc6790Ronald Cron    FreePool (DevicePath) ;
1152152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  }
1153152286cea508549928b776e8a2ca62e089bc6790Ronald Cron
1154152286cea508549928b776e8a2ca62e089bc6790Ronald Cron  return Status;
1155ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
1156ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
1157ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBOOLEAN
1158ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartinBdsLoadOptionTftpIsSupported (
115922a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  IN  EFI_DEVICE_PATH           *DevicePath
1160ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  )
1161ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin{
1162ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_STATUS  Status;
1163ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_HANDLE Handle;
1164ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_DEVICE_PATH  *RemainingDevicePath;
1165ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_DEVICE_PATH  *NextDevicePath;
1166ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBcProtocol;
1167ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
116822a262c8eeace5e5e7e3e812a0b30ac49ea5b811oliviermartin  Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);
1169ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR(Status)) {
1170ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
1171ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
1172ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
1173ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  // Validate the Remaining Device Path
1174ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (IsDevicePathEnd(RemainingDevicePath)) {
1175ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
1176ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
1177ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) &&
1178ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin      !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) {
1179ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
1180ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
1181ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  NextDevicePath = NextDevicePathNode (RemainingDevicePath);
1182ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (IsDevicePathEnd(NextDevicePath)) {
1183ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
1184ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
1185ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) {
1186ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
1187ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
1188ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin
1189ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);
1190ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  if (EFI_ERROR (Status)) {
1191ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return FALSE;
1192ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  } else {
1193ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin    return TRUE;
1194ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin  }
1195ea46ebbe6a5a579ff341071a13ae625e15edae64oliviermartin}
1196