diff options
| author | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-06-13 15:32:48 +0300 | 
|---|---|---|
| committer | Konstantin Aladyshev <aladyshev22@gmail.com> | 2021-06-13 15:32:48 +0300 | 
| commit | 57d983fcdbf62dc2c48b75a72a054eab50d9726b (patch) | |
| tree | 10830ffdd3c5ec6c4f551b8e8961097483848843 /Lesson_3 | |
| parent | 22bd932679cde7acec07561d5cee0e9684c5e18c (diff) | |
| download | UEFI-Lessons-57d983fcdbf62dc2c48b75a72a054eab50d9726b.tar.gz UEFI-Lessons-57d983fcdbf62dc2c48b75a72a054eab50d9726b.tar.bz2 UEFI-Lessons-57d983fcdbf62dc2c48b75a72a054eab50d9726b.zip | |
Add lesson 3
Diffstat (limited to 'Lesson_3')
| -rw-r--r-- | Lesson_3/README.md | 168 | ||||
| -rw-r--r-- | Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c | 10 | ||||
| -rw-r--r-- | Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf | 17 | ||||
| -rw-r--r-- | Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c | 10 | ||||
| -rw-r--r-- | Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.inf | 16 | ||||
| -rw-r--r-- | Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc | 26 | 
6 files changed, 247 insertions, 0 deletions
| diff --git a/Lesson_3/README.md b/Lesson_3/README.md new file mode 100644 index 0000000..f0aef2e --- /dev/null +++ b/Lesson_3/README.md @@ -0,0 +1,168 @@ +Finally we are ready to write our "Hello World" app. + +First we create a new edk2 module in our package directory similar to the our `SimplestApp` module: +``` +$ mkdir UefiLessonsPkg/HelloWorld +$ vi UefiLessonsPkg/HelloWorld/HelloWorld.inf +[Defines] +  INF_VERSION                    = 1.25 +  BASE_NAME                      = HelloWorld +  FILE_GUID                      = 2e55fa38-f148-42d3-af90-1be247323e30 +  MODULE_TYPE                    = UEFI_APPLICATION +  VERSION_STRING                 = 1.0 +  ENTRY_POINT                    = UefiMain + +[Sources] +  HelloWorld.c + +[Packages] +  MdePkg/MdePkg.dec + +[LibraryClasses] +  UefiApplicationEntryPoint +``` +Don't forget to add our newly created app to the `Components` section of the package DSC file +``` +[Components] +  UefiLessonsPkg/SimplestApp/SimplestApp.inf ++ UefiLessonsPkg/HelloWorld/HelloWorld.inf +``` +Next we need to write the source code file. Let's remember the code for our SimplestApp: +``` +EFI_STATUS +EFIAPI +UefiMain ( +  IN EFI_HANDLE        ImageHandle, +  IN EFI_SYSTEM_TABLE  *SystemTable +  ) +{ +  return EFI_SUCCESS; +} +``` +To print something to the console ("Hello World" message in our case) we need to use services from the `EFI_SYSTEM_TABLE` that is passed to the entry point of our app. + +The description of the `EFI_SYSTEM_TABLE` can be found in the UEFI specification (https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf). + +EFI_SYSTEM_TABLE is a struct that was populated by the UEFI firmware and contains pointers to the runtime and boot services tables. +``` +typedef struct { + EFI_TABLE_HEADER Hdr; + CHAR16 *FirmwareVendor; + UINT32 FirmwareRevision; + EFI_HANDLE ConsoleInHandle; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + EFI_HANDLE ConsoleOutHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + EFI_HANDLE StandardErrorHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; + EFI_RUNTIME_SERVICES *RuntimeServices; + EFI_BOOT_SERVICES *BootServices; + UINTN NumberOfTableEntries; + EFI_CONFIGURATION_TABLE *ConfigurationTable; +} EFI_SYSTEM_TABLE; +``` +We are interested in the `ConOut` field. `ConOut` is abbreviaton for "Console Output" and according to the UEFI spec it is a pointer to the `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` interface that is associated with `ConsoleOutHandle`. + +If we keep digging into UEFI spec we can find description of the `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL`. +According to the spec `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` defines the minimum requirements for a text-based ConsoleOut device. + +As everything in UEFI it has GUID: +``` +#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \ + {0x387477c2,0x69c7,0x11d2,\ + {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b}} +``` + +And the interface description is: +``` +typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { + EFI_TEXT_RESET Reset; + EFI_TEXT_STRING OutputString; + EFI_TEXT_TEST_STRING TestString; + EFI_TEXT_QUERY_MODE QueryMode; + EFI_TEXT_SET_MODE SetMode; + EFI_TEXT_SET_ATTRIBUTE SetAttribute; + EFI_TEXT_CLEAR_SCREEN ClearScreen; + EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; + EFI_TEXT_ENABLE_CURSOR EnableCursor; + SIMPLE_TEXT_OUTPUT_MODE *Mode; +} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; +``` +Right now we are interested in a `OutputString` method: +``` +OutputString     Displays the string on the device at the current cursor location. +``` +This is what we need. Let's look at the function description: +``` +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString() + +Summary +Writes a string to the output device. + +Prototype +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_STRING) ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +Parameters +This    A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. +String  The Null-terminated string to be displayed on the output device(s). +``` + +In edk2 `EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL` is defined in the header file: +https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/SimpleTextOut.h + + +With all this knowledge we can write our source code file `UefiLessonsPkg/HelloWorld/HelloWorld.c`: +``` +EFI_STATUS +EFIAPI +UefiMain ( +  IN EFI_HANDLE        ImageHandle, +  IN EFI_SYSTEM_TABLE  *SystemTable +  ) +{ +  SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); +  return EFI_SUCCESS; +} +``` + +The `L""` signifies that the string is composed from CHAR16 symbols, as was required in spec. + +Let's compile our edk2 module: +``` +$ build --platform=UefiLessonsPkg/UefiLessonsPkg.dsc \ +        --module=UefiLessonsPkg/HelloWorld/HelloWorld.inf \ +        --arch=X64 \ +        --buildtarget=RELEASE --tagname=GCC5 +``` + +Copy the app to our `UEFI_disk` folder and run OVMF: +``` +$ cp Build/UefiLessonsPkg/RELEASE_GCC5/X64/HelloWorld.efi ~/UEFI_disk/ +$ qemu-system-x86_64 -drive if=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd \ +                     -drive format=raw,file=fat:rw:~/UEFI_disk \ +                     -nographic \ +                     -net none +``` + +``` +UEFI Interactive Shell v2.2 +EDK II +UEFI v2.70 (EDK II, 0x00010000) +Mapping table +      FS0: Alias(s):HD0a1:;BLK1: +          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1) +     BLK0: Alias(s): +          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) +     BLK2: Alias(s): +          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) +Press ESC in 4 seconds to skip startup.nsh or any other key to continue. +Shell> fs0: +FS0:\> HelloWorld.efi +Hello World! +FS0:\> +``` diff --git a/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c b/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c new file mode 100644 index 0000000..399b0ac --- /dev/null +++ b/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( +  IN EFI_HANDLE        ImageHandle, +  IN EFI_SYSTEM_TABLE  *SystemTable +  ) +{ +  SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello World!\n"); +  return EFI_SUCCESS; +} diff --git a/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf b/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf new file mode 100644 index 0000000..95924c5 --- /dev/null +++ b/Lesson_3/UefiLessonsPkg/HelloWorld/HelloWorld.inf @@ -0,0 +1,17 @@ +[Defines] +  INF_VERSION                    = 1.25 +  BASE_NAME                      = HelloWorld +  FILE_GUID                      = 2e55fa38-f148-42d3-af90-1be247323e30 +  MODULE_TYPE                    = UEFI_APPLICATION +  VERSION_STRING                 = 1.0 +  ENTRY_POINT                    = UefiMain + +[Sources] +  HelloWorld.c + +[Packages] +  MdePkg/MdePkg.dec + +[LibraryClasses] +  UefiApplicationEntryPoint + diff --git a/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c b/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c new file mode 100644 index 0000000..8bdf500 --- /dev/null +++ b/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.c @@ -0,0 +1,10 @@ +EFI_STATUS +EFIAPI +UefiMain ( +  IN EFI_HANDLE        ImageHandle, +  IN EFI_SYSTEM_TABLE  *SystemTable +  ) +{ +  return EFI_SUCCESS; +} + diff --git a/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.inf b/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.inf new file mode 100644 index 0000000..7d4bae2 --- /dev/null +++ b/Lesson_3/UefiLessonsPkg/SimplestApp/SimplestApp.inf @@ -0,0 +1,16 @@ +[Defines] +  INF_VERSION                    = 1.25 +  BASE_NAME                      = SimplestApp +  FILE_GUID                      = 4a298956-fbe0-47fb-ae3a-2d5a0a959a26 +  MODULE_TYPE                    = UEFI_APPLICATION +  VERSION_STRING                 = 1.0 +  ENTRY_POINT                    = UefiMain + +[Sources] +  SimplestApp.c + +[Packages] +  MdePkg/MdePkg.dec + +[LibraryClasses] +  UefiApplicationEntryPoint diff --git a/Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..91a79e6 --- /dev/null +++ b/Lesson_3/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,26 @@ +[Defines] +  DSC_SPECIFICATION              = 0x0001001C +  PLATFORM_GUID                  = 3db7270f-ffac-4139-90a4-0ae68f3f8167 +  PLATFORM_VERSION               = 0.01 +  PLATFORM_NAME                  = UefiLessonsPkg +  SKUID_IDENTIFIER               = DEFAULT +  SUPPORTED_ARCHITECTURES        = X64 +  BUILD_TARGETS                  = RELEASE + + +[LibraryClasses] +  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf +  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf +  DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf +  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf +  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf +  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf +  RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf +  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf +  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + +[Components] +  UefiLessonsPkg/SimplestApp/SimplestApp.inf +  UefiLessonsPkg/HelloWorld/HelloWorld.inf + + | 
