2 BDS Lib functions which relate with create or process the boot option.
4 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #ifdef __MAKEWITH_TIANO
16 #include "../include/tiano_includes.h"
18 #include "BdsHelper.h"
19 #include "gnuefi-helper.h"
21 #include "../include/refit_call_wrapper.h"
23 EFI_GUID EfiDevicePathProtocolGuid
= { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
26 This function will create all handles associate with every device
27 path node. If the handle associate with one device path node can not
28 be created success, then still give one chance to do the dispatch,
29 which load the missing drivers if possible.
31 @param DevicePathToConnect The device path which will be connected, it can be
32 a multi-instance device path
34 @retval EFI_SUCCESS All handles associate with every device path node
36 @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
37 @retval EFI_NOT_FOUND Create the handle associate with one device path
42 BdsLibConnectDevicePath (
43 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePathToConnect
47 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
48 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
49 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
50 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
51 EFI_DEVICE_PATH_PROTOCOL
*Next
;
53 EFI_HANDLE PreviousHandle
;
56 if (DevicePathToConnect
== NULL
) {
60 DevicePath
= DuplicateDevicePath (DevicePathToConnect
);
61 if (DevicePath
== NULL
) {
62 return EFI_OUT_OF_RESOURCES
;
64 CopyOfDevicePath
= DevicePath
;
68 // The outer loop handles multi instance device paths.
69 // Only console variables contain multiple instance device paths.
71 // After this call DevicePath points to the next Instance
73 Instance
= GetNextDevicePathInstance (&DevicePath
, &Size
);
74 if (Instance
== NULL
) {
75 FreePool (CopyOfDevicePath
);
76 return EFI_OUT_OF_RESOURCES
;
80 while (!IsDevicePathEndType (Next
)) {
81 Next
= NextDevicePathNode (Next
);
84 SetDevicePathEndNode (Next
);
87 // Start the real work of connect with RemainingDevicePath
89 PreviousHandle
= NULL
;
92 // Find the handle that best matches the Device Path. If it is only a
93 // partial match the remaining part of the device path is returned in
94 // RemainingDevicePath.
96 RemainingDevicePath
= Instance
;
97 Status
= refit_call3_wrapper(gBS
->LocateDevicePath
, &EfiDevicePathProtocolGuid
, &RemainingDevicePath
, &Handle
);
99 if (!EFI_ERROR (Status
)) {
100 #ifdef __MAKEWITH_TIANO
101 if (Handle
== PreviousHandle
) {
103 // If no forward progress is made try invoking the Dispatcher.
104 // A new FV may have been added to the system an new drivers
106 // Status == EFI_SUCCESS means a driver was dispatched
107 // Status == EFI_NOT_FOUND means no new drivers were dispatched
109 Status
= gDS
->Dispatch ();
113 if (!EFI_ERROR (Status
)) {
114 PreviousHandle
= Handle
;
116 // Connect all drivers that apply to Handle and RemainingDevicePath,
117 // the Recursive flag is FALSE so only one level will be expanded.
119 // Do not check the connect status here, if the connect controller fail,
120 // then still give the chance to do dispatch, because partial
121 // RemainingDevicepath may be in the new FV
123 // 1. If the connect fail, RemainingDevicepath and handle will not
124 // change, so next time will do the dispatch, then dispatch's status
126 // 2. If the connect success, the RemainingDevicepath and handle will
127 // change, then avoid the dispatch, we have chance to continue the
130 refit_call4_wrapper(gBS
->ConnectController
, Handle
, NULL
, RemainingDevicePath
, FALSE
);
134 // Loop until RemainingDevicePath is an empty device path
136 } while (!EFI_ERROR (Status
) && !IsDevicePathEnd (RemainingDevicePath
));
138 } while (DevicePath
!= NULL
);
140 if (CopyOfDevicePath
!= NULL
) {
141 FreePool (CopyOfDevicePath
);
144 // All handle with DevicePath exists in the handle database
150 Build the boot#### or driver#### option from the VariableName, the
151 build boot#### or driver#### will also be linked to BdsCommonOptionList.
153 @param BdsCommonOptionList The header of the boot#### or driver#### option
155 @param VariableName EFI Variable name indicate if it is boot#### or
158 @retval BDS_COMMON_OPTION Get the option just been created
159 @retval NULL Failed to get the new option
163 BdsLibVariableToOption (
164 IN OUT LIST_ENTRY
*BdsCommonOptionList
,
165 IN CHAR16
*VariableName
173 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
174 BDS_COMMON_OPTION
*Option
;
176 UINT32 LoadOptionsSize
;
179 EFI_GUID EfiGlobalVariableGuid
= { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }};
182 // Read the variable. We will never free this data.
184 Variable
= BdsLibGetVariableAndSize (
186 &EfiGlobalVariableGuid
,
189 if (Variable
== NULL
) {
193 // Notes: careful defined the variable of Boot#### or
194 // Driver####, consider use some macro to abstract the code
197 // Get the option attribute
200 Attribute
= *(UINT32
*) Variable
;
201 TempPtr
+= sizeof (UINT32
);
204 // Get the option's device path size
206 FilePathSize
= *(UINT16
*) TempPtr
;
207 TempPtr
+= sizeof (UINT16
);
210 // Get the option's description string
212 Description
= (CHAR16
*) TempPtr
;
215 // Get the option's description string size
217 TempPtr
+= StrSize ((CHAR16
*) TempPtr
);
220 // Get the option's device path
222 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) TempPtr
;
223 TempPtr
+= FilePathSize
;
225 LoadOptions
= TempPtr
;
226 LoadOptionsSize
= (UINT32
) (VariableSize
- (UINTN
) (TempPtr
- Variable
));
229 // The Console variables may have multiple device paths, so make
230 // an Entry for each one.
232 Option
= AllocateZeroPool (sizeof (BDS_COMMON_OPTION
));
233 if (Option
== NULL
) {
237 Option
->Signature
= BDS_LOAD_OPTION_SIGNATURE
;
238 Option
->DevicePath
= AllocateZeroPool (GetDevicePathSize (DevicePath
));
239 ASSERT(Option
->DevicePath
!= NULL
);
240 CopyMem (Option
->DevicePath
, DevicePath
, GetDevicePathSize (DevicePath
));
242 Option
->Attribute
= Attribute
;
243 Option
->Description
= AllocateZeroPool (StrSize (Description
));
244 ASSERT(Option
->Description
!= NULL
);
245 CopyMem (Option
->Description
, Description
, StrSize (Description
));
247 Option
->LoadOptions
= AllocateZeroPool (LoadOptionsSize
);
248 ASSERT(Option
->LoadOptions
!= NULL
);
249 CopyMem (Option
->LoadOptions
, LoadOptions
, LoadOptionsSize
);
250 Option
->LoadOptionsSize
= LoadOptionsSize
;
253 // Get the value from VariableName Unicode string
254 // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this
255 // Unicode stream to ASCII without any loss in meaning.
257 if (*VariableName
== 'B') {
258 NumOff
= (UINT8
) (sizeof (L
"Boot") / sizeof(CHAR16
) - 1);
259 Option
->BootCurrent
= (UINT16
) ((VariableName
[NumOff
] -'0') * 0x1000);
260 Option
->BootCurrent
= (UINT16
) (Option
->BootCurrent
+ ((VariableName
[NumOff
+1]-'0') * 0x100));
261 Option
->BootCurrent
= (UINT16
) (Option
->BootCurrent
+ ((VariableName
[NumOff
+2]-'0') * 0x10));
262 Option
->BootCurrent
= (UINT16
) (Option
->BootCurrent
+ ((VariableName
[NumOff
+3]-'0')));
265 // Insert active entry to BdsDeviceList
267 if ((Option
->Attribute
& LOAD_OPTION_ACTIVE
) == LOAD_OPTION_ACTIVE
) {
268 InsertTailList (BdsCommonOptionList
, &Option
->Link
);
281 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
282 buffer, and the size of the buffer. If failure return NULL.
284 @param Name String part of EFI variable name
285 @param VendorGuid GUID part of EFI variable name
286 @param VariableSize Returns the size of the EFI variable that was read
288 @return Dynamically allocated memory that contains a copy of the EFI variable
289 Caller is responsible freeing the buffer.
290 @retval NULL Variable was not read
294 BdsLibGetVariableAndSize (
296 IN EFI_GUID
*VendorGuid
,
297 OUT UINTN
*VariableSize
307 // Pass in a zero size buffer to find the required buffer size.
310 Status
= refit_call5_wrapper(gRT
->GetVariable
, Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
311 if (Status
== EFI_BUFFER_TOO_SMALL
) {
313 // Allocate the buffer to return
315 Buffer
= AllocateZeroPool (BufferSize
);
316 if (Buffer
== NULL
) {
320 // Read variable into the allocated buffer.
322 Status
= refit_call5_wrapper(gRT
->GetVariable
, Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
323 if (EFI_ERROR (Status
)) {
328 *VariableSize
= BufferSize
;