aboutsummaryrefslogtreecommitdiffstats
path: root/Lessons/Lesson_36/README.md
blob: f6d64ad123dce5c324897f3eadf5e8c556ac59c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
In this lesson we will try to create the most simple library.

Usually libraries are present in these directories:
```
<Pkg Name>/Library/<Library Name>/               <---- inf and source files for the library (=library implementation)
<Pkg Name>/Include/Library/                      <---- library headers (=library interface)
```

Create folders for our `SimpleLibrary`:
```
$ mkdir -p UefiLessonsPkg/Library/SimpleLibrary/
$ mkdir -p UefiLessonsPkg/Include/Library/
```

First let's implement the header file, the interface for our library. Our `SimpleLibrary` would contain the only function `Plus2` that would receive a `number` and return a `number+2`.
Therefore the content in the header file (`UefiLessonsPkg/Include/Library/SimpleLibrary.h`) would look like this:
```
UINTN Plus2(UINTN number);
```

No harder the library implementation file `UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.c`:
```
#include <Library/SimpleLibrary.h>

UINTN Plus2(UINTN number) {
  return number+2;
}
```

This is really a simple library, it stands to its name!

Now we need to create an INF file for the library `UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf`:
```
[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = SimpleLibrary
  FILE_GUID                      = 826c8951-5bd2-4d72-a9d9-f7ab48684117
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  LIBRARY_CLASS                  = SimpleLibrary | UEFI_APPLICATION

[Sources]
  SimpleLibrary.c

[Packages]
  MdePkg/MdePkg.dec
```

The interesting string here is the:
```
LIBRARY_CLASS = SimpleLibrary | UEFI_APPLICATION
```
It says that this library can only be used in modules with a type `UEFI_APPLICATION`. If you would say here `DXE_DRIVER` and try to link it to some of you UEFI applications, build process would fail. The error message would look like this:
```
build.py...
/home/kostr/tiano/edk2/UefiLessonsPkg/UefiLessonsPkg.dsc(...): error 1001: Module type [UEFI_APPLICATION] is not supported by library instance [/home/kostr/tiano/edk2/UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf]
        consumed by [/home/kostr/tiano/edk2/UefiLessonsPkg/<path to your app inf file>]
```

Now we need to include our library to our package DSC file `UefiLessonsPkg/UefiLessonsPkg.dsc`, so it would get build on a package build:
```
[Components]
  ...
  UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf
```

But if you try to build our package now build would fail with a message:
```
/home/kostr/tiano/edk2/UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.c:1:10: fatal error: Library/SimpleLibrary.h: No such file or directory
    1 | #include <Library/SimpleLibrary.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
```
The reason of that is a fact that our `UefiLessonsPkg/Include/Library/` folder is not recognized by a build system as a place where headers might be.

To fix it we need to add to our `UefiLessonsPkg/UefiLessonsPkg.dec` file `[Includes]` section:
```
[Includes]
  Include
```

And include this `UefiLessonsPkg/UefiLessonsPkg.dec` file to the library module INF file section `[Packages]`:
```
[Packages]
  MdePkg/MdePkg.dec
  UefiLessonsPkg/UefiLessonsPkg.dec
```

Now we are good, build would succeed.

# SimpleLibraryUser

Now let's create an application that would use our library.

UefiLessonsPkg/SimpleLibraryUser/SimpleLibraryUser.c:
```
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>

#include <Library/SimpleLibrary.h>

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  Print(L"%d\n", Plus2(3));

  return EFI_SUCCESS;
}
```

UefiLessonsPkg/SimpleLibraryUser/SimpleLibraryUser.inf
```
[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = SimpleLibraryUser
  FILE_GUID                      = 22a1f57c-21ca-4011-9133-e3df0d01dace
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = UefiMain

[Sources]
  SimpleLibraryUser.c

[Packages]
  MdePkg/MdePkg.dec
  UefiLessonsPkg/UefiLessonsPkg.dec                  <--- we need to include this for the same reason as in library INF file (for the header search)

[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib
  SimpleLibrary                                      <--- library is included as usual
```

Now add modifications to the `UefiLessonsPkg/UefiLessonsPkg.dsc`:
```
[LibraryClasses]
  ...
  SimpleLibrary|UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf

[Components]
  ...
  UefiLessonsPkg/SimpleLibraryUser/SimpleLibraryUser.inf
```
Here we've added implementation for our library class and added our new module to the package components.

If you build everything now and execute it under OVMF, you would get:
```
FS0:\> SimpleLibraryUser.efi
5
```

`3+2` is indeed `5`, so our library works correctly!