853 lines
27 KiB
C
853 lines
27 KiB
C
/** @file
|
|
preovide H2O deafult boot list related functions
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2014 - 2019, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "Bds.h"
|
|
#include <Guid/BdsDefaultBootOptions.h>
|
|
|
|
typedef struct _HANDLE_PRIORITY_MAP {
|
|
EFI_HANDLE Handle;
|
|
UINT32 Priority;
|
|
} HANDLE_PRIORITY_MAP;
|
|
|
|
/**
|
|
Get whole file path from gH2OBdsDefaultBootOptionsTokenSpaceGuid token space PCD.
|
|
|
|
This function allocates space for a new copy of the device path. If DevicePath is not
|
|
found or allocate memory failed, then NULL is returned. The memory for the new device
|
|
path is allocated from EFI boot services memory. It is the responsibility of the caller
|
|
to free the memory allocated.
|
|
|
|
@param[in] Handle A pointer to a device handle.
|
|
|
|
@return pointer to device path or NULL if not found or allocate memory failed.
|
|
**/
|
|
STATIC
|
|
EFI_DEVICE_PATH_PROTOCOL *
|
|
GetDevicePathFromDefaultBootOptionsPcd (
|
|
IN UINTN TokenNum
|
|
)
|
|
{
|
|
CHAR16 *DefaultBootOption;
|
|
CHAR16 *FilePath;
|
|
UINTN FilePathSize;
|
|
UINTN Index;
|
|
UINTN CurrentIndex;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
|
|
DefaultBootOption = (CHAR16 *) LibPcdGetExPtr(&gH2OBdsDefaultBootOptionsTokenSpaceGuid, TokenNum);
|
|
if (DefaultBootOption == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
for (Index = 0; !(DefaultBootOption[Index] == L'\\' && DefaultBootOption[Index + 1] == L't'); Index++) {
|
|
if (DefaultBootOption[Index] == L'\0') {
|
|
break;
|
|
}
|
|
}
|
|
FilePathSize = (Index + 1) * sizeof (CHAR16);
|
|
FilePath = AllocateZeroPool (FilePathSize);
|
|
if (FilePath == NULL) {
|
|
return NULL;
|
|
}
|
|
CopyMem (FilePath, DefaultBootOption, FilePathSize - sizeof (CHAR16));
|
|
//
|
|
// Convert string "\\" to string "\"
|
|
//
|
|
for (Index = 0, CurrentIndex = 0; FilePath[Index] != L'\0'; Index++, CurrentIndex++) {
|
|
if (FilePath[Index] == L'\\' && FilePath[Index + 1] == L'\\') {
|
|
Index++;
|
|
}
|
|
FilePath[CurrentIndex] = FilePath[Index];
|
|
}
|
|
FilePath[CurrentIndex] = L'\0';
|
|
DevicePath = ConvertTextToDevicePath (FilePath);
|
|
FreePool (FilePath);
|
|
return DevicePath;
|
|
}
|
|
|
|
/**
|
|
Get option description string from gH2OBdsDefaultBootOptionsTokenSpaceGuid token space PCD.
|
|
|
|
This function allocates space for option description string. If description is not found or allocate
|
|
memory failed, then NULL is returned. The memory for the description is allocated from EFI boot
|
|
services memory. It is the responsibility of the caller to free the memory allocated.
|
|
|
|
@param[in] TokenNum Token number in gH2OBdsDefaultBootOptionsTokenSpaceGuid token space.
|
|
|
|
@return pointer to description or NULL if not found.
|
|
**/
|
|
STATIC
|
|
CHAR16 *
|
|
GetDescriptionFromDefaultBootOptionsPcd (
|
|
IN UINTN TokenNum
|
|
)
|
|
{
|
|
CHAR16 *DefaultBootOption;
|
|
CHAR16 *TempPtr;
|
|
CHAR16 *Description;
|
|
UINTN DescriptionSize;
|
|
UINTN Index;
|
|
|
|
DefaultBootOption = (CHAR16 *) LibPcdGetExPtr(&gH2OBdsDefaultBootOptionsTokenSpaceGuid, TokenNum);
|
|
if (DefaultBootOption == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
for (Index = 0; !(DefaultBootOption[Index] == L'\\' && DefaultBootOption[Index + 1] == L't'); Index++) {
|
|
if (DefaultBootOption[Index] == L'\0') {
|
|
return NULL;
|
|
}
|
|
}
|
|
TempPtr = &DefaultBootOption[Index];
|
|
Index++;
|
|
while (!(DefaultBootOption[Index] == L'\\' && DefaultBootOption[Index + 1] == L't') && DefaultBootOption[Index] != L'\0') {
|
|
Index++;
|
|
}
|
|
|
|
DescriptionSize = (UINTN) (&DefaultBootOption[Index]) - (UINTN) TempPtr - sizeof (CHAR16);
|
|
Description = AllocateZeroPool (DescriptionSize);
|
|
if (Description == NULL) {
|
|
return NULL;
|
|
}
|
|
CopyMem (Description, TempPtr + 2, DescriptionSize - sizeof (CHAR16));
|
|
return Description;
|
|
}
|
|
|
|
|
|
/**
|
|
Get option attributes from gH2OBdsDefaultBootOptionsTokenSpaceGuid token space PCD.
|
|
|
|
@param[in] TokenNum Token number in gH2OBdsDefaultBootOptionsTokenSpaceGuid token space.
|
|
|
|
@return Attributes value of option. Attribute will be considered 0 if not found.
|
|
**/
|
|
STATIC
|
|
UINT32
|
|
GetAttributesFromDefaultBootOptionsPcd (
|
|
IN UINTN TokenNum
|
|
)
|
|
{
|
|
CHAR16 *DefaultBootOption;
|
|
CHAR16 *TempPtr;
|
|
CHAR16 *AttributesString;
|
|
UINTN AttributesStringSize;
|
|
UINTN Index;
|
|
UINTN TabIndex;
|
|
UINT32 Attributes;
|
|
|
|
DefaultBootOption = (CHAR16 *) LibPcdGetExPtr(&gH2OBdsDefaultBootOptionsTokenSpaceGuid, TokenNum);
|
|
if (DefaultBootOption == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// skip device path and description
|
|
//
|
|
Index = 0;
|
|
for (TabIndex = 0; TabIndex < 2; TabIndex++) {
|
|
for (; !(DefaultBootOption[Index] == L'\\' && DefaultBootOption[Index + 1] == L't'); Index++) {
|
|
if (DefaultBootOption[Index] == L'\0') {
|
|
return 0;
|
|
}
|
|
}
|
|
Index += 2;
|
|
}
|
|
TempPtr = &DefaultBootOption[Index];
|
|
Index++;
|
|
while (!(DefaultBootOption[Index] == L'\\' && DefaultBootOption[Index + 1] == L't') && DefaultBootOption[Index] != L'\0') {
|
|
Index++;
|
|
}
|
|
|
|
AttributesStringSize = (UINTN) (&DefaultBootOption[Index]) - (UINTN) TempPtr + sizeof (CHAR16);
|
|
AttributesString = AllocateZeroPool (AttributesStringSize);
|
|
if (AttributesString == NULL) {
|
|
return 0;
|
|
}
|
|
CopyMem (AttributesString, TempPtr, AttributesStringSize - sizeof (CHAR16));
|
|
Attributes = (UINT32 ) StrHexToUintn (AttributesString);
|
|
FreePool (AttributesString);
|
|
return Attributes;
|
|
}
|
|
|
|
|
|
/**
|
|
Convert all of escape sequences in string to C standard hex value.
|
|
|
|
@param[in,out] String A Null-terminated string to be converted.
|
|
|
|
@retval EFI_SUCCESS Convert string successfully.
|
|
@retval EFI_INVALID_PARAMETER String is NULL or input string format is incorrect.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
ConvertEscapeSequences (
|
|
IN OUT CHAR16 *String
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN CurrentIndex;
|
|
CHAR16 NumberString[4];
|
|
|
|
|
|
if (String == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
CurrentIndex = 0;
|
|
for (Index = 0; String[Index] != L'\0'; Index++, CurrentIndex++) {
|
|
if (String[Index] =='\\') {
|
|
switch (String[Index + 1]) {
|
|
|
|
case L'a':
|
|
String[CurrentIndex] = L'\a';
|
|
Index++;
|
|
break;
|
|
|
|
case L'b':
|
|
String[CurrentIndex] = L'\b';
|
|
Index++;
|
|
break;
|
|
|
|
case L'f':
|
|
String[CurrentIndex] = L'\f';
|
|
Index++;
|
|
break;
|
|
|
|
case L'n':
|
|
String[CurrentIndex] = L'\n';
|
|
Index++;
|
|
break;
|
|
|
|
case L'r':
|
|
String[CurrentIndex] = L'\r';
|
|
Index++;
|
|
break;
|
|
|
|
case L't':
|
|
String[CurrentIndex] = L'\t';
|
|
Index++;
|
|
break;
|
|
|
|
case L'\\':
|
|
String[CurrentIndex] = L'\\';
|
|
Index++;
|
|
break;
|
|
|
|
case L'\'':
|
|
String[CurrentIndex] = L'\'';
|
|
Index++;
|
|
break;
|
|
|
|
case L'\"':
|
|
String[CurrentIndex] = L'\"';
|
|
Index++;
|
|
break;
|
|
|
|
case L'?':
|
|
String[CurrentIndex] = L'\?';
|
|
Index++;
|
|
break;
|
|
|
|
default:
|
|
if (String[Index + 1] == L'x') {
|
|
if (String [Index + 2] == L'\0' || String [Index + 3] == L'\0') {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
CopyMem (NumberString, &String [Index + 2], 2 * sizeof (CHAR16));
|
|
NumberString[2] = L'\0';
|
|
String[CurrentIndex] = (CHAR16) StrHexToUintn (NumberString);
|
|
Index += 3;
|
|
} else if (String [Index + 1] != L'\0' || String [Index + 2] != L'\0' || String [Index + 3] != L'\0') {
|
|
CopyMem (NumberString, &String [Index + 1], 3 * sizeof (CHAR16));
|
|
NumberString[3] = L'\0';
|
|
String[CurrentIndex] = (CHAR16) StrDecimalToUintn (NumberString);
|
|
Index += 3;
|
|
} else {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
} else {
|
|
String[CurrentIndex] = String[Index];
|
|
}
|
|
}
|
|
String[CurrentIndex] = L'\0';
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Convert optional data string which format is array data to binary data.
|
|
|
|
This function allocates space for optional data. If optional data is not found or allocate
|
|
memory failed, then failed is returned. The memory for the optional data is allocated from EFI boot
|
|
services memory. It is the responsibility of the caller to free the memory allocated.
|
|
|
|
@param[in] TokenNum Token number in gH2OBdsDefaultBootOptionsTokenSpaceGuid token space.
|
|
@param[out] OptionalData Pointer to optional data.
|
|
@param[out] OptionalDataSize Pointer to optional data size.
|
|
|
|
@retval EFI_SUCCESS Convert optional data string successfully.
|
|
@retval EFI_INVALID_PARAMETER OptionalDataString is NULL, OptinalData is NULL or OptionalDataSize is NULL.
|
|
@retval EFI_INVALID_PARAMETER Input string isn't array data format.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
ConvertArrayToData (
|
|
IN CHAR16 *OptionalDataString,
|
|
OUT VOID **OptionalData,
|
|
OUT UINT32 *OptionalDataSize
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN PreviousIndex;
|
|
UINT32 Size;
|
|
UINT8 *Data;
|
|
CHAR16 *WorkingString;
|
|
UINTN Offset;
|
|
|
|
if (OptionalDataString == NULL || OptionalData == NULL || OptionalDataSize == NULL ||
|
|
OptionalDataString[0] != L'{') {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Size = 1;
|
|
for (Index = 1; OptionalDataString[Index] != L'}'; Index++) {
|
|
if (OptionalDataString[Index] == L',') {
|
|
Size++;
|
|
}
|
|
}
|
|
|
|
WorkingString = AllocateCopyPool (StrSize (OptionalDataString), OptionalDataString);
|
|
if (WorkingString == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Data = AllocateZeroPool (Size);
|
|
if (Data == NULL) {
|
|
FreePool (WorkingString);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
PreviousIndex = 1;
|
|
Offset = 0;
|
|
for (Index = 1; WorkingString[Index] != L'}'; Index++) {
|
|
if (WorkingString[Index] == ',') {
|
|
WorkingString[Index] = L'\0';
|
|
Data[Offset++] = (UINT8) StrHexToUintn (&WorkingString[PreviousIndex]);
|
|
PreviousIndex = Index + 1;
|
|
}
|
|
}
|
|
WorkingString[Index] = L'\0';
|
|
Data[Offset] = (UINT8) StrHexToUintn (&WorkingString[PreviousIndex]);
|
|
FreePool (WorkingString);
|
|
*OptionalData = Data;
|
|
*OptionalDataSize = Size;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Convert optional data string which format is CHAR16 string to binary data.
|
|
|
|
This function allocates space for optional data. If optional data is not found or allocate
|
|
memory failed, then failed is returned. The memory for the optional data is allocated from EFI boot
|
|
services memory. It is the responsibility of the caller to free the memory allocated.
|
|
|
|
@param[in] TokenNum Token number in gH2OBdsDefaultBootOptionsTokenSpaceGuid token space.
|
|
@param[out] OptionalData Pointer to optional data.
|
|
@param[out] OptionalDataSize Pointer to optional data size.
|
|
|
|
@retval EFI_SUCCESS Convert optional data string successfully.
|
|
@retval EFI_INVALID_PARAMETER OptionalDataString is NULL, OptinalData is NULL or OptionalDataSize is NULL.
|
|
@retval EFI_INVALID_PARAMETER Input string isn't CHAR16 string format.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
ConvertStringToData (
|
|
IN CHAR16 *OptionalDataString,
|
|
OUT VOID **OptionalData,
|
|
OUT UINT32 *OptionalDataSize
|
|
)
|
|
{
|
|
CHAR16 *CopiedString;
|
|
CHAR16 *WorkingString;
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
UINTN WorkingStringSize;
|
|
|
|
if (OptionalDataString == NULL || OptionalData == NULL || OptionalDataSize == NULL ||
|
|
OptionalDataString[0] != L'L' || OptionalDataString[1] != L'\\' || OptionalDataString[2] != L'\"') {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
CopiedString = AllocateCopyPool (StrSize (OptionalDataString), OptionalDataString);
|
|
if (CopiedString == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
WorkingStringSize = StrSize (OptionalDataString);
|
|
WorkingString = AllocateZeroPool (WorkingStringSize);
|
|
if (WorkingString == NULL) {
|
|
FreePool (CopiedString);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
for (Index = 3; !(CopiedString[Index - 1] == L'\\' && CopiedString[Index] == L'\"'); Index++) {
|
|
}
|
|
CopiedString[Index - 1] = L'\0';
|
|
|
|
|
|
StrCpyS (WorkingString, WorkingStringSize / sizeof(CHAR16), CopiedString + 3);
|
|
FreePool (CopiedString);
|
|
Status = ConvertEscapeSequences (WorkingString);
|
|
if (Status != EFI_SUCCESS) {
|
|
FreePool (WorkingString);
|
|
return Status;
|
|
}
|
|
|
|
*OptionalData = WorkingString;
|
|
*OptionalDataSize = (UINT32) StrSize (WorkingString);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Convert optional data string which format is ASCII string to binary data.
|
|
|
|
This function allocates space for optional data. If optional data is not found or allocate
|
|
memory failed, then failed is returned. The memory for the optional data is allocated from EFI boot
|
|
services memory. It is the responsibility of the caller to free the memory allocated.
|
|
|
|
@param[in] TokenNum Token number in gH2OBdsDefaultBootOptionsTokenSpaceGuid token space.
|
|
@param[out] OptionalData Pointer to optional data.
|
|
@param[out] OptionalDataSize Pointer to optional data size.
|
|
|
|
@retval EFI_SUCCESS Convert optional data string successfully.
|
|
@retval EFI_INVALID_PARAMETER OptionalDataString is NULL, OptinalData is NULL or OptionalDataSize is NULL.
|
|
@retval EFI_INVALID_PARAMETER Input string isn't ASCII string format.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
ConvertAsciiStringToData (
|
|
IN CHAR16 *OptionalDataString,
|
|
OUT VOID **OptionalData,
|
|
OUT UINT32 *OptionalDataSize
|
|
)
|
|
{
|
|
CHAR16 *CopiedString;
|
|
CHAR8 *AsciiString;
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
UINTN OptionalDataStringSize;
|
|
|
|
if (OptionalDataString == NULL || OptionalData == NULL || OptionalDataSize == NULL ||
|
|
OptionalDataString[0] != L'\\' || OptionalDataString[1] != L'\"') {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
OptionalDataStringSize = StrSize (OptionalDataString);
|
|
CopiedString = AllocateCopyPool (OptionalDataStringSize, OptionalDataString);
|
|
if (CopiedString == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
for (Index = 2; !(CopiedString[Index - 1] == L'\\' && CopiedString[Index] == L'\"'); Index++) {
|
|
}
|
|
CopiedString[Index - 1] = L'\0';
|
|
Status = ConvertEscapeSequences (CopiedString + 2);
|
|
if (Status != EFI_SUCCESS) {
|
|
FreePool (CopiedString);
|
|
return Status;
|
|
}
|
|
|
|
AsciiString = AllocateZeroPool (OptionalDataStringSize);
|
|
if (AsciiString == NULL) {
|
|
FreePool (CopiedString);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
UnicodeStrToAsciiStrS (CopiedString + 2, AsciiString, OptionalDataStringSize);
|
|
FreePool (CopiedString);
|
|
|
|
|
|
*OptionalData = AsciiString;
|
|
*OptionalDataSize = (UINT32) AsciiStrSize (AsciiString);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Convert optional data string from gH2OBdsDefaultBootOptionsTokenSpaceGuid token space PCD to binary data.
|
|
|
|
This function allocates space for optional data. If optional data is not found or allocate
|
|
memory failed, then failed is returned. The memory for the optional data is allocated from EFI boot
|
|
services memory. It is the responsibility of the caller to free the memory allocated.
|
|
|
|
@param[in] TokenNum Token number in gH2OBdsDefaultBootOptionsTokenSpaceGuid token space.
|
|
@param[out] OptionalData Pointer to optional data.
|
|
@param[out] OptionalDataSize Pointer to optional data size.
|
|
|
|
@retval EFI_SUCCESS Convert optional data string successfully.
|
|
@retval EFI_INVALID_PARAMETER OptionalDataString is NULL, OptinalData is NULL or OptionalDataSize is NULL.
|
|
@retval EFI_UNSUPPORTED Input optional data string format is unsupported.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
ConvertDataStringToData (
|
|
IN CHAR16 *OptionalDataString,
|
|
OUT VOID **OptionalData,
|
|
OUT UINT32 *OptionalDataSize
|
|
)
|
|
{
|
|
|
|
if (OptionalDataString == NULL || OptionalData == NULL || OptionalDataSize == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
if (OptionalDataString[0] == L'{') {
|
|
return ConvertArrayToData (OptionalDataString, OptionalData, OptionalDataSize);
|
|
} else if (OptionalDataString[0] == L'L' && OptionalDataString[1] == L'\\' && OptionalDataString[2] == L'\"') {
|
|
return ConvertStringToData (OptionalDataString, OptionalData, OptionalDataSize);
|
|
} else if (OptionalDataString[0] == L'\\' && OptionalDataString[1] == L'\"') {
|
|
return ConvertAsciiStringToData (OptionalDataString, OptionalData, OptionalDataSize);
|
|
}
|
|
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
|
|
/**
|
|
Get optional data from gH2OBdsDefaultBootOptionsTokenSpaceGuid token space PCD.
|
|
|
|
This function allocates space for optional data. If optional data is not found or allocate
|
|
memory failed, then failed is returned. The memory for the optional data is allocated from EFI boot
|
|
services memory. It is the responsibility of the caller to free the memory allocated.
|
|
|
|
@param[in] TokenNum Token number in gH2OBdsDefaultBootOptionsTokenSpaceGuid token space.
|
|
@param[out] OptionalData Pointer to optional data.
|
|
@param[out] OptionalDataSize Pointer to optional data size.
|
|
|
|
@retval EFI_SUCCESS Get optional data successfully.
|
|
@retval EFI_INVALID_PARAMETER OptinalData is NULL or OptionalDataSize is NULL.
|
|
@retval EFI_NOT_FOUND Cannot find optional data.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory to store optional data failed.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
GetOptionalDataFromDefaultBootOptionsPcd (
|
|
IN UINTN TokenNum,
|
|
OUT VOID **OptinalData,
|
|
OUT UINT32 *OptionalDataSize
|
|
)
|
|
{
|
|
CHAR16 *DefaultBootOption;
|
|
CHAR16 *DataString;
|
|
UINTN DataStringSize;
|
|
UINTN Index;
|
|
UINTN TabIndex;
|
|
VOID *Data;
|
|
UINT32 DataSize;
|
|
EFI_STATUS Status;
|
|
|
|
DefaultBootOption = (CHAR16 *) LibPcdGetExPtr(&gH2OBdsDefaultBootOptionsTokenSpaceGuid, TokenNum);
|
|
if (DefaultBootOption == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// skip device path ,description and attribute
|
|
//
|
|
Index = 0;
|
|
for (TabIndex = 0; TabIndex < 3; TabIndex++) {
|
|
for (; !(DefaultBootOption[Index] == L'\\' && DefaultBootOption[Index + 1] == L't'); Index++) {
|
|
if (DefaultBootOption[Index] == L'\0') {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
Index += 2;
|
|
}
|
|
|
|
DataStringSize = StrSize (&DefaultBootOption[Index]);
|
|
DataString = AllocateZeroPool (DataStringSize);
|
|
if (DataString == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
CopyMem (DataString, &DefaultBootOption[Index], DataStringSize);
|
|
Data = NULL;
|
|
DataSize = 0;
|
|
Status = ConvertDataStringToData (DataString, &Data, &DataSize);
|
|
if (Status == EFI_SUCCESS) {
|
|
*OptinalData = Data;
|
|
*OptionalDataSize = DataSize;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Swap the content of the two inpupt HANDLE_PRIORITY_MAP instance.
|
|
|
|
@param[in,out] PriorityMap First HANDLE_PRIORITY_MAP instance.
|
|
@param[in,out] PriorityMap2 Second HANDLE_PRIORITY_MAP instance.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
SwapMap (
|
|
IN OUT HANDLE_PRIORITY_MAP *PriorityMap,
|
|
IN OUT HANDLE_PRIORITY_MAP *PriorityMap2
|
|
)
|
|
{
|
|
HANDLE_PRIORITY_MAP TempMap;
|
|
|
|
CopyMem (&TempMap , PriorityMap , sizeof (HANDLE_PRIORITY_MAP));
|
|
CopyMem (PriorityMap , PriorityMap2, sizeof (HANDLE_PRIORITY_MAP));
|
|
CopyMem (PriorityMap2, &TempMap , sizeof (HANDLE_PRIORITY_MAP));
|
|
}
|
|
|
|
/**
|
|
Update boot group boot options to boot list.
|
|
|
|
@retval EFI_SUCCESS Update boot group to boot list successfully.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateDefaultBootListFromBootGroup (
|
|
OUT LIST_ENTRY *BootList
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuffer;
|
|
HANDLE_PRIORITY_MAP *SortedMap;
|
|
H2O_BDS_BOOT_GROUP_PROTOCOL *BootGroup;
|
|
UINTN Index;
|
|
UINTN InnerIndex;
|
|
UINT32 BootOptionArrayLen;
|
|
H2O_BDS_LOAD_OPTION *BootOptionArray;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gH2OBdsBootGroupProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
SortedMap = AllocateZeroPool (HandleCount * sizeof (HANDLE_PRIORITY_MAP));
|
|
if (SortedMap == NULL) {
|
|
FreePool (HandleBuffer);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Initialize Sorted map
|
|
//
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gH2OBdsBootGroupProtocolGuid,
|
|
(VOID **) &BootGroup
|
|
);
|
|
ASSERT (Status == EFI_SUCCESS);
|
|
SortedMap[Index].Handle = HandleBuffer[Index];
|
|
SortedMap[Index].Priority = BootGroup->DefaultBootListPriority;
|
|
}
|
|
|
|
//
|
|
// Sort Sorted map by Priority from high to low
|
|
//
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
for (InnerIndex = Index; InnerIndex > 0; InnerIndex--) {
|
|
if (SortedMap[InnerIndex].Priority > SortedMap[InnerIndex - 1].Priority) {
|
|
SwapMap (&SortedMap[InnerIndex], &SortedMap[InnerIndex - 1]);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// According to priority to update default boot list
|
|
//
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
SortedMap[Index].Handle,
|
|
&gH2OBdsBootGroupProtocolGuid,
|
|
(VOID **) &BootGroup
|
|
);
|
|
ASSERT (Status == EFI_SUCCESS);
|
|
Status = BootGroup->UpdateDefaultBootList (
|
|
BootGroup,
|
|
gBdsServices,
|
|
&BootOptionArrayLen,
|
|
&BootOptionArray
|
|
);
|
|
if (Status != EFI_SUCCESS || BootOptionArrayLen == 0) {
|
|
continue;
|
|
}
|
|
|
|
for (InnerIndex = 0; InnerIndex < BootOptionArrayLen; InnerIndex++) {
|
|
InsertTailList (BootList, &BootOptionArray[InnerIndex].Link);
|
|
}
|
|
}
|
|
|
|
FreePool (SortedMap);
|
|
FreePool (HandleBuffer);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Add all of default boot options to boot list.
|
|
|
|
@param[out] BootList List header for boot options.
|
|
|
|
@retval EFI_SUCCESS Add boot options to boot list successfully.
|
|
@retval EFI_INVALID_PARAMETER BootList is NULL.
|
|
@retval Other Create new boot option failed..
|
|
**/
|
|
EFI_STATUS
|
|
UpdateDefaultBootListFromPcd (
|
|
OUT LIST_ENTRY *BootList
|
|
)
|
|
{
|
|
UINTN TokenNum;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
CHAR16 *Description;
|
|
UINT32 Attributes;
|
|
VOID *OptionalData;
|
|
UINT32 OptionalDataSize;
|
|
H2O_BDS_LOAD_OPTION *BootOption;
|
|
EFI_STATUS Status;
|
|
|
|
if (BootList == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
for (TokenNum = LibPcdGetNextToken(&gH2OBdsDefaultBootOptionsTokenSpaceGuid, 0); TokenNum != 0; \
|
|
TokenNum = LibPcdGetNextToken(&gH2OBdsDefaultBootOptionsTokenSpaceGuid, TokenNum)) {
|
|
DevicePath = GetDevicePathFromDefaultBootOptionsPcd (TokenNum);
|
|
if (DevicePath == NULL) {
|
|
continue;
|
|
}
|
|
Description = GetDescriptionFromDefaultBootOptionsPcd (TokenNum);
|
|
Attributes = GetAttributesFromDefaultBootOptionsPcd (TokenNum);
|
|
OptionalData = NULL;
|
|
OptionalDataSize = 0;
|
|
GetOptionalDataFromDefaultBootOptionsPcd (TokenNum, &OptionalData, &OptionalDataSize);
|
|
Status = gBdsServices->CreateLoadOption (
|
|
gBdsServices,
|
|
BOOT_OPTION,
|
|
NULL,
|
|
NULL,
|
|
Attributes,
|
|
DevicePath,
|
|
Description,
|
|
OptionalData,
|
|
OptionalDataSize,
|
|
&BootOption
|
|
);
|
|
FreePool (DevicePath);
|
|
if (Description != NULL) {
|
|
FreePool (Description);
|
|
}
|
|
if (OptionalData != NULL) {
|
|
FreePool (OptionalData);
|
|
}
|
|
if (Status != EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
InsertTailList (BootList, &BootOption->Link);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Add all of default boot options to boot list.
|
|
|
|
@param[out] BootList List header for boot options.
|
|
|
|
@retval EFI_SUCCESS Add boot options to boot list successfully.
|
|
@retval EFI_INVALID_PARAMETER BootList is NULL.
|
|
@retval Other Create new boot option failed..
|
|
**/
|
|
EFI_STATUS
|
|
AddDefaultBootOptionsToBootList (
|
|
OUT LIST_ENTRY *BootList
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *Link;
|
|
H2O_BDS_LOAD_OPTION *LoadOption;
|
|
UINTN Count;
|
|
UINT16 *BootOrder;
|
|
CHAR16 *VariableName;
|
|
EFI_GUID VariableGuid;
|
|
EFI_STATUS OemSvcStatus;
|
|
|
|
if (BootList == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
UpdateDefaultBootListFromPcd (BootList);
|
|
UpdateDefaultBootListFromBootGroup (BootList);
|
|
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcUpdateDefaultBootList \n"));
|
|
Status = OemSvcUpdateDefaultBootList (&BootList);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcUpdateDefaultBootList Status: %r\n", Status));
|
|
if (Status == EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
if (IsListEmpty (BootList)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Count = 0;
|
|
for (Link = GetFirstNode (BootList); !IsNull (BootList, Link); Link = GetNextNode (BootList, Link)) {
|
|
Count++;
|
|
}
|
|
BootOrder = AllocatePool (Count * sizeof (UINT16));
|
|
if (BootOrder == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Count = 0;
|
|
for (Link = GetFirstNode (BootList); !IsNull (BootList, Link); Link = GetNextNode (BootList, Link)) {
|
|
LoadOption = BDS_OPTION_FROM_LINK (Link);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcDxeUpdateDescriptionOfBootOption \n"));
|
|
OemSvcStatus = OemSvcDxeUpdateDescriptionOfBootOption (LoadOption->DevicePath, NULL, NULL, &LoadOption->Description);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcDxeUpdateDescriptionOfBootOption Status: %r\n", OemSvcStatus));
|
|
|
|
Status = gBdsServices->ConvertLoadOptionToVar (
|
|
gBdsServices,
|
|
LoadOption,
|
|
&VariableName,
|
|
&VariableGuid
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
FreePool (VariableName);
|
|
|
|
BootOrder[Count++] = LoadOption->LoadOrder;
|
|
}
|
|
|
|
Status = CommonSetVariable (
|
|
EFI_BOOT_ORDER_VARIABLE_NAME,
|
|
&gEfiGlobalVariableGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
Count * sizeof (UINT16),
|
|
BootOrder
|
|
);
|
|
|
|
FreePool (BootOrder);
|
|
return Status;
|
|
}
|