-
Notifications
You must be signed in to change notification settings - Fork 345
Shell Application to internal command
Internal commands of the shell application are almost the same as a UEFI Application, but they have to register with the shell binary that they are compiled into. This means that they are made as libraries and use the initialization routine of the library to perform this registration. Internal commands also have a slight increase in the abilities they can have. All of this extra requirements and features are contained within ShellCommandLib and most only function when linked within the shell binary image. Your command must be linked within the shell binary to the ShellCommandLib
Internal commands have a few extra capabilities. These should be used very judiciously since these are things that cannot always be reversed once done. Registration (see below) is one of these extras. CommandInit is the initialization command that you need to call at least once.
Internal commands can get more direct access to the list of alias’ inside the shell. This includes getting the list of alias’ and checking for a single alias at a time.
Internal commands can get a list of all commands and can get access to the help command for a given command.
Internal commands can determine and change the state of the echo feature.
Internal commands can get and set the ‘exit state’ which determine whether the shell will exit upon completion of the current command. This cannot be undone once set.
Internal commands can parse and manipulate the script file. This means that they can move the ‘execution point’ of the script around within the script file.
Internal commands can add, remove, and manipulate the map names in the shell environment. There are a lot of commands having to do with map creation and manipulation. Most of these changes are hard to undo, but the ShellCommandCreateInitialMappingsAndPaths function can pretty much reset everything.
Files and Paths are manipulated vie many functions. These do not overlap with functions in the ShellLib or the Shell protocols, but extend that to be more feature rich. The major feature here is the conversion to EFI_FILE_PROTOCOL from SHELL_FILE_HANDLE and back.
The registration API is as follows:
RETURN_STATUS EFIAPI ShellCommandRegisterCommandName ( IN CONST CHAR16 *CommandString, IN SHELL_RUN_COMMAND CommandHandler, IN SHELL_GET_MAN_FILENAME GetManFileName, IN UINT32 ShellMinSupportLevel, IN CONST CHAR16 *ProfileName, IN CONST BOOLEAN CanAffectLE, IN CONST EFI_HANDLE HiiHandle, IN CONST EFI_STRING_ID ManFormatHelp );
You pass into this command:
- the string you respond to (nominally the command itself)
- the function to call when this command in invoked
- the external filename for help text
- the support level your command requires
- the profile name you are part of
- whether this command can affect ‘Lasterror’ environment variable
- the HII handle that your help text is registered with
- The String Id within HII that your text is retrievable with
These steps should handle most of the required changes. Other cleanup can be done, such as replacing PrintToken() with ShellPrintHiiEx().
Use ShellPkg/Library/UefiShellInstall1CommandsLib as your porting basis.
- Make a new directory in ShellPkg/Library called DpInstall1CommandsLib.
- Using Windows cmd.exe, change directory to ShellPkg/Library.
- Run copy UefiShellInstall1CommandsLib\UefiShellInstall1CommandsLib.* DpInstall1CommandsLib\DpInstall1CommandsLib.*
- Edit DpInstall1CommandsLib.inf
- Change BASE_NAME to DpUefiShellInstall1CommandsLib
- Generate a new GUID for FILE_GUID using Visual Studio guidgen.exe or GuidGen.
- Change [Sources] to list the DP source files (DpUefiShellInstall1CommandsLib.c/h/uni, Dp.c, Dp.h, etc)
- To [Packages] add PerformancePkg/PerformancePkg.dec
- To [LibraryClasses] add TimerLib, PerformanceLib, and DxeServicesLib
- Change [Protocols] to use
- gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED
- gEfiDriverBindingProtocolGuid # SOMETIMES_CONSUMED
- gEfiComponentName2ProtocolGuid # SOMETIMES_CONSUMED
- gEfiLoadedImageDevicePathProtocolGuid # SOMETIMES_CONSUMED
- gEfiDevicePathToTextProtocolGuid # SOMETIMES_CONSUMED
- To [Pcds] add gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize
- Change [Guids] to use gDpShellInstall1HiiGuid
- Edit DpInstall1CommandsLib.uni
- Change all instances of BCFG to DP, keeping the case of the changed item, e.g.
- Change STR_GET_HELP_BCFG to STR_GET_HELP_DP
- Change .TH bcfg to .TH dp
- Change all help text to reflect help text in DpStrings.uni.
- Change all instances of BCFG to DP, keeping the case of the changed item, e.g.
- Edit DpInstall1CommandsLib.h
- Change all instances of BCFG to DP, keeping the case of the changed item.
- Change gShellInstall1HiiHandle to gDpShellInstall1HiiHandle.
- Edit DpInstall1CommandsLib.c
- Change all instances of BCFG to DP, keeping the case of the changed item.
- Change gShellInstall1HiiHandle to gDpShellInstall1HiiHandle.
- Include DpUefiShellInstall1CommandsLib.h
- Add Dp to the start of each function name so they start with DpShell.
- Change all instances of gShellInstall1HiiHandle to gDpShellInstall1HiiHandle.
- In DpShellInstall1CommandsLibConstructor, this comment should be above HiiAddPackages().
- //
- // 3rd parameter 'HII strings array' must be name of .uni strings file followed by 'Strings', e.g. mycommands.uni must be
- // specified as 'mycommandsStrings' because the build Autogen process defines this as a string array for the strings in your
- // .uni file. Examine your Build folder under your package's DEBUG folder and you will find it defined in a xxxStrDefs.h file.
- //
- In DpUtilities.c, DpTrace.c, DpProfile.c, DpInternal.h change all instances of gHiiHandle to gDpShellInstall1HiiHandle.
- In Dp.c do the following:
- Change all instances of gHiiHandle to gDpShellInstall1HiiHandle.
- Add the following:
- #include "DpUefiShellInstall1CommandsLib.h"
- #include
- #include
- #include
- #include
- Change InitializeDp to ShellCommandRunDpInstall.
- Replace the code between GetPerformanceCounter() and ShellCommandLineParse() with the following:
- //
- // initialize the shell lib (we must be in non-auto-init...)
- //
- Status = ShellInitialize();
- ASSERT_EFI_ERROR(Status);
- Status = CommandInit();
- ASSERT_EFI_ERROR(Status);
- Edit ShellPkg/Include/Guid/ShellLibHiiGuid.h and do the following:
- Add the GUID in DpInstall1CommandsLib.inf and call it SHELL_DP_INSTALL1_HII_GUID.
- Add 'extern EFI_GUID gDpShellInstall1HiiGuid'.
- Edit ShellPkg/ShellPkg.dec and add the GUID in DpInstall1CommandsLib.inf and call it gDpShellInstall1HiiGuid.
- Edit ShellPkg/ShellPkg.dsc and do the following:
- Add ShellPkg/Library/DpInstall1CommandsLib/DpUefiShellInstall1CommandsLib.inf as a NULL library instance to Shell.inf {} section.
- Add the appropriate TimerLib and PerformanceLib drivers to the [LibraryClasses] section.
- Add the following library instances to [LibraryClasses.common]
- IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
- PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
- PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
- DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
Home
Getting Started with EDK II
Build Instructions
EDK II Platforms
EDK II Documents
EDK II Release Planning
Reporting Issues
Reporting Security Issues
Community Information
Inclusive Language
Additional Projects & Tasks
Training
Community Support
Community Virtual Meetings
GHSA GitHub Security Advisories Proceess (Draft)