load.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 803 行 · 第 1/2 页
C
803 行
TRUE,
BmImageHandle,
FilePath,
NULL,
0,
ImageHandle
);
if (!EFI_ERROR(Status)) {
//
// Verify the image is an application (and not a driver)
//
Status = BS->HandleProtocol (*ImageHandle, &LoadedImageProtocol, &ImageInfo);
ASSERT (!EFI_ERROR(Status));
if (ImageInfo->ImageCodeType != EfiLoaderCode) {
DEBUG ((D_BM | D_INFO, "BmDefaultBootImage: Image %hs is not an application\n", FileName));
Status = BS->Exit(*ImageHandle, EFI_SUCCESS, 0, NULL);
ASSERT (!EFI_ERROR(Status));
Status = EFI_LOAD_ERROR;
} else {
DEBUG ((D_BM | D_INFO, "BmDefaultBootImage: Loaded %hs\n", FileName));
}
}
FreePool (FilePath);
if (!EFI_ERROR(Status)) {
//
// If we got here we are done.
//
goto Done;
}
//
// BugBug: This is the old code. Get rid of this when the protoype
// OSes start following the EFI specifiction!
//
//
// We found a file system on the device. Open it.
//
Dir = LibOpenRoot(Handle);
if (!Dir) {
continue;
}
Status = Dir->Open (Dir, &Root, L"EFI", EFI_FILE_MODE_READ, 0);
Dir->Close (Dir);
Dir = NULL;
if (EFI_ERROR(Status)) {
continue;
}
//
// Open the directory \EFI\BOOT on removable media
//
Root->SetPosition (Root, 0);
StrCpy(DirInfo->FileName, L"BOOT");
Status = Root->Open (Root, &Dir, DirInfo->FileName, EFI_FILE_MODE_READ, 0);
if (EFI_ERROR(Status)) {
goto Done;
}
Dir->SetPosition (Dir, 0);
for (;;) {
BufferSize = FileInfoSize;
Status = Dir->Read (Dir, &BufferSize, FileInfo);
//
// If no more directory entries, we're done
//
if (EFI_ERROR(Status) || BufferSize == 0) {
break;
}
if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) ||
!BmIsEfiImageName(FileInfo->FileName)) {
continue;
}
//
// Build a path to the image and see if we can load it
//
FileName = PoolPrint(L"EFI\\%s\\%s", DirInfo->FileName, FileInfo->FileName);
ASSERT (FileName);
FilePath = FileDevicePath (Handle, FileName);
Status = BS->LoadImage (
TRUE,
BmImageHandle,
FilePath,
NULL,
0,
ImageHandle
);
if (!EFI_ERROR(Status)) {
//
// Verify the image is an application (and not a driver)
//
Status = BS->HandleProtocol (*ImageHandle, &LoadedImageProtocol, &ImageInfo);
ASSERT (!EFI_ERROR(Status));
if (ImageInfo->ImageCodeType != EfiLoaderCode) {
DEBUG ((D_BM | D_INFO, "BmDefaultBootImage: Image %hs is not an application\n", FileName));
Status = BS->Exit(*ImageHandle, EFI_SUCCESS, 0, NULL);
ASSERT (!EFI_ERROR(Status));
Status = EFI_LOAD_ERROR;
} else {
DEBUG ((D_BM | D_INFO, "BmDefaultBootImage: Loaded %hs\n", FileName));
}
}
FreePool (FileName);
FreePool (FilePath);
if (!EFI_ERROR(Status)) {
goto Done;
}
}
Dir->Close (Dir);
Dir = NULL;
Root->Close (Root);
Root = NULL;
}
}
Status = EFI_NOT_FOUND;
*ImageHandle = NULL;
Done:
if (Root) {
Root->Close(Root);
}
if (Dir) {
Dir->Close (Dir);
}
if (FileInfo) {
FreePool (FileInfo);
}
if (DirInfo) {
FreePool (DirInfo);
}
return Status;
}
BOOLEAN
BmIsEfiImageName (
CHAR16 *FileName
)
{
// Search for ".efi" extension
while (*FileName) {
if (FileName[0] == '.' && StriCmp(FileName, L".EFI") == 0) {
return TRUE;
}
FileName += 1;
}
return FALSE;
}
EFI_STATUS
BmBootNextOption(
VOID
)
{
EFI_STATUS Status;
UINT16 BootNext;
LIST_ENTRY *Link;
BM_LOAD_OPTION *Option;
if (BmBootNext.DataSize != 0) {
//
// Get the BootNext value
//
BootNext = *(UINT16 *)BmBootNext.u.Data;
//
// Delete the BootNext environment variable
//
Status = RT->SetVariable (
VarBootNext,
&EfiGlobalVariable,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0,
NULL
);
for (Link = BmOrderedBootOptions.Flink; Link != &BmOrderedBootOptions; Link = Link->Flink) {
Option = CR(Link, BM_LOAD_OPTION, Order, BM_LOAD_OPTION_SIGNATURE);
if (Option->OptionNumber == BootNext) {
Status = BmLoad (Option, TRUE, FALSE);
}
}
}
return Status;
}
EFI_STATUS
BmLocateHandleByDiskSignatureAndPartition (
IN UINT8 MBRType,
IN UINT8 SignatureType,
IN VOID *Signature,
IN UINT32 *PartitionNumber OPTIONAL,
IN OUT UINTN *NoHandles,
OUT EFI_HANDLE **Buffer
)
{
EFI_STATUS Status;
UINTN BufferSize;
UINTN NoBlockIoHandles;
EFI_HANDLE *BlockIoBuffer;
EFI_DEVICE_PATH *DevicePath;
UINTN Index;
EFI_DEVICE_PATH *Start, *Next, *DevPath;
HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
HARDDRIVE_DEVICE_PATH HardDriveDevicePathData;
BOOLEAN Match;
BOOLEAN PreviousNodeIsHardDriveDevicePath;
//
// Initialize for GrowBuffer loop
//
BlockIoBuffer = NULL;
BufferSize = 50 * sizeof(EFI_HANDLE);
//
// Call the real function
//
while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
//
// Get list of device handles that support the BLOCK_IO Protocol.
//
Status = BS->LocateHandle (
ByProtocol,
&BlockIoProtocol,
NULL,
&BufferSize,
BlockIoBuffer
);
}
NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
if (EFI_ERROR(Status)) {
NoBlockIoHandles = 0;
}
//
// If there was an error or there are no device handles that support
// the BLOCK_IO Protocol, then return.
//
if (NoBlockIoHandles == 0) {
FreePool(BlockIoBuffer);
*NoHandles = 0;
*Buffer = NULL;
return Status;
}
//
// Loop through all the device handles that support the BLOCK_IO Protocol
//
*NoHandles = 0;
for(Index=0;Index<NoBlockIoHandles;Index++) {
Status = BS->HandleProtocol (BlockIoBuffer[Index],
&DevicePathProtocol,
(VOID*)&DevicePath
);
//
// Search DevicePath for a Hard Drive Media Device Path node.
// If one is found, then see if it matches the signature that was
// passed in. If it does match, and the next node is the End of the
// device path, and the previous node is not a Hard Drive Media Device
// Path, then we have found a match.
//
Match = FALSE;
if (DevicePath != NULL) {
PreviousNodeIsHardDriveDevicePath = FALSE;
DevPath = DevicePath;
Start = DevPath;
//
// Check for end of device path type
//
for (; ;) {
if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
//
// Ensure data structure is properly aligned.
//
CopyMem (&HardDriveDevicePathData, DevPath, sizeof (HARDDRIVE_DEVICE_PATH));
HardDriveDevicePath = &HardDriveDevicePathData;
if (PreviousNodeIsHardDriveDevicePath == FALSE) {
Next = NextDevicePathNode(DevPath);
if (IsDevicePathEndType(Next)) {
if ((HardDriveDevicePath->MBRType == MBRType) &&
(HardDriveDevicePath->SignatureType == SignatureType)) {
switch(SignatureType) {
case SIGNATURE_TYPE_MBR:
if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) {
Match = TRUE;
}
if (PartitionNumber) {
//
// If the PartitionNumber exists match on it too
//
if (*PartitionNumber != HardDriveDevicePath->PartitionNumber) {
Match = FALSE;
}
}
break;
case SIGNATURE_TYPE_GUID:
if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
Match = TRUE;
}
break;
}
}
}
}
PreviousNodeIsHardDriveDevicePath = TRUE;
} else {
PreviousNodeIsHardDriveDevicePath = FALSE;
}
if (IsDevicePathEnd(DevPath)) {
break;
}
DevPath = NextDevicePathNode(DevPath);
}
}
if (Match == FALSE) {
BlockIoBuffer[Index] = NULL;
} else {
*NoHandles = *NoHandles + 1;
}
}
//
// If there are no matches, then return
//
if (*NoHandles == 0) {
FreePool(BlockIoBuffer);
*NoHandles = 0;
*Buffer = NULL;
return EFI_SUCCESS;
}
//
// Allocate space for the return buffer of device handles.
//
*Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
if (*Buffer == NULL) {
FreePool(BlockIoBuffer);
*NoHandles = 0;
*Buffer = NULL;
return EFI_OUT_OF_RESOURCES;
}
//
// Build list of matching device handles.
//
*NoHandles = 0;
for(Index=0;Index<NoBlockIoHandles;Index++) {
if (BlockIoBuffer[Index] != NULL) {
(*Buffer)[*NoHandles] = BlockIoBuffer[Index];
*NoHandles = *NoHandles + 1;
}
}
FreePool(BlockIoBuffer);
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?