b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/** @file
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Main file for attrib shell level 2 function.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync This program and the accompanying materials
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync are licensed and made available under the terms and conditions of the BSD License
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync which accompanies this distribution. The full text of the license may be found at
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync http://opensource.org/licenses/bsd-license.php
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync**/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#include "UefiShellLevel2CommandsLib.h"
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync// This function was from from the BdsLib implementation in
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync// IntelFrameworkModulePkg\Library\GenericBdsLib\BdsConnect.c
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync// function name: BdsLibConnectAllEfi
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/**
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync This function will connect all current system handles recursively. The
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync connection will finish until every handle's child handle created if it have.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync @retval EFI_SUCCESS All handles and it's child handle have been
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync connected
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync**/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncEFI_STATUS
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncEFIAPI
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncConnectAllEfi (
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync VOID
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync )
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync{
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync EFI_STATUS Status;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync UINTN HandleCount;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync EFI_HANDLE *HandleBuffer;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync UINTN Index;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Status = gBS->LocateHandleBuffer (
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync AllHandles,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync NULL,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync NULL,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync &HandleCount,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync &HandleBuffer
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync );
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync if (EFI_ERROR (Status)) {
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync return Status;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync }
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync for (Index = 0; Index < HandleCount; Index++) {
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync }
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync if (HandleBuffer != NULL) {
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync FreePool (HandleBuffer);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync }
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync return EFI_SUCCESS;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync}
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/**
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync function to load a .EFI driver into memory and possible connect the driver.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync if FileName is NULL then ASSERT.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync @param[in] FileName FileName of the driver to load
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync @param[in] Connect Whether to connect or not
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync @retval EFI_SUCCESS the driver was loaded and if Connect was
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync true then connect was attempted. Connection may
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync have failed.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync @retval EFI_OUT_OF_RESOURCES there was insufficient memory
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync**/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncEFI_STATUS
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncEFIAPI
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncLoadDriver(
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync IN CONST CHAR16 *FileName,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync IN CONST BOOLEAN Connect
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync )
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync{
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync EFI_HANDLE LoadedDriverHandle;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync EFI_STATUS Status;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync EFI_DEVICE_PATH_PROTOCOL *Node;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync EFI_DEVICE_PATH_PROTOCOL *FilePath;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync EFI_LOADED_IMAGE_PROTOCOL *LoadedDriverImage;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync LoadedDriverImage = NULL;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync FilePath = NULL;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Node = NULL;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync LoadedDriverHandle = NULL;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Status = EFI_SUCCESS;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ASSERT (FileName != NULL);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync // Fix local copies of the protocol pointers
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Status = CommandInit();
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ASSERT_EFI_ERROR(Status);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync // Convert to DEVICE_PATH
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync FilePath = gEfiShellProtocol->GetDevicePathFromFilePath(FileName);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync if (FilePath == NULL) {
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ASSERT(FALSE);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync return (EFI_INVALID_PARAMETER);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync }
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync // Use LoadImage to get it into memory
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Status = gBS->LoadImage(
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync FALSE,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync gImageHandle,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync FilePath,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync NULL,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync 0,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync &LoadedDriverHandle);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync if (EFI_ERROR(Status)) {
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_IMAGE), gShellLevel2HiiHandle, FileName, Status);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync } else {
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync // Make sure it is a driver image
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Status = gBS->HandleProtocol (LoadedDriverHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedDriverImage);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ASSERT (LoadedDriverImage != NULL);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync if ( EFI_ERROR(Status)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync || ( LoadedDriverImage->ImageCodeType != EfiBootServicesCode
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync && LoadedDriverImage->ImageCodeType != EfiRuntimeServicesCode)
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ){
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_DRIVER), gShellLevel2HiiHandle, FileName);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync // Exit and unload the non-driver image
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync gBS->Exit(LoadedDriverHandle, EFI_INVALID_PARAMETER, 0, NULL);
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync Status = EFI_INVALID_PARAMETER;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync }
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync }
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync if (!EFI_ERROR(Status)) {
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync //
// Start the image
//
Status = gBS->StartImage(LoadedDriverHandle, NULL, NULL);
if (EFI_ERROR(Status)) {
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_ERROR), gShellLevel2HiiHandle, FileName, Status);
} else {
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_LOADED), gShellLevel2HiiHandle, FileName, LoadedDriverImage->ImageBase, Status);
}
}
if (!EFI_ERROR(Status) && Connect) {
//
// Connect it...
//
Status = ConnectAllEfi();
}
//
// clean up memory...
//
if (FilePath != NULL) {
FreePool(FilePath);
}
return (Status);
}
STATIC CONST SHELL_PARAM_ITEM LoadParamList[] = {
{L"-nc", TypeFlag},
{NULL, TypeMax}
};
/**
Function for 'load' command.
@param[in] ImageHandle Handle to the Image (NULL if Internal).
@param[in] SystemTable Pointer to the System Table (NULL if Internal).
**/
SHELL_STATUS
EFIAPI
ShellCommandRunLoad (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
LIST_ENTRY *Package;
CHAR16 *ProblemParam;
SHELL_STATUS ShellStatus;
UINTN ParamCount;
EFI_SHELL_FILE_INFO *ListHead;
EFI_SHELL_FILE_INFO *Node;
ListHead = NULL;
ProblemParam = NULL;
ShellStatus = SHELL_SUCCESS;
//
// initialize the shell lib (we must be in non-auto-init...)
//
Status = ShellInitialize();
ASSERT_EFI_ERROR(Status);
//
// parse the command line
//
Status = ShellCommandLineParse (LoadParamList, &Package, &ProblemParam, TRUE);
if (EFI_ERROR(Status)) {
if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
FreePool(ProblemParam);
ShellStatus = SHELL_INVALID_PARAMETER;
} else {
ASSERT(FALSE);
}
} else {
//
// check for "-?"
//
if (ShellCommandLineGetFlag(Package, L"-?")) {
ASSERT(FALSE);
} else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
//
// we didnt get a single file to load parameter
//
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
ShellStatus = SHELL_INVALID_PARAMETER;
} else {
for ( ParamCount = 1
; ShellCommandLineGetRawValue(Package, ParamCount) != NULL
; ParamCount++
){
Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount), EFI_FILE_MODE_READ, &ListHead);
if (!EFI_ERROR(Status)) {
for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
; !IsNull(&ListHead->Link, &Node->Link)
; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
){
//
// once we have an error preserve that value, but finish the loop.
//
if (EFI_ERROR(Status)) {
LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE));
} else {
Status = LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE));
}
} // for loop for multi-open
if (EFI_ERROR(Status)) {
ShellCloseFileMetaArg(&ListHead);
} else {
Status = ShellCloseFileMetaArg(&ListHead);;
}
} else {
//
// no files found.
//
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, (CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount));
ShellStatus = SHELL_NOT_FOUND;
}
} // for loop for params
}
//
// free the command line package
//
ShellCommandLineFreeVarList (Package);
}
if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
ShellStatus = SHELL_DEVICE_ERROR;
}
return (ShellStatus);
}