bbssupport.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,604 行 · 第 1/3 页
C
1,604 行
/*++
Copyright (c) 2004 - 2006, Intel Corporation
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.
Module Name:
BBSsupport.c
Abstract:
This function deal with the legacy boot option, it create, delete
and manage the legacy boot option, all legacy boot option is getting from
the legacy BBS table.
--*/
#include "BBSsupport.h"
#include "BdsLib.h"
#include EFI_PROTOCOL_DEFINITION (LegacyBios)
EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
END_DEVICE_PATH_LENGTH,
0
};
VOID
AsciiToUnicodeSize (
IN UINT8 *a,
IN UINTN Size,
OUT UINT16 *u
)
/*++
Routine Description:
Translate the first n characters of an Ascii string to
Unicode characters. The count n is indicated by parameter
Size. If Size is greater than the length of string, then
the entire string is translated.
Arguments:
a - Pointer to input Ascii string.
Size - The number of characters to translate.
u - Pointer to output Unicode string buffer.
Returns:
None
--*/
{
UINTN i;
i = 0;
while (a[i] != 0) {
u[i] = (CHAR16) a[i];
if (i == Size) {
break;
}
i++;
}
u[i] = 0;
}
VOID
BdsBuildLegacyDevNameString (
IN BBS_TABLE *CurBBSEntry,
IN UINTN Index,
IN UINTN BufSize,
OUT CHAR16 *BootString
)
{
CHAR16 *Fmt;
CHAR16 *Type;
UINT8 *StringDesc;
CHAR16 temp[80];
switch (Index) {
//
// Primary Master
//
case 1:
Fmt = L"Primary Master %s";
break;
//
// Primary Slave
//
case 2:
Fmt = L"Primary Slave %s";
break;
//
// Secondary Master
//
case 3:
Fmt = L"Secondary Master %s";
break;
//
// Secondary Slave
//
case 4:
Fmt = L"Secondary Slave %s";
break;
default:
Fmt = L"%s";
break;
}
switch (CurBBSEntry->DeviceType) {
case BBS_FLOPPY:
Type = L"Floppy";
break;
case BBS_HARDDISK:
Type = L"Harddisk";
break;
case BBS_CDROM:
Type = L"CDROM";
break;
case BBS_PCMCIA:
Type = L"PCMCIAe";
break;
case BBS_USB:
Type = L"USB";
break;
case BBS_EMBED_NETWORK:
Type = L"Network";
break;
case BBS_BEV_DEVICE:
Type = L"BEVe";
break;
case BBS_UNKNOWN:
default:
Type = L"Unknown";
break;
}
//
// If current BBS entry has its description then use it.
//
StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);
if (NULL != StringDesc) {
//
// Only get fisrt 32 characters, this is suggested by BBS spec
//
AsciiToUnicodeSize (StringDesc, 32, temp);
Fmt = L"%s";
Type = temp;
}
SPrint (BootString, BufSize, Fmt, Type);
}
EFI_STATUS
BdsCreateLegacyBootOption (
IN BBS_TABLE *CurrentBbsEntry,
IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath,
IN UINTN Index,
IN OUT UINT16 **BootOrderList,
IN OUT UINTN *BootOrderListSize
)
/*++
Routine Description:
Create a legacy boot option for the specified entry of
BBS table, save it as variable, and append it to the boot
order list.
Arguments:
CurrentBbsEntry - Pointer to current BBS table.
CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS
Index - Index of the specified entry in BBS table.
BootOrderList - On input, the original boot order list.
On output, the new boot order list attached with the
created node.
BootOrderListSize - On input, the original size of boot order list.
- On output, the size of new boot order list.
Returns:
EFI_SUCCESS - Boot Option successfully created.
EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
Other - Error occurs while setting variable.
--*/
{
EFI_STATUS Status;
UINT16 CurrentBootOptionNo;
UINT16 BootString[10];
UINT16 BootDesc[100];
UINT16 *NewBootOrderList;
UINTN BufferSize;
VOID *Buffer;
UINT8 *Ptr;
UINT16 CurrentBbsDevPathSize;
UINTN BootOrderIndex;
UINTN BootOrderLastIndex;
UINTN ArrayIndex;
BOOLEAN IndexNotFound;
if (NULL == (*BootOrderList)) {
CurrentBootOptionNo = 0;
} else {
for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {
IndexNotFound = TRUE;
for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {
if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {
IndexNotFound = FALSE;
break;
}
}
if (!IndexNotFound) {
continue;
} else {
break;
}
}
CurrentBootOptionNo = (UINT16) ArrayIndex;
}
SPrint (
BootString,
sizeof (BootString),
L"Boot%04x",
CurrentBootOptionNo
);
BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);
CurrentBbsDevPathSize = (UINT16) (EfiDevicePathSize (CurrentBbsDevPath));
BufferSize = sizeof (UINT32) +
sizeof (UINT16) +
EfiStrSize (BootDesc) +
CurrentBbsDevPathSize +
sizeof (BBS_TABLE) +
sizeof (UINT16);
Buffer = EfiAllocateZeroPool (BufferSize);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ptr = (UINT8 *) Buffer;
*((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
Ptr += sizeof (UINT32);
*((UINT16 *) Ptr) = CurrentBbsDevPathSize;
Ptr += sizeof (UINT16);
EfiCopyMem (
Ptr,
BootDesc,
EfiStrSize (BootDesc)
);
Ptr += EfiStrSize (BootDesc);
EfiCopyMem (
Ptr,
CurrentBbsDevPath,
CurrentBbsDevPathSize
);
Ptr += CurrentBbsDevPathSize;
EfiCopyMem (
Ptr,
CurrentBbsEntry,
sizeof (BBS_TABLE)
);
Ptr += sizeof (BBS_TABLE);
*((UINT16 *) Ptr) = (UINT16) Index;
Status = gRT->SetVariable (
BootString,
&gEfiGlobalVariableGuid,
VAR_FLAG,
BufferSize,
Buffer
);
SafeFreePool (Buffer);
Buffer = NULL;
NewBootOrderList = EfiAllocateZeroPool (*BootOrderListSize + sizeof (UINT16));
if (NULL == NewBootOrderList) {
return EFI_OUT_OF_RESOURCES;
}
if (NULL != *BootOrderList) {
EfiCopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);
}
SafeFreePool (*BootOrderList);
BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16));
NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo;
*BootOrderListSize += sizeof (UINT16);
*BootOrderList = NewBootOrderList;
return Status;
}
BOOLEAN
BdsIsLegacyBootOption (
IN UINT8 *BootOptionVar,
OUT BBS_TABLE **BbsEntry,
OUT UINT16 *BbsIndex
)
{
UINT8 *Ptr;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
BOOLEAN Ret;
UINT16 DevPathLen;
Ptr = BootOptionVar;
Ptr += sizeof (UINT32);
DevPathLen = *(UINT16 *) Ptr;
Ptr += sizeof (UINT16);
Ptr += EfiStrSize ((UINT16 *) Ptr);
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
Ptr += DevPathLen;
*BbsEntry = (BBS_TABLE *) Ptr;
Ptr += sizeof (BBS_TABLE);
*BbsIndex = *(UINT16 *) Ptr;
Ret = TRUE;
} else {
*BbsEntry = NULL;
Ret = FALSE;
}
return Ret;
}
EFI_STATUS
BdsDeleteBootOption (
IN UINTN OptionNumber,
IN OUT UINT16 *BootOrder,
IN OUT UINTN *BootOrderSize
)
{
UINT16 BootOption[100];
UINTN Index;
EFI_STATUS Status;
UINTN Index2Del;
Status = EFI_SUCCESS;
Index2Del = 0;
SPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);
Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);
//
// adjust boot order array
//
for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {
if (BootOrder[Index] == OptionNumber) {
Index2Del = Index;
break;
}
}
if (Index != *BootOrderSize / sizeof (UINT16)) {
for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {
if (Index >= Index2Del) {
BootOrder[Index] = BootOrder[Index + 1];
}
}
*BootOrderSize -= sizeof (UINT16);
}
return Status;
}
EFI_STATUS
BdsDeleteAllInvalidLegacyBootOptions (
VOID
)
/*++
Routine Description:
Delete all the invalid legacy boot options.
Arguments:
None.
Returns:
EFI_SUCCESS - All invalide legacy boot options are deleted.
EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
EFI_NOT_FOUND - Fail to retrive variable of boot order.
Other - Error occurs while setting variable or locating
protocol.
--*/
{
UINT16 *BootOrder;
UINT8 *BootOptionVar;
UINTN BootOrderSize;
UINTN BootOptionSize;
EFI_STATUS Status;
UINT16 HddCount;
UINT16 BbsCount;
HDD_INFO *LocalHddInfo;
BBS_TABLE *LocalBbsTable;
BBS_TABLE *BbsEntry;
UINT16 BbsIndex;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
UINTN Index;
UINT16 BootOption[10];
UINT16 BootDesc[100];
BOOLEAN DescStringMatch;
Status = EFI_SUCCESS;
BootOrder = NULL;
BootOrderSize = 0;
HddCount = 0;
BbsCount = 0;
LocalHddInfo = NULL;
LocalBbsTable = NULL;
BbsEntry = NULL;
Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);
if (EFI_ERROR (Status)) {
return Status;
}
LegacyBios->GetBbsInfo (
LegacyBios,
&HddCount,
&LocalHddInfo,
&BbsCount,
&LocalBbsTable
);
BootOrder = BdsLibGetVariableAndSize (
L"BootOrder",
&gEfiGlobalVariableGuid,
&BootOrderSize
);
if (NULL == BootOrder) {
return EFI_NOT_FOUND;
}
Index = 0;
while (Index < BootOrderSize / sizeof (UINT16)) {
SPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
BootOptionVar = BdsLibGetVariableAndSize (
BootOption,
&gEfiGlobalVariableGuid,
&BootOptionSize
);
if (NULL == BootOptionVar) {
SafeFreePool (BootOrder);
return EFI_OUT_OF_RESOURCES;
}
if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {
SafeFreePool (BootOptionVar);
Index++;
continue;
}
//
// Check if BBS Description String is changed
//
DescStringMatch = FALSE;
BdsBuildLegacyDevNameString (
&LocalBbsTable[BbsIndex],
BbsIndex,
sizeof(BootDesc),
BootDesc
);
if (EfiStrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {
DescStringMatch = TRUE;
}
if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||
(LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
(LocalBbsTable[BbsIndex].BootPriority == BBS_LOWEST_PRIORITY)) &&
(LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&
DescStringMatch) {
Index++;
continue;
}
SafeFreePool (BootOptionVar);
//
// should delete
//
BdsDeleteBootOption (
BootOrder[Index],
BootOrder,
&BootOrderSize
);
}
if (BootOrderSize) {
Status = gRT->SetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
VAR_FLAG,
BootOrderSize,
BootOrder
);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?