aboutsummaryrefslogtreecommitdiffstats
path: root/Lessons_uncategorized/Lesson_FDF_FV_8/README.md
blob: 203593842cfca360d095974a1fab99dd67730f40 (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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
Sometimes we might want to put to the FFS files that aren't the result of the edk2 build. Off course we can do it manually via the `FILE = <...>` statement, but it is also possible to do it via the INF file. As with compiled modules this keeps code more structured and clean.

The files that we want to push to the FFS need to be listed in the INF module `[Binaries]` section.

Let's try to create INF file for the `Shell.efi` image. First build the `*.efi` file:
```
build --platform=ShellPkg/ShellPkg.dsc --module=ShellPkg/Application/Shell/Shell.inf --arch=X64 --buildtarget=RELEASE --tagname=GCC5
```

Now create a folder `BinaryModule` for our new module and put newly generated file into that folder:
```
mkdir UefiLessonsPkg/BinaryModule/
cp Build/Shell/RELEASE_GCC5/X64/ShellPkg/Application/Shell/Shell/OUTPUT/Shell.efi UefiLessonsPkg/BinaryModule/
```

Create INF file:
```
[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = BinaryModule
  FILE_GUID                      = a580fb82-9d1f-480b-ba42-17273d861c95
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0

[Binaries]
  PE32|Shell.efi
```

Here we don't need the `ENTRY_POINT` define that we've always used in our modules. And `[Packages]` and `[LibraryClasses]` sections are also no longer necessary.
However you might need `[Depex]` section in a you binary module. But right now we leave things as they are.

The format of the statements inside the `[Binaries]` section is:
```
<SectionFileType>|<FilePath>[|Target]
```
- `<SectionFileType>` - remember how there are usually two words for sections inside the rule statements? This is the second word
- `<FilePath>` - path to the file to include
- `<Target>` - you can use `DEBUG/RELEASE/NOOPT/*` as a taget, or you can omit this part alltogether

To build the binary module along with the ordinary rule section:
```
[Rule.<ARCH>.<MODULE_TYPE>]
```
You need to define another rule section:
```
[Rule.<ARCH>.<MODULE_TYPE>.BINARY]
```

So in our case we need to add `[Rule.Common.UEFI_APPLICATION.BINARY]` section along with the old one `[Rule.Common.UEFI_APPLICATION]`.

`UefiLessonsPkg/UefiLessonsPkg.fdf`:
```
[FV.SimpleVolume]
FvAlignment        = 16

INF UefiLessonsPkg/BinaryModule/BinaryModule.inf

[Rule.Common.UEFI_APPLICATION]
  FILE APPLICATION = $(NAMED_GUID) {
    PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
    UI       STRING="$(MODULE_NAME)"
    VERSION  STRING="$(INF_VERSION)" BUILD_NUM=$(BUILD_NUMBER)
  }

[Rule.Common.UEFI_APPLICATION.BINARY]
  FILE FREEFORM = $(NAMED_GUID) {
    PE32     PE32                    |.efi
    UI       STRING="$(MODULE_NAME)"
    VERSION  STRING="$(INF_VERSION)" BUILD_NUM=$(BUILD_NUMBER)
  }
```

To be certain that the correct rule is used in the `BINARY` rule we create `FILE FREEFORM` opposed to the `FILE APPLICATION` in the standard rule.

In the binary rule statements everything is the same except the `PE32` statement. Here instead of an actual file we need to write file extension in a form `|.<extension>`

As we don't need to compile our module, we don't need to add it to the `[Components]` section of our DSC file. And there wouldn't be any folder like `Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/BinaryModule/` after the compilation. Only the `Ffs` folder would be created:
```
$ find Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/
Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/
Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/a580fb82-9d1f-480b-ba42-17273d861c95SEC2.ui
Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/a580fb82-9d1f-480b-ba42-17273d861c95SEC3.ver.txt
Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/a580fb82-9d1f-480b-ba42-17273d861c95.ffs
Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/a580fb82-9d1f-480b-ba42-17273d861c95SEC1.1.pe32.txt
Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/a580fb82-9d1f-480b-ba42-17273d861c95SEC3.ver
Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/a580fb82-9d1f-480b-ba42-17273d861c95.ffs.txt
Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/a580fb82-9d1f-480b-ba42-17273d861c95SEC1.1.pe32
```
And here is the output of `VolInfo`:
```
$ VolInfo Build/UefiLessonsPkg/RELEASE_GCC5/FV/SIMPLEVOLUME.Fv -x Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
VolInfo Version 1.0 Build Developer Build based on Revision: Unknown
%36s %511s
ParseGuidBaseNameFile: Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
Signature:        _FVH (4856465F)
Attributes:       40800
       EFI_FVB2_ERASE_POLARITY
       EFI_FVB2_ALIGNMENT_16
Header Length:         0x00000048
File System ID:        8c8ce578-8a3d-4f1c-9935-896185c32dd3
Revision:              0x0002
Number of Blocks:      0x000E2ED8
Block Length:          0x00000001
Total Volume Size:     0x000E2ED8
============================================================
File Name:        A580FB82-9D1F-480B-BA42-17273D861C95  BinaryModule
File Offset:      0x00000048
File Length:      0x000E2E8A
File Attributes:  0x00
File State:       0xF8
        EFI_FILE_DATA_VALID
File Type:        0x02  EFI_FV_FILETYPE_FREEFORM
------------------------------------------------------------
  Type:  EFI_SECTION_PE32
  Size:  0x000E2E44
------------------------------------------------------------
  Type:  EFI_SECTION_USER_INTERFACE
  Size:  0x0000001E
  String: BinaryModule
------------------------------------------------------------
  Type:  EFI_SECTION_VERSION
  Size:  0x0000000E
  Build Number:  0x0000
  Version String:  1.0
There are a total of 1 files in this FV
```

# Adding other sections

Let's try to write other sections to the file. Create file "hello.txt":
```
echo "hello" > UefiLessonsPkg/BinaryModule/hello.txt
```
And add it as `RAW` to the `[Binaries]` section:
```
[Binaries]
  PE32|Shell.efi
  RAW|hello.txt
```

If we perform build right now, nothing would change.

We need to modify our rule to include `.txt` files:
```
[Rule.Common.UEFI_APPLICATION.BINARY]
  FILE FREEFORM = $(NAMED_GUID) {
    PE32     PE32                    |.efi
    UI       STRING="$(MODULE_NAME)"
    VERSION  STRING="$(INF_VERSION)" BUILD_NUM=$(BUILD_NUMBER)
    RAW RAW |.txt
  }
```
With this rule the new section would be added to the file:
```
$ VolInfo Build/UefiLessonsPkg/RELEASE_GCC5/FV/SIMPLEVOLUME.Fv -x Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
VolInfo Version 1.0 Build Developer Build based on Revision: Unknown
%36s %511s
ParseGuidBaseNameFile: Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
Signature:        _FVH (4856465F)
Attributes:       40800
       EFI_FVB2_ERASE_POLARITY
       EFI_FVB2_ALIGNMENT_16
Header Length:         0x00000048
File System ID:        8c8ce578-8a3d-4f1c-9935-896185c32dd3
Revision:              0x0002
Number of Blocks:      0x000E2EE0
Block Length:          0x00000001
Total Volume Size:     0x000E2EE0
============================================================
File Name:        A580FB82-9D1F-480B-BA42-17273D861C95  BinaryModule
File Offset:      0x00000048
File Length:      0x000E2E96
File Attributes:  0x00
File State:       0xF8
        EFI_FILE_DATA_VALID
File Type:        0x02  EFI_FV_FILETYPE_FREEFORM
------------------------------------------------------------
  Type:  EFI_SECTION_PE32
  Size:  0x000E2E44
------------------------------------------------------------
  Type:  EFI_SECTION_USER_INTERFACE
  Size:  0x0000001E
  String: BinaryModule
------------------------------------------------------------
  Type:  EFI_SECTION_VERSION
  Size:  0x0000000E
  Build Number:  0x0000
  Version String:  1.0
------------------------------------------------------------
  Type:  EFI_SECTION_RAW
  Size:  0x0000000A
There are a total of 1 files in this FV
```
Let's try to add another `.txt` file to our module. Create file:
```
$ echo "world!" > UefiLessonsPkg/BinaryModule/world.txt
```
And include it to the `[Binaries]` section:
```
[Binaries]
  PE32|Shell.efi
  RAW|hello.txt
  RAW|world.txt
```
In this case two `RAW` sections would be at the end of our file:
```
$ VolInfo Build/UefiLessonsPkg/RELEASE_GCC5/FV/SIMPLEVOLUME.Fv -x Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
VolInfo Version 1.0 Build Developer Build based on Revision: Unknown
%36s %511s
ParseGuidBaseNameFile: Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
Signature:        _FVH (4856465F)
Attributes:       40800
       EFI_FVB2_ERASE_POLARITY
       EFI_FVB2_ALIGNMENT_16
Header Length:         0x00000048
File System ID:        8c8ce578-8a3d-4f1c-9935-896185c32dd3
Revision:              0x0002
Number of Blocks:      0x000E2EF0
Block Length:          0x00000001
Total Volume Size:     0x000E2EF0
============================================================
File Name:        A580FB82-9D1F-480B-BA42-17273D861C95  BinaryModule
File Offset:      0x00000048
File Length:      0x000E2EA3
File Attributes:  0x00
File State:       0xF8
        EFI_FILE_DATA_VALID
File Type:        0x02  EFI_FV_FILETYPE_FREEFORM
------------------------------------------------------------
  Type:  EFI_SECTION_PE32
  Size:  0x000E2E44
------------------------------------------------------------
  Type:  EFI_SECTION_USER_INTERFACE
  Size:  0x0000001E
  String: BinaryModule
------------------------------------------------------------
  Type:  EFI_SECTION_VERSION
  Size:  0x0000000E
  Build Number:  0x0000
  Version String:  1.0
------------------------------------------------------------
  Type:  EFI_SECTION_RAW
  Size:  0x0000000A
------------------------------------------------------------
  Type:  EFI_SECTION_RAW
  Size:  0x0000000B
There are a total of 1 files in this FV
```

The `hello` section is the one that has a size 0x0000000A, and `world!` section is the one that has a size `0x0000000B` as it is one symbol longer.

You can see both strings if you look at the ffs file with `hexdump`:
```
$ hexdump Build/UefiLessonsPkg/RELEASE_GCC5/FV/Ffs/a580fb82-9d1f-480b-ba42-17273d861c95BinaryModule/a580fb82-9d1f-480b-ba42-17273d861c95.ffs -C | tail
000e2e20  d8 ab e8 ab 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000e2e30  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000e2e50  00 00 00 00 00 00 00 00  00 00 00 00 1e 00 00 15  |................|
000e2e60  42 00 69 00 6e 00 61 00  72 00 79 00 4d 00 6f 00  |B.i.n.a.r.y.M.o.|
000e2e70  64 00 75 00 6c 00 65 00  00 00 00 00 0e 00 00 14  |d.u.l.e.........|
000e2e80  00 00 31 00 2e 00 30 00  00 00 00 00 0a 00 00 19  |..1...0.........|
000e2e90  68 65 6c 6c 6f 0a 00 00  0b 00 00 19 77 6f 72 6c  |hello.......worl|
000e2ea0  64 21 0a                                          |d!.|
000e2ea3
```

# Many sections of the same type in one rule

What whould be if you put another `RAW` statement to the file?
```
[Rule.Common.UEFI_APPLICATION.BINARY]
  FILE FREEFORM = $(NAMED_GUID) {
    RAW RAW |.txt
    PE32     PE32                    |.efi
    UI       STRING="$(MODULE_NAME)"
    VERSION  STRING="$(INF_VERSION)" BUILD_NUM=$(BUILD_NUMBER)
    RAW RAW |.txt
  }
```

Each statement would generate 2 `RAW` sections (`hello` and `world!`) in this case:
```
$ VolInfo Build/UefiLessonsPkg/RELEASE_GCC5/FV/SIMPLEVOLUME.Fv -x Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
VolInfo Version 1.0 Build Developer Build based on Revision: Unknown
%36s %511s
ParseGuidBaseNameFile: Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
Signature:        _FVH (4856465F)
Attributes:       40800
       EFI_FVB2_ERASE_POLARITY
       EFI_FVB2_ALIGNMENT_16
Header Length:         0x00000048
File System ID:        8c8ce578-8a3d-4f1c-9935-896185c32dd3
Revision:              0x0002
Number of Blocks:      0x000E2F08
Block Length:          0x00000001
Total Volume Size:     0x000E2F08
============================================================
File Name:        A580FB82-9D1F-480B-BA42-17273D861C95  BinaryModule
File Offset:      0x00000048
File Length:      0x000E2EBB
File Attributes:  0x00
File State:       0xF8
        EFI_FILE_DATA_VALID
File Type:        0x02  EFI_FV_FILETYPE_FREEFORM
------------------------------------------------------------
  Type:  EFI_SECTION_RAW
  Size:  0x0000000A
------------------------------------------------------------
  Type:  EFI_SECTION_RAW
  Size:  0x0000000B
------------------------------------------------------------
  Type:  EFI_SECTION_PE32
  Size:  0x000E2E44
------------------------------------------------------------
  Type:  EFI_SECTION_USER_INTERFACE
  Size:  0x0000001E
  String: BinaryModule
------------------------------------------------------------
  Type:  EFI_SECTION_VERSION
  Size:  0x0000000E
  Build Number:  0x0000
  Version String:  1.0
------------------------------------------------------------
  Type:  EFI_SECTION_RAW
  Size:  0x0000000A
------------------------------------------------------------
  Type:  EFI_SECTION_RAW
  Size:  0x0000000B
There are a total of 1 files in this FV
```

# `SectionFileType` for `RAW` section

Remember how I told you that `RAW` section can have several `SectionFileType's`: `RAW`/`BIN`/`ASL`/`ACPI`. You can try to use them for our files:
```
[Binaries]
  PE32|Shell.efi
  ASL|hello.txt
  ACPI|world.txt
```
Off course our `*.txt` aren't connected to the ACPI in any way, but let's just do it as an experiment.

Modify rule statement like this:
```
[Rule.Common.UEFI_APPLICATION.BINARY]
  FILE FREEFORM = $(NAMED_GUID) {
    PE32     PE32                    |.efi
    UI       STRING="$(MODULE_NAME)"
    VERSION  STRING="$(INF_VERSION)" BUILD_NUM=$(BUILD_NUMBER)
    RAW ASL |.txt
  }
```
Now build system would include only the file `ASL|hello.txt`, but not `ACPI|world.txt` as the rule works only with `ASL` `SectionFileType's`. For the proof look at the `VolInfo` output:
```
$ VolInfo Build/UefiLessonsPkg/RELEASE_GCC5/FV/SIMPLEVOLUME.Fv -x Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
VolInfo Version 1.0 Build Developer Build based on Revision: Unknown
%36s %511s
ParseGuidBaseNameFile: Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
Signature:        _FVH (4856465F)
Attributes:       40800
       EFI_FVB2_ERASE_POLARITY
       EFI_FVB2_ALIGNMENT_16
Header Length:         0x00000048
File System ID:        8c8ce578-8a3d-4f1c-9935-896185c32dd3
Revision:              0x0002
Number of Blocks:      0x000E2EE0
Block Length:          0x00000001
Total Volume Size:     0x000E2EE0
============================================================
File Name:        A580FB82-9D1F-480B-BA42-17273D861C95  BinaryModule
File Offset:      0x00000048
File Length:      0x000E2E96
File Attributes:  0x00
File State:       0xF8
        EFI_FILE_DATA_VALID
File Type:        0x02  EFI_FV_FILETYPE_FREEFORM
------------------------------------------------------------
  Type:  EFI_SECTION_PE32
  Size:  0x000E2E44
------------------------------------------------------------
  Type:  EFI_SECTION_USER_INTERFACE
  Size:  0x0000001E
  String: BinaryModule
------------------------------------------------------------
  Type:  EFI_SECTION_VERSION
  Size:  0x0000000E
  Build Number:  0x0000
  Version String:  1.0
------------------------------------------------------------
  Type:  EFI_SECTION_RAW
  Size:  0x0000000A
There are a total of 1 files in this FV
```

One final thing to note: there is no difference in a flash content from an actual `SectionFileType` that you use in `[Binaries]` section `RAW`/`BIN`/`ASL`/`ACPI`. There is no difference between `ASL|hello.txt` or `BIN|hello.txt` as long as the file is included in the rule.

# `FILE RAW =` in the rule

`BINARY` rules also allow to add RAW files to the filesystem. Here is an example:
```
[Rule.Common.UEFI_APPLICATION.BINARY]
  FILE RAW = $(NAMED_GUID) {
                          |.efi
  }
```
This would produce following `VolInfo` output:
```
$ VolInfo Build/UefiLessonsPkg/RELEASE_GCC5/FV/SIMPLEVOLUME.Fv -x Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
VolInfo Version 1.0 Build Developer Build based on Revision: Unknown
%36s %511s
ParseGuidBaseNameFile: Build/UefiLessonsPkg/RELEASE_GCC5/FV/Guid.xref
Signature:        _FVH (4856465F)
Attributes:       40800
       EFI_FVB2_ERASE_POLARITY
       EFI_FVB2_ALIGNMENT_16
Header Length:         0x00000048
File System ID:        8c8ce578-8a3d-4f1c-9935-896185c32dd3
Revision:              0x0002
Number of Blocks:      0x000E2EA0
Block Length:          0x00000001
Total Volume Size:     0x000E2EA0
============================================================
File Name:        A580FB82-9D1F-480B-BA42-17273D861C95  BinaryModule
File Offset:      0x00000048
File Length:      0x000E2E58
File Attributes:  0x00
File State:       0xF8
        EFI_FILE_DATA_VALID
File Type:        0x01  EFI_FV_FILETYPE_RAW
There are a total of 1 files in this FV
```

# Override for binary modules

In case you use override for a binary module:
```
INF RuleOverride=MyOverride UefiLessonsPkg/BinaryModule/BinaryModule.inf
```
You only need to provide one rule that matches override name, without the `BINARY` clause:
```
[Rule.Common.USER_APPLICATION.MyOverride]
```

# `USER_DEFINED` module type

In the example above we've used `MODULE_TYPE = UEFI_APPLICATION` in our module. Often modules that should produce non-standard files in FFS use `MODULE_TYPE = USER_DEFINED` type.

# Links

- [https://edk2-docs.gitbook.io/edk-ii-inf-specification/3_edk_ii_inf_file_format/315_-binaries-_section](https://edk2-docs.gitbook.io/edk-ii-inf-specification/3_edk_ii_inf_file_format/315_-binaries-_section)