boot.c

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

C
1,972
字号
    *LoadOptionSize = 0;   
    Print (L"\n    New BootOption Data. ASCII/Unicode strings only, with max of %d characters\n", MAX_CHAR);
    
    Ascii = FALSE;
    
    BmntClearLine();
    ConOut->SetAttribute (ConOut, BootMenu.ReverseScreenAttribute);
    Print (L"    Enter BootOption Data Type [A-Ascii U-Unicode N-No BootOption] : ");
    WaitForSingleEvent (ConIn->WaitForKey, 0);
    ConIn->ReadKeyStroke (ConIn, &Key);

    switch (Key.UnicodeChar) {
    case 'N':
    case 'n':
        Print(L" None\n");
        ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);   
        return (EFI_SUCCESS);
    case 'A':
    case 'a':
        Ascii = TRUE;
        Print(L" Ascii");
        Print (L"\n    Enter BootOption Data [Data will be stored as Ascii string]:");
        break;
    case 'U':
    case 'u':
    default :
        Print (L" Unicode");
        Print (L"\n    Enter BootOption Data [Data will be stored as Unicode string]: ");
        break;
    } 

    ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);   
    Print (L"\n");   

    TempStr = (CHAR16 *) AllocateZeroPool(SizeLoadOptionStr);
    ASSERT(TempStr);
    Input (L" ", TempStr, SizeLoadOptionStr);

    if (Ascii) {
        AsciiChar = (CHAR8 *)LoadOptionStr;
        TempStr1 = TempStr;
        for(;*TempStr1 != CHAR_NULL;TempStr1++) {
            // Convert to ASCII
            *AsciiChar = (CHAR8)*TempStr1;
            *LoadOptionSize += 1;
            AsciiChar++;
        }
        
        // Check to see if any boot options were added
        // LoadOptionSize would be non-zero if something was entered at input
        // if something was added then increment LoadOptionSize by 1 so that 
        // we can capture the Null string terminator character as well
        if (*LoadOptionSize) {
            *LoadOptionSize += 1;
            *AsciiChar = '\0';
        }
    } else {
        StrCpy(LoadOptionStr,TempStr);   
        *LoadOptionSize = StrSize(LoadOptionStr);
    }

    FreePool(TempStr);

    return EFI_SUCCESS;
}


EFI_STATUS
BootTheOption (
    IN  FILE_MENU_CONTEXT   *Context,
    IN  BOOT_MENU_CONTEXT   *BootOption
    )
{
    EFI_STATUS              Status;
    EFI_DEVICE_PATH         *DevicePath;
    EFI_HANDLE              ImageHandle;
    LEGACY_BOOT_INTERFACE   *BootLegacy;
    
    DevicePath = Context->DevicePath;
    if (DevicePath->Type == BBS_DEVICE_PATH && 
        DevicePath->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
        //
        LibLocateProtocol (&LegacyBootProtocol, &BootLegacy);
        if (BootLegacy) {
            Status = BootLegacy->BootIt (DevicePath);
            if (EFI_ERROR(Status)) {
                Print (L"Start of %s failed: %r\n", BootOption->Description, Status);
                BootPause ();
                return Status;
            }
        } else {
            //
            // Booting from legacy devices not support on this platform
            //
            ASSERT(FALSE);
            return EFI_UNSUPPORTED;
        }
    }

    if (Context->IsRemovableMedia) {
        Status = DefaultBootTheBootOption (Context, BootOption, &ImageHandle);
        if (EFI_ERROR(Status)) {
            return Status;
        }
    } else {
        Status = BS->LoadImage(TRUE, GlobalImageHandle, DevicePath, NULL, 0, &ImageHandle);
        if (EFI_ERROR(Status)) {
            return Status;
        }
    }
    
    //
    // Before calling the image, enable the Watchdog Timer for the 5 Minute period
    //

    Status = BS->StartImage (ImageHandle, 0, NULL);

    if (EFI_ERROR(Status)) {
    }
    return Status;
}

EFI_STATUS
DefaultBootTheBootOption (
    IN  FILE_MENU_CONTEXT   *Context,
    IN  BOOT_MENU_CONTEXT   *BootOption,
    OUT EFI_HANDLE          *ImageHandle
    )
{
    UINTN                   PathSize;
    EFI_STATUS              Status;
    UINTN                   NoHandles, Index;
    EFI_HANDLE              *Handles;
    EFI_HANDLE              Handle;
    EFI_FILE_HANDLE         EfiBoot, Dir;
    UINTN                   FileInfoSize, BufferSize;
    EFI_FILE_INFO           *FileInfo;
    CHAR16                  *FileName;    
    EFI_DEVICE_PATH         *FilePath, *DevicePath;
    EFI_LOADED_IMAGE        *ImageInfo;
    EFI_BLOCK_IO            *BlkIo;
    VOID                    *Buffer;

    EfiBoot = NULL;
    Dir = NULL;

    ASSERT (Context->DevicePath);
    PathSize = DevicePathSize(Context->DevicePath) - sizeof(EFI_DEVICE_PATH);

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

    //
    // Read a block just in case we booted without the media in place
    // This will allow for the FileSystemProtocol to be found when attempting
    // to boot from the device in that case.
    //
    LibLocateHandle (ByProtocol, &BlockIoProtocol, NULL, &NoHandles, &Handles);
    for (Index=0; Index < NoHandles; Index++) {
      Handle = Handles[Index];
      
      DevicePath=DevicePathFromHandle (Handle);

      if (CompareMem(DevicePath, Context->DevicePath, PathSize) != 0) {
        continue;
      }

      Status = BS->HandleProtocol(Handle, &BlockIoProtocol, (VOID **)&BlkIo);
        if (!EFI_ERROR(Status)) {
            if (!BlkIo->Media->LogicalPartition) {
                Buffer = AllocatePool (BlkIo->Media->BlockSize);
                BlkIo->ReadBlocks (BlkIo, BlkIo->Media->MediaId, 0, BlkIo->Media->BlockSize, Buffer);
                FreePool (Buffer);
            }
        }
    }
    //
    // 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 (!DevicePath) {
            continue;
        }
        if (CompareMem(DevicePath, Context->DevicePath, PathSize) != 0) {
            //
            // Match on the first part of the device path
            //
            continue;
        }

        //
        // We found a file system on the device.  Open it.
        //
        Dir = LibOpenRoot(Handle);
        if (!Dir) {
            continue;
        }

        Status = Dir->Open (Dir, &EfiBoot, L"EFI", EFI_FILE_MODE_READ, 0);
        Dir->Close (Dir);
        if (EFI_ERROR(Status)) {
            continue;
        }
        Status = EfiBoot->Open (EfiBoot, &Dir, L"BOOT", EFI_FILE_MODE_READ, 0);
        EfiBoot->Close (EfiBoot);
        if (EFI_ERROR(Status)) {
            continue;
        }

        //
        // Check the Boot directory for a bootable image
        //
        Dir->SetPosition (Dir, 0);
        for (; ;) {

            BufferSize = FileInfoSize;
            Status = Dir->Read (Dir, &BufferSize, FileInfo);

            //
            // If at the end of the search, we're done
            //
            if (EFI_ERROR(Status) || BufferSize == 0) {
                break;
            }

            //
            // If it not an image name, skip it
            //
            if ((FileInfo->Attribute & EFI_FILE_DIRECTORY)  /*||
                !IsEfiImageName(FileInfo->FileName)*/) {
                continue;
            }

            //
            // Build a path to the image and see if we can load it
            //
            FileName = PoolPrint(L"\\EFI\\BOOT\\%s", FileInfo->FileName);
            ASSERT (FileName);
            FilePath = FileDevicePath (Handle, FileName);

            Status = BS->LoadImage (
                        TRUE,
                        GlobalImageHandle,
                        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, "DefaultBootImage: 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)) {
                Dir->Close (Dir);
                FreePool (FileInfo);
                return Status;
            }
        }

        Dir->Close (EfiBoot);
    }

    *ImageHandle = NULL;
    if (FileInfo) {
        FreePool (FileInfo);
    }
    return EFI_NOT_FOUND;
}

BOOLEAN
IsEfiImageName (
    CHAR16  *FileName
    )
{
    // Search for ".efi" extension
    while (*FileName) {
        if (FileName[0] == '.' && StriCmp(FileName, L".EFI") == 0) {
            return TRUE;
        }
        FileName += 1;
    }
    return FALSE;
}

BOOLEAN
PrintBootHelp(
    IN  CHAR16      *Description
    )
{
    SIMPLE_TEXT_OUTPUT_INTERFACE    *ConOut;
    EFI_STATUS                      Status;
    UINTN                           MaxColumn, ScreenSize;
    UINTN                           Row,Col;
    UINTN                           Size,PrintSize;
    BOOLEAN                         Done;
    CHAR16                          *TempStr;

    ConOut = ST->ConOut;

    InitializeListHead (&BootOrderHelpMenu.Head);

    Status = ConOut->SetAttribute (ConOut, BootOrderHelpMenu.ScreenAttribute);
    ASSERT (!EFI_ERROR (Status));
    ConOut->EnableCursor(ConOut, FALSE);
    if (BootOrderHelpMenu.ClearScreen) {
        Status = ConOut->ClearScreen (ConOut);
        ASSERT (!EFI_ERROR (Status));
    }
    ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &MaxColumn, &ScreenSize);
    Print (BootOrderHelpMenu.Header);

    Size = StrSize(Description)/sizeof(CHAR16);
    TempStr = Description;

    Col = MaxColumn - BootOrderHelpMenu.Col*2;

    Done = FALSE;
    for (Row = 2;!Done; ) {
        if( Size > Col) {
            PrintSize = Col;
        } else {
            PrintSize = Size;
            Done = TRUE;
        }

        PrintAt(BootOrderHelpMenu.Col, Row, L"%-.*s", PrintSize, TempStr);
        Size -= PrintSize;
        TempStr = TempStr + PrintSize;   
        Row++;
    }

    return TRUE;
}

EFI_STATUS
Bmnt_DisplayDeleteBootMenu (
    VOID
    ) 
{
    BOOT_MENU_CONTEXT       *ResultContext;
    BOOT_MENU_CONTEXT       *PreviousResultContext;
    BOOT_MENU_CONTEXT       *SaveNvramContext;
    BOOT_MENU_CONTEXT       *DeleteAllContext;
    BOOT_MENU_CONTEXT       *DeleteHelpContext;
    BOOT_MENU_CONTEXT       *DeleteExitContext;
    BOOLEAN                 NVRAMNeedsUpdating;
    UINTN                   MenuOption;
    EFI_INPUT_KEY           Key;
    EFI_STATUS              Status;
    BOOLEAN                 Done;
    UINTN                   EndRow;
    UINTN                   MaxColumn, ScreenSize;
    BOOLEAN                 Exit;
    CHAR16                  *Header = L"%EDelete Boot Option(s).  Select an Option\n\n";

    // 
    // initialize header text
    //
    FreeBootOrderMenuOfVariables();
    InitializeBootOrderMenuFromVariable();

    BootMenu.Header = Header;
    DeleteAllContext =

⌨️ 快捷键说明

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