The three examples listed in the EFI Shell Developers Guide (the latest version is 0.91 dated June 27, 2005) have never been updated to reflect the TianoCore UEFI development environment. I have modified the sources for the three examples so that they now successfully build in the TianoCore EDK. This post assumes that you are familiar with UEFI and the EFI Developers Kit. It does not attempt to explain the content of the files. Please read the EFI Shell Developers Guide if you need a detailed explanation.
Example 1 – HelloWorld
// // HelloWorld.h // #ifndef _EFI_HELLOWORLD_H_ #define _EFI_HELLOWORLD_H_ #define EFI_HELLOWORLD_GUID {0x6435f523, 0x5cd3, 0x444f, 0xa4, 0x23, 0x83, 0x4f, 0xbb, 0x71, 0x29, 0xc7} #endif
// // HelloWorldStrings.uni // /=# #langdef eng "English" #string STR_HELLO #language eng "Hello World\n" #string STR_GOODBYE #language eng "Goodbye World\n"
// // HelloWorld.c // #include "EfiShellLib.h" #include "HelloWorld.h" #include STRING_DEFINES_FILE extern UINT8 STRING_ARRAY_NAME[]; EFI_HII_HANDLE HiiHandle; EFI_GUID HelloGuid = EFI_HELLOWORLD_GUID; EFI_BOOTSHELL_CODE( EFI_APPLICATION_ENTRY_POINT(HelloMain) ) EFI_STATUS HelloMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { EFI_SHELL_APP_INIT (ImageHandle, SystemTable); EFI_SHELL_STR_INIT (HiiHandle, STRING_ARRAY_NAME, HelloGuid); PrintToken (STRING_TOKEN(STR_HELLO), HiiHandle); PrintToken (STRING_TOKEN(STR_GOODBYE), HiiHandle); LibUnInitializeStrings(); return EFI_SUCCESS; }
# # HelloWorld.inf # # Component description file # [defines] BASE_NAME = HelloWorld FILE_GUID = 0B2E45BA-3539-4a2a-B853-3723E3CAAB1B COMPONENT_TYPE = APPLICATION [sources.common] HelloWorldStrings.uni HelloWorld.c [includes.common] . ..\Inc ..\Library $(EDK_SOURCE)\Foundation $(EDK_SOURCE)\Foundation\Core\Dxe $(EDK_SOURCE)\Foundation\Efi $(EDK_SOURCE)\Foundation\Efi\Include $(EDK_SOURCE)\Foundation\Framework $(EDK_SOURCE)\Foundation\Framework\Include $(EDK_SOURCE)\Foundation\Include $(EDK_SOURCE)\Foundation\Include\IndustryStandard $(DEST_DIR)\ [libraries.common] EfiShellLib [nmake.common] IMAGE_ENTRY_POINT = HelloMain C_STD_FLAGS=$(C_STD_FLAGS) /DSTRING_ARRAY_NAME=$(BASE_NAME)Strings C_STD_FLAGS=$(C_STD_FLAGS) /DSTRING_DEFINES_FILE=\"$(BASE_NAME)StrDefs.h\" C_STD_FLAGS=$(C_STD_FLAGS) /DEFI_BOOTSHELL
Example 2 – UseArg
// // UseArg.c // #include "EfiShellLib.h" #ifdef EFI_BOOTSHELL EFI_APPLICATION_ENTRY_POINT (UseArgMain) #endif EFI_STATUS UseArgMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { UINTN Index; EFI_SHELL_APP_INIT (ImageHandle, SystemTable); Print (L"The arguments are:\n"); for (Index = 0; Index < SI->Argc; Index++) { Print (L"%s\n", SI->Argv[Index]); } return EFI_SUCCESS; }
# # UseArg.inf # # Component description file # [defines] BASE_NAME = UseArg FILE_GUID = 181157FA-77B2-4798-B3F7-003756ECE6ED COMPONENT_TYPE = APPLICATION [sources.common] UseArg.c [includes.common] . ..\Inc ..\Library $(EDK_SOURCE)\Foundation $(EDK_SOURCE)\Foundation\Core\Dxe $(EDK_SOURCE)\Foundation\Efi $(EDK_SOURCE)\Foundation\Efi\Include $(EDK_SOURCE)\Foundation\Framework $(EDK_SOURCE)\Foundation\Framework\Include $(EDK_SOURCE)\Foundation\Include $(EDK_SOURCE)\Foundation\Include\IndustryStandard $(DEST_DIR)\ [libraries.common] EfiShellLib [nmake.common] IMAGE_ENTRY_POINT=UseArgMain C_STD_INCLUDE= C_STD_FLAGS=$(C_STD_FLAGS) /DEFI_BOOTSHELL
Example 3 – UseVar
// // UseVar.h // #ifndef _EFI_USEVAR_H_ #define _EFI_USEVAR_H_ #define VAR_NAME L"SampleVar" #define EFI_USEVAR_GUID {0xe35ab40b, 0x1116, 0x43a3, 0x91, 0x41, 0xa3, 0xcd, 0xa8, 0x85, 0x1, 0xb7} #define VAR_GUID {0x11299421, 0xa2a5, 0x4206, 0xb1, 0x93, 0x9c, 0xf3, 0xe8, 0x21, 0x29, 0x5c} #endif
// // UseVar.c // #include "EfiShellLib.h" #include "UseVar.h" #include STRING_DEFINES_FILE extern UINT8 STRING_ARRAY_NAME[]; // prototypes BOOLEAN IsQuoted (void); EFI_STATUS OutputVar (EFI_HII_HANDLE); EFI_STATUS WriteVar (CHAR16 *, EFI_HII_HANDLE); #ifdef EFI_BOOTSHELL EFI_APPLICATION_ENTRY_POINT (UseVarMain) #endif EFI_STATUS UseVarMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { EFI_HII_HANDLE HiiHandle; EFI_STATUS Status = EFI_SUCCESS; EFI_GUID StrGuid = EFI_USEVAR_GUID; EFI_SHELL_APP_INIT (ImageHandle, SystemTable); EFI_SHELL_STR_INIT (HiiHandle, STRING_ARRAY_NAME, StrGuid); switch (SI->Argc) { case 1: Status = OutputVar (HiiHandle); break; case 2: if (!StriCmp (SI->Argv[1], L"-?") && !IsQuoted ()) { PrintToken (STRING_TOKEN(STR_USAGE), HiiHandle); break; } Status = WriteVar (SI->Argv[1], HiiHandle); break; default: PrintToken (STRING_TOKEN(STR_USAGE), HiiHandle); break; } LibUnInitializeStrings (); return Status; } EFI_STATUS OutputVar (EFI_HII_HANDLE HiiHandle) { EFI_STATUS Status; EFI_GUID VarGuid = VAR_GUID; UINTN BufferSize = 0; VOID *Buffer = NULL; // Pass in a zero size buffer to find the required buffer size. Status = RT->GetVariable (VAR_NAME, &VarGuid, NULL, &BufferSize, Buffer); if (Status == EFI_BUFFER_TOO_SMALL) { // Allocate the buffer to hold the content of variable Status = BS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer); if (EFI_ERROR (Status)) { return Status; } // // Read variable into the allocated buffer. // Status = RT->GetVariable (VAR_NAME, &VarGuid, NULL, &BufferSize, Buffer); if (EFI_ERROR (Status)) { return Status; } } else if (EFI_NOT_FOUND == Status) { PrintToken (STRING_TOKEN(STR_NOT_FOUND), HiiHandle); return Status; } PrintToken (STRING_TOKEN(STR_TITLE), HiiHandle); PrintToken (STRING_TOKEN(STR_VAR), HiiHandle, Buffer); BS->FreePool (Buffer); return Status; } EFI_STATUS WriteVar (CHAR16 *Str2Write, EFI_HII_HANDLE HiiHandle) { EFI_STATUS Status = EFI_SUCCESS; EFI_GUID VarGuid = VAR_GUID; UINTN VarSize; if (NULL == Str2Write) { return EFI_INVALID_PARAMETER; } // Calculate the size of the string to write // including the end NULL VarSize = (StrLen (Str2Write) + 1) * sizeof (CHAR16); Status = RT->SetVariable (VAR_NAME, &VarGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS|EFI_VARIABLE_NON_VOLATILE, VarSize, Str2Write); if (EFI_ERROR (Status)) { PrintToken (STRING_TOKEN(STR_WRITE_FAIL), HiiHandle); } return Status; } BOOLEAN IsQuoted (void) { EFI_SHELL_ARG_INFO *ArgInfo; // Attribute of ARG_IS_QUOTED means that at least part of the // argument was quoted in a pair of quotation marks. // Attribute of ARG_PARTIALLY_QUOTED means that not all the // chararcters of the argument were quoted. ArgInfo = SI->ArgInfo; if (ArgInfo[1].Attributes & ARG_IS_QUOTED && !(ArgInfo[1].Attributes & ARG_PARTIALLY_QUOTED)) { return TRUE; } return FALSE; }
/ // UseVarStrings.uni // /=# #langdef eng "English" #langdef fra "Français" #string STR_TITLE #language eng "%HThe content of variable 'SampleVar' is:%N\n" #language fra "%HThe content of variable 'SampleVar' is:%N\n" #string STR_VAR #language eng "%s\n" #language fra "%s\n" #string STR_NOT_FOUND #language eng "Variable %H'SampleVar'%N not found!\n" #language fra "Variable %H'SampleVar'%N not found!\n" #string STR_WRITE_FAIL #language eng "Fail to write variable %H'SampleVar'%N.\n" #language fra "Fail to write variable %H'SampleVar'%N.\n" #string STR_USAGE #language eng "USEVAR [string | -?]\n" "\n" " string - String will be written in variable\n" " named 'SampleVar'.\n" " -? - Display the help information.\n" "\n" "Examples:\n" " *To write a string into variable 'SampleVar':\n" " fs0:\\> usevar \"EFI, One generation ahead!\"\n" "\n" " *To display the content of variable 'SampleVar':\n" " fs0:\\> usevar\n" " The content of variable 'SampleVar' is:\n" " EFI, One generation ahead!\n" #language fra "USEVAR [string | -?]\n" "\n" " string - String will be written in variable\n" " named 'SampleVar'.\n" " -? - Display the help information.\n" "\n" "Examples:\n" " *To write a string into variable 'SampleVar':\n" " fs0:\\> usevar \"EFI, One generation ahead!\"\n" "\n" " *To display the content of variable 'SampleVar':\n" " fs0:\\> usevar\n" " The content of variable 'SampleVar' is:\n" " EFI, One generation ahead!\n" #string STR_SHELLENV_GNC_COMMAND_NOT_SUPPORT #language eng "%hs: This command is not supported in the \n" "underlaying EFI version, required EFI version \n" "should be %hd.%hd or above\n\n" #language fra "%hs: This command is not supported in the \n" "underlaying EFI version, required EFI version \n" "should be %hd.%hd or above\n\n"
# # UseVar.inf # # Component description file # [defines] BASE_NAME = UseVar FILE_GUID = 7BD2613C-4EF8-49f5-876D-DF94A42B9B09 COMPONENT_TYPE = APPLICATION [sources.common] UseVarStrings.uni UseVar.c [includes.common] . ..\Inc ..\Library $(EDK_SOURCE)\Foundation $(EDK_SOURCE)\Foundation\Core\Dxe $(EDK_SOURCE)\Foundation\Efi $(EDK_SOURCE)\Foundation\Efi\Include $(EDK_SOURCE)\Foundation\Framework $(EDK_SOURCE)\Foundation\Framework\Include $(EDK_SOURCE)\Foundation\Include $(EDK_SOURCE)\Foundation\Include\IndustryStandard $(DEST_DIR)\ [libraries.common] EfiShellLib [nmake.common] IMAGE_ENTRY_POINT=UseVarMain C_STD_INCLUDE= C_STD_FLAGS=$(C_STD_FLAGS) /DSTRING_ARRAY_NAME=$(BASE_NAME)Strings C_STD_FLAGS=$(C_STD_FLAGS) /DSTRING_DEFINES_FILE=\"$(BASE_NAME)StrDefs.h\" C_STD_FLAGS=$(C_STD_FLAGS) /DEFI_BOOTSHELL
The source files for each example should be placed in their own subdirectory under ${EDK_SOURCE}/Other/Maintained/Application/UefiShell. For example here is the the filesystem layout for the UseVar example.
The EDK Shell Developers Guide contents incorrect information regarding configuring a build tip and where the resultant executables are placed by the buidl.
The appropriate build tip description file (.dsc) needs to be modified to include the three examples in the build. For example, if you are building DUET, you would modify ${EDK_SOURCE}/Sample/Platform/DUET/build/DUET.dsc as follows:
# # Shell # Other\Maintained\Application\UefiShell\ShellFull.inf FV=NULL Other\Maintained\Application\UefiShell\HelloWorld\HelloWorld.inf FV=NULL Other\Maintained\Application\UefiShell\UseArg\UseArg.inf FV=NULL Other\Maintained\Application\UefiShell\UseVar\UseVar.inf FV=NULL
Upon successfully building the tip the resultant executable files for the three applications can be found in
${EDK_SOURCE}/bin/DUETuefi32/IA32 for a 32-bit build or ${EDK_SOURCE}/bin/DUETuefi64/IA32 for a 64-bit build.
June 2010 Post updated. TianoCore activity moved to SourceForge in April 2010.