mirror of https://github.com/acidanthera/audk.git
ArmPkg/BdsLib: Add missing BdsLoadOption.c file
Missing from my commit "ArmPkg/BdsLib: Move some functions used to create/update BDS Boot Entry from ArmPlatformPkg/Bds to ArmPkg/BdsLib" git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12325 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
6f5e1c03c3
commit
a6d4d0ac16
|
@ -0,0 +1,264 @@
|
|||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
#include "BdsInternal.h"
|
||||
|
||||
EFI_STATUS
|
||||
BootOptionParseLoadOption (
|
||||
IN EFI_LOAD_OPTION EfiLoadOption,
|
||||
IN UINTN EfiLoadOptionSize,
|
||||
IN OUT BDS_LOAD_OPTION **BdsLoadOption
|
||||
)
|
||||
{
|
||||
BDS_LOAD_OPTION *LoadOption;
|
||||
UINTN DescriptionLength;
|
||||
|
||||
if (EfiLoadOption == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (*BdsLoadOption == NULL) {
|
||||
LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));
|
||||
if (LoadOption == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
} else {
|
||||
LoadOption = *BdsLoadOption;
|
||||
}
|
||||
|
||||
LoadOption->LoadOption = EfiLoadOption;
|
||||
LoadOption->LoadOptionSize = EfiLoadOptionSize;
|
||||
|
||||
LoadOption->Attributes = *(UINT32*)EfiLoadOption;
|
||||
LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOption + sizeof(UINT32));
|
||||
LoadOption->Description = (CHAR16*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16));
|
||||
DescriptionLength = StrSize (LoadOption->Description);
|
||||
LoadOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength);
|
||||
|
||||
// If ((End of EfiLoadOptiony - Start of EfiLoadOption) == EfiLoadOptionSize) then No Optional Data
|
||||
if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - (UINTN)EfiLoadOption) == EfiLoadOptionSize) {
|
||||
LoadOption->OptionalData = NULL;
|
||||
LoadOption->OptionalDataSize = 0;
|
||||
} else {
|
||||
LoadOption->OptionalData = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength);
|
||||
LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - (UINTN)EfiLoadOption);
|
||||
}
|
||||
|
||||
if (*BdsLoadOption == NULL) {
|
||||
*BdsLoadOption = LoadOption;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
BootOptionFromLoadOptionVariable (
|
||||
IN CHAR16* BootVariableName,
|
||||
OUT BDS_LOAD_OPTION** BdsLoadOption
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_LOAD_OPTION EfiLoadOption;
|
||||
UINTN EfiLoadOptionSize;
|
||||
|
||||
Status = GetEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
*BdsLoadOption = NULL;
|
||||
Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, BdsLoadOption);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
BootOptionFromLoadOptionIndex (
|
||||
IN UINT16 LoadOptionIndex,
|
||||
OUT BDS_LOAD_OPTION **BdsLoadOption
|
||||
)
|
||||
{
|
||||
CHAR16 BootVariableName[9];
|
||||
EFI_STATUS Status;
|
||||
|
||||
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", LoadOptionIndex);
|
||||
|
||||
Status = BootOptionFromLoadOptionVariable (BootVariableName, BdsLoadOption);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
(*BdsLoadOption)->LoadOptionIndex = LoadOptionIndex;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
BootOptionToLoadOptionVariable (
|
||||
IN BDS_LOAD_OPTION* BdsLoadOption
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN DescriptionSize;
|
||||
//UINT16 FilePathListLength;
|
||||
EFI_DEVICE_PATH_PROTOCOL* DevicePathNode;
|
||||
UINTN NodeLength;
|
||||
UINT8* EfiLoadOptionPtr;
|
||||
VOID* OldLoadOption;
|
||||
CHAR16 BootVariableName[9];
|
||||
UINTN BootOrderSize;
|
||||
UINT16* BootOrder;
|
||||
|
||||
// If we are overwriting an existent Boot Option then we have to free previously allocated memory
|
||||
if (BdsLoadOption->LoadOptionSize > 0) {
|
||||
OldLoadOption = BdsLoadOption->LoadOption;
|
||||
} else {
|
||||
OldLoadOption = NULL;
|
||||
|
||||
// If this function is called at the creation of the Boot Device entry (not at the update) the
|
||||
// BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry
|
||||
BdsLoadOption->LoadOptionIndex = BootOptionAllocateBootIndex ();
|
||||
|
||||
//TODO: Add to the the Boot Entry List
|
||||
}
|
||||
|
||||
DescriptionSize = StrSize(BdsLoadOption->Description);
|
||||
|
||||
// Ensure the FilePathListLength information is correct
|
||||
ASSERT (GetDevicePathSize (BdsLoadOption->FilePathList) == BdsLoadOption->FilePathListLength);
|
||||
|
||||
// Allocate the memory for the EFI Load Option
|
||||
BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize;
|
||||
|
||||
BdsLoadOption->LoadOption = (EFI_LOAD_OPTION)AllocateZeroPool (BdsLoadOption->LoadOptionSize);
|
||||
if (BdsLoadOption->LoadOption == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
EfiLoadOptionPtr = BdsLoadOption->LoadOption;
|
||||
|
||||
//
|
||||
// Populate the EFI Load Option and BDS Boot Option structures
|
||||
//
|
||||
|
||||
// Attributes fields
|
||||
*(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes;
|
||||
EfiLoadOptionPtr += sizeof(UINT32);
|
||||
|
||||
// FilePath List fields
|
||||
*(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength;
|
||||
EfiLoadOptionPtr += sizeof(UINT16);
|
||||
|
||||
// Boot description fields
|
||||
CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize);
|
||||
EfiLoadOptionPtr += DescriptionSize;
|
||||
|
||||
// File path fields
|
||||
DevicePathNode = BdsLoadOption->FilePathList;
|
||||
while (!IsDevicePathEndType (DevicePathNode)) {
|
||||
NodeLength = DevicePathNodeLength(DevicePathNode);
|
||||
CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength);
|
||||
EfiLoadOptionPtr += NodeLength;
|
||||
DevicePathNode = NextDevicePathNode (DevicePathNode);
|
||||
}
|
||||
|
||||
// Set the End Device Path Type
|
||||
SetDevicePathEndNode (EfiLoadOptionPtr);
|
||||
EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH);
|
||||
|
||||
// Fill the Optional Data
|
||||
if (BdsLoadOption->OptionalDataSize > 0) {
|
||||
CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize);
|
||||
}
|
||||
|
||||
// Case where the fields have been updated
|
||||
if (OldLoadOption) {
|
||||
// Now, the old data has been copied to the new allocated packed structure, we need to update the pointers of BdsLoadOption
|
||||
BootOptionParseLoadOption (BdsLoadOption->LoadOption, BdsLoadOption->LoadOptionSize, &BdsLoadOption);
|
||||
// Free the old packed structure
|
||||
FreePool (OldLoadOption);
|
||||
}
|
||||
|
||||
// Create/Update Boot#### environment variable
|
||||
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);
|
||||
Status = gRT->SetVariable (
|
||||
BootVariableName,
|
||||
&gEfiGlobalVariableGuid,
|
||||
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
BdsLoadOption->LoadOptionSize,
|
||||
BdsLoadOption->LoadOption
|
||||
);
|
||||
|
||||
// When it is a new entry we must add the entry to the BootOrder
|
||||
if (OldLoadOption == NULL) {
|
||||
// Add the new Boot Index to the list
|
||||
Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);
|
||||
// Add the new index at the end
|
||||
BootOrder[BootOrderSize / sizeof(UINT16)] = BdsLoadOption->LoadOptionIndex;
|
||||
BootOrderSize += sizeof(UINT16);
|
||||
} else {
|
||||
// BootOrder does not exist. Create it
|
||||
BootOrderSize = sizeof(UINT16);
|
||||
BootOrder = &(BdsLoadOption->LoadOptionIndex);
|
||||
}
|
||||
|
||||
// Update (or Create) the BootOrder environment variable
|
||||
Status = gRT->SetVariable (
|
||||
L"BootOrder",
|
||||
&gEfiGlobalVariableGuid,
|
||||
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
BootOrderSize,
|
||||
BootOrder
|
||||
);
|
||||
DEBUG((EFI_D_ERROR,"Create %s\n",BootVariableName));
|
||||
} else {
|
||||
DEBUG((EFI_D_ERROR,"Update %s\n",BootVariableName));
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
UINT16
|
||||
BootOptionAllocateBootIndex (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
UINT32 BootIndex;
|
||||
UINT16 *BootOrder;
|
||||
UINTN BootOrderSize;
|
||||
BOOLEAN Found;
|
||||
|
||||
// Get the Boot Option Order from the environment variable
|
||||
Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
for (BootIndex = 0; BootIndex <= 0xFFFF; BootIndex++) {
|
||||
Found = FALSE;
|
||||
for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
|
||||
if (BootOrder[Index] == BootIndex) {
|
||||
Found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!Found) {
|
||||
return BootIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the first index
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue