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 + -
显示快捷键?