aboutsummaryrefslogtreecommitdiffstats
path: root/Lesson_13/README.md
diff options
context:
space:
mode:
authorKonstantin Aladyshev <aladyshev22@gmail.com>2021-06-22 20:43:50 +0300
committerKonstantin Aladyshev <aladyshev22@gmail.com>2021-06-22 20:43:50 +0300
commitd0cc477ee23e19be08a600d3b9d9a238dcb39f32 (patch)
tree53412e2e8bfbb7f973901cfc597ddd96fac21c19 /Lesson_13/README.md
parent949552d025a5968b3fd3e8d0ab399c9a85232def (diff)
downloadUEFI-Lessons-d0cc477ee23e19be08a600d3b9d9a238dcb39f32.tar.gz
UEFI-Lessons-d0cc477ee23e19be08a600d3b9d9a238dcb39f32.tar.bz2
UEFI-Lessons-d0cc477ee23e19be08a600d3b9d9a238dcb39f32.zip
Add lesson 13
Diffstat (limited to 'Lesson_13/README.md')
-rw-r--r--Lesson_13/README.md115
1 files changed, 115 insertions, 0 deletions
diff --git a/Lesson_13/README.md b/Lesson_13/README.md
new file mode 100644
index 0000000..5ba6fb3
--- /dev/null
+++ b/Lesson_13/README.md
@@ -0,0 +1,115 @@
+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
+ );
+```
+
+
+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
+```