load.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 803 行 · 第 1/2 页

C
803
字号
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

    load.c

Abstract:

    EFI Boot Manager



Revision History

--*/

#include "bm.h"

//
// Internal prototypes
//

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
BmDefaultBootImage (
    IN EFI_DEVICE_PATH      *DevicePath,
    OUT EFI_HANDLE          *ImageHandle
    );


BOOLEAN
BmIsEfiImageName (
    CHAR16  *FileName
    );

//
//
//


VOID
BmLoadDrivers (
    VOID
    )
{
    LIST_ENTRY          *Link;
    BM_LOAD_OPTION      *Option;
    EFI_INPUT_KEY       Key;
    BOOLEAN             Reconnect;

    ConnectAll ();

    //
    // Display loading drivers
    //
    BmDisplay (BM_LOADING_DEVICE_DRIVERS);

    //
    // Load all images in order
    //
    Reconnect = FALSE;
    for (Link = BmOrderedDriverOptions.Flink; Link != &BmOrderedDriverOptions; Link = Link->Flink) {
        Option = CR(Link, BM_LOAD_OPTION, Order, BM_LOAD_OPTION_SIGNATURE);

        //
        // See if the user want to skip Driver Load by pressing F10
        //
        if (ST->ConIn != NULL) {
          while (ST->ConIn->ReadKeyStroke (ST->ConIn, &Key) == EFI_SUCCESS) {
            if (Key.ScanCode == SCAN_F10) {
              return;
            }
          }
        }

        if (Option->Attributes & LOAD_OPTION_FORCE_RECONNECT) {
            Reconnect = TRUE;
        }

        BmLoad (Option, FALSE, TRUE);
    }

    //
    // See if the user want to skip Driver Load by pressing F10
    //
    if (ST->ConIn != NULL) {
      while (ST->ConIn->ReadKeyStroke (ST->ConIn, &Key) == EFI_SUCCESS) {
        if (Key.ScanCode == SCAN_F10) {
          return;
        }
      }
    }

    //
    // If one of the drivers requested a FORCE_RECONNECT, then disconnect all the drivers
    //
    if (Reconnect) {
      DisconnectAll ();
    }

    //
    // Always connect all the drivers after all the driver have been loaded and initialized
    //
    ConnectAllConsoles ();
}

EFI_STATUS
BmLoad (
    IN BM_LOAD_OPTION   *Option,
    IN BOOLEAN          BootLoad,
    IN BOOLEAN          AutoBoot
    )
{
    EFI_STATUS              Status;
    EFI_HANDLE              ImageHandle;
    EFI_LOADED_IMAGE        *ImageInfo;
    CHAR16                  *LoadImage, *LoadImageFailed;
    CHAR16                  *StartImage, *StartImageFailed;
    EFI_DEVICE_PATH         *FilePath, *HardDriveFilePath;
    UINT32                  *PartitionNumber;
    UINTN                   NoHandles;
    EFI_HANDLE              *HandleBuffer;
    EFI_BLOCK_IO            *BlockIo;
    UINTN                   Index;
    HARDDRIVE_DEVICE_PATH   *HardDrive;

    //
    // Lookup some strings
    //
    LoadImage = BmString (BM_LOAD_IMAGE);
    LoadImageFailed = BmString (BM_LOAD_IMAGE_FAILED);

    StartImage = BmString (BM_START_IMAGE);
    StartImageFailed = BmString (BM_START_IMAGE_FAILED);

    //
    // Connect the drivers required to access the device specified by Option->FilePath
    //
    ConnectDevicePath (Option->FilePath);

    //
    // Load the image
    //
    DEBUG((D_BM | D_INFO, "BM: Loading driver %s:%s\n", 
                Option->Name,
                Option->Description
                ));

    //
    // Set BootCurrent variable
    //
    BmSetBootCurrent(TRUE, (UINT16)Option->OptionNumber);

    //
    // Load this image
    //
    if (Option->FilePath->Type == BBS_DEVICE_PATH && 
        Option->FilePath->SubType == BBS_BBS_DP    ) {
        //
        // If the device path starts with a BBS device path entry
        //  call into platform code to boot the legacy PC AT way
        //
        if (BmBootLegacy != NULL) {
            Status = BmBootLegacy->BootIt (Option->FilePath);
            if (EFI_ERROR(Status)) {
                Print (LoadImageFailed, Option->Description, Status);
                if (!AutoBoot) {
                    BmPause ();
                }
                goto Done;
            }
        } else {
            //
            // Booting from legacy devices not support on this platform
            //
            Status = EFI_UNSUPPORTED;
            goto Done;
        }
    }

    //
    // If the device path starts with a Media Hard drive node expand it
    //  to be a full device path. Add in the pointer to the hard disk controller.
    //  this allows a disk to move around and we can still boot from it.
    //
    FilePath = Option->FilePath;
    HardDriveFilePath = NULL;
    if (FilePath->Type == MEDIA_DEVICE_PATH &&
        FilePath->SubType == MEDIA_HARDDRIVE_DP) {

        HardDrive = (HARDDRIVE_DEVICE_PATH *)FilePath;

        PartitionNumber = (HardDrive->MBRType == SIGNATURE_TYPE_MBR) ? &HardDrive->PartitionNumber : NULL;
        BmLocateHandleByDiskSignatureAndPartition (
            HardDrive->MBRType,
            HardDrive->SignatureType,
            HardDrive->Signature,
            PartitionNumber,
            &NoHandles,
            &HandleBuffer
            );

        if (HandleBuffer) {
            for (Index = 0; Index < NoHandles; Index++) {
                Status = BS->HandleProtocol (HandleBuffer[Index], &BlockIoProtocol, (VOID*)&BlockIo);
                if (EFI_ERROR(Status)) {
                    continue;
                }
                if (BlockIo->Media->RemovableMedia) {
                    //
                    // Skip removeable media devices
                    //
                    continue;
                }

                HardDriveFilePath = DevicePathFromHandle (HandleBuffer[Index]);
                if (HardDriveFilePath) {
                    //
                    // We have now converted the Media Hard drive node to a 
                    //  device path that ends in the Media Hard drive node.
                    //  So add the file name at the end and we are done
                    //
                    FilePath = AppendDevicePath (
                                    HardDriveFilePath, 
                                    NextDevicePathNode (Option->FilePath)
                                    );

                    //
                    // Save the pointer so we can free it later
                    //
                    HardDriveFilePath = FilePath;
                    break;
                }
            }

            FreePool (HandleBuffer);
        }
    }

    Print (LoadImage, Option->Description);
    Status = BS->LoadImage(
                BootLoad,
                BmImageHandle,
                FilePath,
                NULL,
                0,
                &ImageHandle
                );

    if (Status == EFI_ALREADY_STARTED) {
        //
        // If image is linked in it will retun EFI_ALREADY_STARTED
        //  thus emulate a load
        //
        Status = EFI_SUCCESS;
        goto Done;
    }

    //
    // If we didn't find an image, and this is a BootLoad request we
    // may need to implement the default boot behaviour for the device.
    // The boot manager only implements the default boot behaviour for
    // filesystem devices.  Other default behaviour is handled by the 
    // device itself in the previous LoadImage request.
    //

    if (EFI_ERROR(Status) && BootLoad) {
        Status = BmDefaultBootImage (FilePath, &ImageHandle);
    }

    BmClearLine ();

    //
    // If image failed to load print a message
    //
    if (EFI_ERROR(Status)) {
        Print (LoadImageFailed, Option->Description, Status);
        if (!AutoBoot) {
            BmPause ();
        }
        goto Done;
    }    

    //
    // Provide the image with it's load optins
    //
    Status = BS->HandleProtocol (ImageHandle, &LoadedImageProtocol, &ImageInfo);
    ASSERT (!EFI_ERROR(Status));
    if (Option->LoadOptionsSize) {
        ImageInfo->LoadOptionsSize = (UINT32) Option->LoadOptionsSize;
        ImageInfo->LoadOptions = Option->LoadOptions;
    }

    //
    // Start the image
    //
    Print (StartImage, Option->Description);

    //
    // Before calling the image, enable the Watchdog Timer for the 5 Minute period
    //

    BS->SetWatchdogTimer ( 5 * 60, 0x0000, 0x00, NULL );
    
    Status = BS->StartImage (ImageHandle, 0, NULL);

    BS->SetWatchdogTimer ( 0x0000, 0x0000, 0x0000, NULL );

    //
    // If image failed to start print a message
    //
    if (EFI_ERROR(Status)) {
        Print (StartImageFailed, Option->Description, Status);
        if (!AutoBoot) {
            BmPause ();
        }
        goto Done;
    }    

Done:    

    if (HardDriveFilePath) {
        FreePool (HardDriveFilePath);
    }

    //
    // Delete BootCurrent variable
    //
    BmSetBootCurrent(FALSE, 0);

    BmNewLine();
    return Status;
}


EFI_STATUS
BmDefaultBootImage (
    IN EFI_DEVICE_PATH      *TargetDevice,
    OUT EFI_HANDLE          *ImageHandle
    )
{
    UINTN                   PathSize;
    EFI_STATUS              Status;
    UINTN                   NoHandles, Index;
    EFI_HANDLE              *Handles;
    EFI_HANDLE              Handle;
    EFI_FILE_HANDLE         Root, Dir;
    UINTN                   FileInfoSize, BufferSize;
    EFI_FILE_INFO           *FileInfo, *DirInfo;
    CHAR16                  *FileName;    
    EFI_DEVICE_PATH         *FilePath, *DevicePath;
    EFI_LOADED_IMAGE        *ImageInfo;

    Root = NULL;
    Dir = NULL;

    PathSize = DevicePathSize(TargetDevice) - sizeof(EFI_DEVICE_PATH);

    FileInfoSize = sizeof(EFI_FILE_HANDLE) + 1024;
    FileInfo = AllocatePool (FileInfoSize);
    DirInfo = AllocatePool (FileInfoSize);
    ASSERT (FileInfo && DirInfo);

    
    //
    // Find all file system handles
    //
    LibLocateHandle (ByProtocol, &FileSystemProtocol, NULL, &NoHandles, &Handles);
    for (Index=0; Index < NoHandles; Index++) {
        Handle = Handles[Index];

        //
        // See if this is a file system on the same device
        //
        // BUGBUG: this doesn't handle instance paths
        DevicePath = DevicePathFromHandle (Handle);
        if (TargetDevice && CompareMem(DevicePath, TargetDevice, PathSize) == 0) {
            //
            // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI
            //  machinename is ia32, ia64, ...
            //
            FilePath = FileDevicePath (Handle, DEFAULT_REMOVABLE_FILE_NAME);
            Status = BS->LoadImage (

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?