bbssupport.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,604 行 · 第 1/3 页
C
1,604 行
} else {
EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
}
SafeFreePool (BootOrder);
return Status;
}
BOOLEAN
BdsFindLegacyBootOptionByDevType (
IN UINT16 *BootOrder,
IN UINTN BootOptionNum,
IN UINT16 DevType,
OUT UINT32 *Attribute,
OUT UINT16 *BbsIndex,
OUT UINTN *OptionNumber
)
{
UINTN Index;
UINTN BootOrderIndex;
UINT16 BootOption[100];
UINTN BootOptionSize;
UINT8 *BootOptionVar;
BBS_TABLE *BbsEntry;
BOOLEAN Found;
BbsEntry = NULL;
Found = FALSE;
if (NULL == BootOrder) {
return Found;
}
for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {
Index = (UINTN) BootOrder[BootOrderIndex];
SPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);
BootOptionVar = BdsLibGetVariableAndSize (
BootOption,
&gEfiGlobalVariableGuid,
&BootOptionSize
);
if (NULL == BootOptionVar) {
continue;
}
if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {
SafeFreePool (BootOptionVar);
continue;
}
if (BbsEntry->DeviceType != DevType) {
SafeFreePool (BootOptionVar);
continue;
}
*Attribute = *(UINT32 *) BootOptionVar;
*OptionNumber = Index;
Found = TRUE;
SafeFreePool (BootOptionVar);
break;
}
return Found;
}
EFI_STATUS
BdsCreateOneLegacyBootOption (
IN BBS_TABLE *BbsItem,
IN UINTN Index,
IN OUT UINT16 **BootOrderList,
IN OUT UINTN *BootOrderListSize
)
{
BBS_BBS_DEVICE_PATH BbsDevPathNode;
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevPath;
DevPath = NULL;
BbsDevPathNode.Header.Type = BBS_DEVICE_PATH;
BbsDevPathNode.Header.SubType = BBS_BBS_DP;
SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));
BbsDevPathNode.DeviceType = BbsItem->DeviceType;
EfiCopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));
DevPath = EfiAppendDevicePathNode (
EndDevicePath,
(EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode
);
if (NULL == DevPath) {
return EFI_OUT_OF_RESOURCES;
}
Status = BdsCreateLegacyBootOption (
BbsItem,
DevPath,
Index,
BootOrderList,
BootOrderListSize
);
BbsItem->BootPriority = 0x00;
gBS->FreePool (DevPath);
return Status;
}
EFI_STATUS
BdsAddNonExistingLegacyBootOptions (
VOID
)
/*++
Routine Description:
Add the legacy boot options from BBS table if they do not exist.
Arguments:
None.
Returns:
EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
others - An error occurred when creating legacy boot options.
--*/
{
UINT16 *BootOrder;
UINTN BootOrderSize;
EFI_STATUS Status;
UINT16 HddCount;
UINT16 BbsCount;
HDD_INFO *LocalHddInfo;
BBS_TABLE *LocalBbsTable;
UINT16 BbsIndex;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
UINTN Index;
UINT32 Attribute;
UINTN OptionNumber;
BOOLEAN Ret;
BootOrder = NULL;
HddCount = 0;
BbsCount = 0;
LocalHddInfo = NULL;
LocalBbsTable = 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) {
BootOrderSize = 0;
}
for (Index = 0; Index < BbsCount; Index++) {
if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
(LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
) {
continue;
}
Ret = BdsFindLegacyBootOptionByDevType (
BootOrder,
BootOrderSize / sizeof (UINT16),
LocalBbsTable[Index].DeviceType,
&Attribute,
&BbsIndex,
&OptionNumber
);
if (Ret && (Attribute & LOAD_OPTION_ACTIVE) != 0) {
continue;
}
if (Ret) {
if (Index != BbsIndex) {
BdsDeleteBootOption (
OptionNumber,
BootOrder,
&BootOrderSize
);
} else {
continue;
}
}
//
// Not found such type of legacy device in boot options or we found but it's disabled
// so we have to create one and put it to the tail of boot order list
//
Status = BdsCreateOneLegacyBootOption (
&LocalBbsTable[Index],
Index,
&BootOrder,
&BootOrderSize
);
if (EFI_ERROR (Status)) {
break;
}
}
if (BootOrderSize > 0) {
Status = gRT->SetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
VAR_FLAG,
BootOrderSize,
BootOrder
);
} else {
EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
}
if (BootOrder != NULL) {
SafeFreePool (BootOrder);
}
return Status;
}
UINT16 *
BdsFillDevOrderBuf (
IN BBS_TABLE *BbsTable,
IN BBS_TYPE BbsType,
IN UINTN BbsCount,
IN UINT16 *Buf
)
{
UINTN Index;
for (Index = 0; Index < BbsCount; Index++) {
if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
continue;
}
if (BbsTable[Index].DeviceType != BbsType) {
continue;
}
*Buf = (UINT16) (Index & 0xFF);
Buf++;
}
return Buf;
}
EFI_STATUS
BdsCreateDevOrder (
IN BBS_TABLE *BbsTable,
IN UINT16 BbsCount
)
{
UINTN Index;
UINTN FDCount;
UINTN HDCount;
UINTN CDCount;
UINTN NETCount;
UINTN BEVCount;
UINTN TotalSize;
UINTN HeaderSize;
UINT8 *DevOrder;
UINT8 *Ptr;
EFI_STATUS Status;
FDCount = 0;
HDCount = 0;
CDCount = 0;
NETCount = 0;
BEVCount = 0;
TotalSize = 0;
HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
DevOrder = NULL;
Ptr = NULL;
Status = EFI_SUCCESS;
for (Index = 0; Index < BbsCount; Index++) {
if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
continue;
}
switch (BbsTable[Index].DeviceType) {
case BBS_FLOPPY:
FDCount++;
break;
case BBS_HARDDISK:
HDCount++;
break;
case BBS_CDROM:
CDCount++;
break;
case BBS_EMBED_NETWORK:
NETCount++;
break;
case BBS_BEV_DEVICE:
BEVCount++;
break;
default:
break;
}
}
TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);
TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);
TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);
TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);
TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);
DevOrder = EfiAllocateZeroPool (TotalSize);
if (NULL == DevOrder) {
return EFI_OUT_OF_RESOURCES;
}
Ptr = DevOrder;
*((BBS_TYPE *) Ptr) = BBS_FLOPPY;
Ptr += sizeof (BBS_TYPE);
*((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
Ptr += sizeof (UINT16);
if (FDCount) {
Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);
}
*((BBS_TYPE *) Ptr) = BBS_HARDDISK;
Ptr += sizeof (BBS_TYPE);
*((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
Ptr += sizeof (UINT16);
if (HDCount) {
Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);
}
*((BBS_TYPE *) Ptr) = BBS_CDROM;
Ptr += sizeof (BBS_TYPE);
*((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
Ptr += sizeof (UINT16);
if (CDCount) {
Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);
}
*((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;
Ptr += sizeof (BBS_TYPE);
*((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
Ptr += sizeof (UINT16);
if (NETCount) {
Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);
}
*((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;
Ptr += sizeof (BBS_TYPE);
*((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
Ptr += sizeof (UINT16);
if (BEVCount) {
Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);
}
Status = gRT->SetVariable (
VarLegacyDevOrder,
&EfiLegacyDevOrderGuid,
VAR_FLAG,
TotalSize,
DevOrder
);
SafeFreePool (DevOrder);
return Status;
}
EFI_STATUS
BdsUpdateLegacyDevOrder (
VOID
)
/*++
Format of LegacyDevOrder variable:
|-----------------------------------------------------------------------------------------------------------------
| BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
|-----------------------------------------------------------------------------------------------------------------
Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.
Index# is a 16 bit integer, the low byte of it stands for the index in BBS table
the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been
disabled by user.
--*/
{
UINT8 *DevOrder;
UINT8 *NewDevOrder;
UINTN DevOrderSize;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
EFI_STATUS Status;
UINT16 HddCount;
UINT16 BbsCount;
HDD_INFO *LocalHddInfo;
BBS_TABLE *LocalBbsTable;
UINTN Index;
UINTN Index2;
UINTN *Idx;
UINTN FDCount;
UINTN HDCount;
UINTN CDCount;
UINTN NETCount;
UINTN BEVCount;
UINTN TotalSize;
UINTN HeaderSize;
UINT8 *Ptr;
UINT8 *NewPtr;
UINT16 *NewFDPtr;
UINT16 *NewHDPtr;
UINT16 *NewCDPtr;
UINT16 *NewNETPtr;
UINT16 *NewBEVPtr;
UINT16 *NewDevPtr;
UINT16 Length;
UINT16 tmp;
UINTN FDIndex;
UINTN HDIndex;
UINTN CDIndex;
UINTN NETIndex;
UINTN BEVIndex;
LocalHddInfo = NULL;
LocalBbsTable = NULL;
Idx = NULL;
FDCount = 0;
HDCount = 0;
CDCount = 0;
NETCount = 0;
BEVCount = 0;
TotalSize = 0;
HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
FDIndex = 0;
HDIndex = 0;
CDIndex = 0;
NETIndex = 0;
BEVIndex = 0;
NewDevPtr = NULL;
Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);
if (EFI_ERROR (Status)) {
return Status;
}
LegacyBios->GetBbsInfo (
LegacyBios,
&HddCount,
&LocalHddInfo,
&BbsCount,
&LocalBbsTable
);
DevOrder = (UINT8 *) BdsLibGetVariableAndSize (
VarLegacyDevOrder,
&EfiLegacyDevOrderGuid,
&DevOrderSize
);
if (NULL == DevOrder) {
return BdsCreateDevOrder (LocalBbsTable, BbsCount);
}
//
// First we figure out how many boot devices with same device type respectively
//
for (Index = 0; Index < BbsCount; Index++) {
if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
(LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
(LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY)
) {
continue;
}
switch (LocalBbsTable[Index].DeviceType) {
case BBS_FLOPPY:
FDCount++;
break;
case BBS_HARDDISK:
HDCount++;
break;
case BBS_CDROM:
CDCount++;
break;
case BBS_EMBED_NETWORK:
NETCount++;
break;
case BBS_BEV_DEVICE:
BEVCount++;
break;
default:
break;
}
}
TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
NewDevOrder = EfiAllocateZeroPool (TotalSize);
if (NULL == NewDevOrder) {
return EFI_OUT_OF_RESOURCES;
}
NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize);
NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);
NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);
NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);
NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);
//
// copy FD
//
Ptr = DevOrder;
NewPtr = NewDevOrder;
*((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?