diff options
author | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-07-10 00:04:40 +0300 |
---|---|---|
committer | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-07-10 00:04:40 +0300 |
commit | 6064c1e48b622f53538f4df9bdd402c607a87d51 (patch) | |
tree | 93d3c937b9568568307fd2ff7053a30c538ad72a /Lessons/Lesson_13/README.md | |
parent | a9c375c80c3505be794ec2b5d5bb90de27ef0d42 (diff) | |
download | UEFI-Lessons-6064c1e48b622f53538f4df9bdd402c607a87d51.tar.gz UEFI-Lessons-6064c1e48b622f53538f4df9bdd402c607a87d51.tar.bz2 UEFI-Lessons-6064c1e48b622f53538f4df9bdd402c607a87d51.zip |
Move lessons to separate folder
Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
Diffstat (limited to 'Lessons/Lesson_13/README.md')
-rw-r--r-- | Lessons/Lesson_13/README.md | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/Lessons/Lesson_13/README.md b/Lessons/Lesson_13/README.md new file mode 100644 index 0000000..0d42005 --- /dev/null +++ b/Lessons/Lesson_13/README.md @@ -0,0 +1,137 @@ +In previous lesson we've used `EFI_SHELL_PARAMETERS_PROTOCOL` to get command line parameters to our app. +It is a valid method but there is a simpler way to do it for the shell apps. + +To ease things we can use the entry point in this format: +https://github.com/tianocore/edk2/blob/master/ShellPkg/Include/Library/ShellCEntryLib.h +``` +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ); +``` +This way `Argc`/`Argv` are passed directly to the app entry point like it is usually happening in C programming. + +Let's create a `SimpleShellApp` based on our `HelloWorld` app. + +With the necessary modifications the INF file would look like this: +``` +[Defines] + INF_VERSION = 1.25 + BASE_NAME = SimpleShellApp + FILE_GUID = 2afd1202-545e-4f8d-b8fb-bc179e84ddc8 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +[Sources] + SimpleShellApp.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + ShellCEntryLib +``` +Main changes: +- `ENTRY_POINT = ShellCEntryLib` is added to the `[Defines]` section +- `ShellCEntryLib` is added to the `[LibraryClasses]` section + +In the end it works this way. Shell C library is the main UEFI app with the standard entry point: +``` +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +``` +It parses incoming parameters with the `EFI_SHELL_PARAMETERS_PROTOCOL` like we did it and then calls our app entry point passing all of the parsed parameteres with the call: +``` +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ); +``` +You can look at the source code of `ShellAppMain` at the https://github.com/tianocore/edk2/blob/master/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c + +If you look at the source you could see that istead of a `HandleProtocol` API that we've used: +``` +Status = gBS->HandleProtocol( + ImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **) &ShellParameters +); +``` +it uses `OpenProtocol` API: (I've modified a code a little bit to make it comparable to our version) +``` +Status = gBS->OpenProtocol( + ImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **)&ShellParameters, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL +); +``` +According to the UEFI spec `HandleProtocol` API is outdated and `OpenProtocol` should be used instead. +`OpenProtocol` API is a more general call that can cover more cases. It all would matter when you start develop UEFI drivers. You can read UEFI spec for more information. Right now just accept a fact that for the UEFI app these two calls are the same. + +Let's go back to our code. To find the necessary `ShellCEntryLib` library class search as usual: +``` +$ grep ShellCEntryLib -r ./ --include=*.inf | grep LIBRARY_CLASS +./ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf: LIBRARY_CLASS = ShellCEntryLib|UEFI_APPLICATION UEFI_DRIVER +``` + +Add this library class to our `UefiLessonsPkg/UefiLessonsPkg.dsc`: +``` +ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf +``` +Don't forget also to add our new app under the `[Components]` section: +``` +UefiLessonsPkg/SimpleShellApp/SimpleShellApp.inf +``` + + +Now let's look at the `*.c` file. + +We can't use our first print method as `SystemTable` now is unavailable, but we can simply use `SystemTable` with the help of `gST` pointer: +``` +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +INTN EFIAPI ShellAppMain(IN UINTN Argc, IN CHAR16 **Argv) +{ + Print(L"Argc=%d\n", Argc); +// SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); + gST->ConOut->OutputString(gST->ConOut, L"Hello again!\n"); + Print(L"Bye!\n"); + return 0; +} +``` + +Let's add some parameters handling code: +``` +for (UINTN i=Argc; i>0; i--) { + Print(L"Arg[%d]=%s\n", Argc-i, Argv[Argc-i]); +} +``` + +If we test our app under OVMF we would get: +``` +FS0:\> SimpleShellApp.efi kkk ggg +Hello again! +Bye! +Arg[0]=FS0:\SimpleShellApp.efi +Arg[1]=kkk +Arg[2]=ggg +FS0:\> SimpleShellApp.efi +Hello again! +Bye! +Arg[0]=FS0:\SimpleShellApp.efi +``` |