aboutsummaryrefslogtreecommitdiffstats
path: root/Lessons
diff options
context:
space:
mode:
Diffstat (limited to 'Lessons')
-rw-r--r--Lessons/Lesson_23/README.md166
1 files changed, 94 insertions, 72 deletions
diff --git a/Lessons/Lesson_23/README.md b/Lessons/Lesson_23/README.md
index bae429d..67ebe62 100644
--- a/Lessons/Lesson_23/README.md
+++ b/Lessons/Lesson_23/README.md
@@ -1,107 +1,125 @@
-Now let's explore `PatchableInModule` PCD.
+Now let's explore `PatchableInModule` PCD class.
-Add PCD to DEC file UefiLessonsPkg/UefiLessonsPkg.dec:
+Add new PCD to DEC file `UefiLessonsPkg/UefiLessonsPkg.dec` under the `[PcdsPatchableInModule]` section:
```
[PcdsPatchableInModule]
- gUefiLessonsPkgTokenSpaceGuid.PcdMyPatchableVar32|0x31313131|UINT32|0x00000004
+ gUefiLessonsPkgTokenSpaceGuid.PcdPatchableInt32|0x31313131|UINT32|0xFCDA11B5
```
-Populate it to INF UefiLessonsPkg/PCDLesson/PCDLesson.inf:
+
+Populate it to INF `UefiLessonsPkg/PCDLesson/PCDLesson.inf`:
```
[PatchPcd]
- gUefiLessonsPkgTokenSpaceGuid.PcdMyPatchableVar32
+ gUefiLessonsPkgTokenSpaceGuid.PcdPatchableInt32
```
To get a value of PCD in a *.c file either `PatchPcdGet` or generic `PcdGet` should be used.
Let's test both methods:
```
-Print(L"PcdMyPatchableVar32=%d\n", PatchPcdGet32(PcdMyPatchableVar32));
-Print(L"PcdMyPatchableVar32=%d\n", PcdGet32(PcdMyPatchableVar32));
+Print(L"PcdPatchableInt32=0x%x\n", PatchPcdGet32(PcdPatchableInt32));
+Print(L"PcdPatchableInt32=0x%x\n", PcdGet32(PcdPatchableInt32));
```
-Now build and look to AutoGen files:
+Now build and look to AutoGen files.
-Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h
+`Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h`:
```
-#define _PCD_TOKEN_PcdMyPatchableVar32 0U
-#define _PCD_PATCHABLE_VALUE_PcdMyPatchableVar32 ((UINT32)0x31313131U)
-extern volatile UINT32 _gPcd_BinaryPatch_PcdMyPatchableVar32;
-#define _PCD_GET_MODE_32_PcdMyPatchableVar32 _gPcd_BinaryPatch_PcdMyPatchableVar32
-#define _PCD_PATCHABLE_PcdMyPatchableVar32_SIZE 4
-#define _PCD_GET_MODE_SIZE_PcdMyPatchableVar32 _gPcd_BinaryPatch_Size_PcdMyPatchableVar32
-extern UINTN _gPcd_BinaryPatch_Size_PcdMyPatchableVar32;
-#define _PCD_SET_MODE_32_PcdMyPatchableVar32(Value) (_gPcd_BinaryPatch_PcdMyPatchableVar32 = (Value))
-#define _PCD_SET_MODE_32_S_PcdMyPatchableVar32(Value) ((_gPcd_BinaryPatch_PcdMyPatchableVar32 = (Value)), RETURN_SUCCESS)
+#define _PCD_TOKEN_PcdPatchableInt32 0U
+#define _PCD_PATCHABLE_VALUE_PcdPatchableInt32 ((UINT32)0x31313131U)
+extern volatile UINT32 _gPcd_BinaryPatch_PcdPatchableInt32;
+#define _PCD_GET_MODE_32_PcdPatchableInt32 _gPcd_BinaryPatch_PcdPatchableInt32
+#define _PCD_PATCHABLE_PcdPatchableInt32_SIZE 4
+#define _PCD_GET_MODE_SIZE_PcdPatchableInt32 _gPcd_BinaryPatch_Size_PcdPatchableInt32
+extern UINTN _gPcd_BinaryPatch_Size_PcdPatchableInt32;
+#define _PCD_SET_MODE_32_PcdPatchableInt32(Value) (_gPcd_BinaryPatch_PcdPatchableInt32 = (Value))
+#define _PCD_SET_MODE_32_S_PcdPatchableInt32(Value) ((_gPcd_BinaryPatch_PcdPatchableInt32 = (Value)), RETURN_SUCCESS)
```
-Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.c
+
+`Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.c`:
```
-volatile UINT32 _gPcd_BinaryPatch_PcdMyPatchableVar32 = _PCD_PATCHABLE_VALUE_PcdMyPatchableVar32;
-GLOBAL_REMOVE_IF_UNREFERENCED UINTN _gPcd_BinaryPatch_Size_PcdMyPatchableVar32 = 4;
+volatile UINT32 _gPcd_BinaryPatch_PcdPatchableInt32 = _PCD_PATCHABLE_VALUE_PcdPatchableInt32;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN _gPcd_BinaryPatch_Size_PcdPatchableInt32 = 4;
```
-So in this case our call to `PcdGet32(PcdMyPatchableVar32)` would be expanded to:
+According to the [https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PcdLib.h](https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PcdLib.h):
```
-PcdGet32(PcdMyPatchableVar32) --> _PCD_GET_MODE_32_PcdMyPatchableVar32 --> _gPcd_BinaryPatch_PcdMyPatchableVar32
+#define PatchPcdGet32(TokenName) _gPcd_BinaryPatch_##TokenName
+...
+#define PcdGet32(TokenName) _PCD_GET_MODE_32_##TokenName
```
-This variable would be assigned in `AutoGen.c`:
+
+If you unravel preprocessor code, you'll see that both calls translate to the same variable:
```
-volatile UINT32 _gPcd_BinaryPatch_PcdMyPatchableVar32 = ((UINT32)0x31313131U);
+PatchPcdGet32(PcdPatchableInt32) -> _gPcd_BinaryPatch_PcdPatchableInt32
+
+PcdGet32(PcdPatchableInt32) -> _PCD_GET_MODE_32_PcdPatchableInt32 -> _gPcd_BinaryPatch_PcdPatchableInt32
```
-So the main difference from the FixedAtBuild and FeatureFlag PCDs is that variable defined as `volatile` and set functions aren't blocked.
-Let's try to set our PCD then. As with get, there are two possibilities. You can use either `PatchPcdSet<Type>` or generic `PcdSet<Type>S`.
+This is a `volatile` variable that is assigned in the `AutoGen.c`:
+```
+volatile UINT32 _gPcd_BinaryPatch_PcdPatchableInt32 = _PCD_PATCHABLE_VALUE_PcdPatchableInt32 // = ((UINT32)0x31313131U)
+```
-Keep in mind that `PcdSet32S` unravels to a macro returning a value.
-https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PcdLib.h:
+So the main difference from the `FixedAtBuild` and `FeatureFlag` PCDs is that the variable defined as `volatile` and the set functions aren't blocked.
+
+# PCD value modification at run-time
+
+Let's try to set our PCD then. As with get, there are two possibilities. You can use either `PatchPcdSet<Type>` or generic `PcdSet<Type>S` API [https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PcdLib.h](https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/PcdLib.h):
```
+#define PatchPcdSet32(TokenName, Value) (_gPcd_BinaryPatch_##TokenName = (Value))
+...
#define PcdSet32S(TokenName, Value) _PCD_SET_MODE_32_S_##TokenName ((Value))
```
-Therefore:
+
+Keep in mind that `PcdSet32S` unravels to a macro returning a value, for example:
```
-PcdSet32S(PcdMyPatchableVar32, 44) --> _PCD_SET_MODE_32_S_PcdMyPatchableVar32 ((Value)) --> ((_gPcd_BinaryPatch_PcdMyPatchableVar32 = (Value)), RETURN_SUCCESS)
+PcdSet32S(PcdPatchableInt32, 44) --> _PCD_SET_MODE_32_S_PcdPatchableInt32 ((44)) --> ((_gPcd_BinaryPatch_PcdPatchableInt32 = (44)), RETURN_SUCCESS)
```
So if you don't want such error:
```
-/home/kostr/tiano/edk2/Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h:108:106: error: right-hand operand of comma expression has no effect [-Werror=unused-value]
- 108 | #define _PCD_SET_MODE_32_S_PcdMyPatchableVar32(Value) ((_gPcd_BinaryPatch_PcdMyPatchableVar32 = (Value)), RETURN_SUCCESS)
+/<...>/Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/AutoGen.h:108:106: error: right-hand operand of comma expression has no effect [-Werror=unused-value]
+ 108 | #define _PCD_SET_MODE_32_S_PcdPatchableInt32(Value) ((_gPcd_BinaryPatch_PcdPatchableInt32 = (Value)), RETURN_SUCCESS)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~.
```
You should use something like this:
```
-RETURN_STATUS PcdStatus = PcdSet32S(PcdMyPatchableVar32, 44);
-Print(L"PcdStatus=%r\n", PcdStatus);
+EFI_STATUS Status = PcdSet32S(PcdPatchableInt32, 44);
+Print(L"Status=%r\n", Status);
```
-Alternatively you can use `PatchPcdSet32` which don't require such thing as it is defined as follows:
+The native `PatchPcdSet32` API function doesn't require such thing, so you can use it simply as this:
```
-#define PatchPcdSet32(TokenName, Value) (_gPcd_BinaryPatch_##TokenName = (Value))
+PatchPcdSet32(PcdPatchableInt32, 43);
```
Test both set methods in app code:
```
-Print(L"PcdMyPatchableVar32=0x%x\n", PcdGet32(PcdMyPatchableVar32));
-RETURN_STATUS PcdStatus = PcdSet32S(PcdMyPatchableVar32, 44);
-Print(L"PcdStatus=%r\n", PcdStatus);
-Print(L"PcdMyPatchableVar32=%d\n", PcdGet32(PcdMyPatchableVar32));
-PatchPcdSet32(PcdMyPatchableVar32, 45);
-Print(L"PcdMyPatchableVar32=%d\n", PatchPcdGet32(PcdMyPatchableVar32));
+Print(L"PcdPatchableInt32=0x%x\n", PatchPcdGet32(PcdPatchableInt32));
+Print(L"PcdPatchableInt32=0x%x\n", PcdGet32(PcdPatchableInt32));
+PatchPcdSet32(PcdPatchableInt32, 43);
+Print(L"PcdPatchableInt32=%d\n", PatchPcdGet32(PcdPatchableInt32));
+EFI_STATUS Status = PcdSet32S(PcdPatchableInt32, 44);
+Print(L"Status=%r\n", Status);
+Print(L"PcdPatchableInt32=%d\n", PatchPcdGet32(PcdPatchableInt32));
```
-
-Now if you execute our app under OVMF prints for patchable PCDs would output:
+Now if you build and execute our app under OVMF you would get the following output:
```
-PcdMyPatchableVar32=0x31313131
-PcdStatus=Success
-PcdMyPatchableVar32=44
-PcdMyPatchableVar32=45
+FS0:\> PCDLesson.efi
+...
+PcdPatchableInt32=0x31313131
+PcdPatchableInt32=0x31313131
+PcdPatchableInt32=43
+Status=Success
+PcdPatchableInt32=44
```
-_________________________________
+# PCD Patching
-In case you've wondered why I've assigned a hex value for PCD default value or why this PCD type is named `PatchableInModule` this section is for you.
+In case you've wondered why I've assigned a hex value for the PCD default value or why this PCD type is named `PatchableInModule` this section is for you.
-This PCD type is named like that because the value of this PCD can be changed in a binary PE/COFF image (*.efi file). To do this two utilities are used:
+This PCD type is named like that because the value of this PCD can be changed in a binary PE/COFF image (i.e. the final `*.efi` file). To do this two utilities are used:
- `GenPatchPcdTable` - this tool is used to get the patchable PCD offset for the EFI image by parsing the map file
- `PatchPcdValue` - this tool is used to actually patch PCD value
@@ -129,7 +147,7 @@ Options:
```
Now let's create a `PatchPcdTable` for our app:
-For the *.efi file we can use one of:
+For the `*.efi` file we can use one of:
```
Build/UefiLessonsPkg/RELEASE_GCC5/X64/PCDLesson.efi
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/OUTPUT/PCDLesson.efi
@@ -140,16 +158,17 @@ For the *.map file we can use one of:
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.map
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/OUTPUT/PCDLesson.map
```
+
In case you wonder how our PCD can be found in a map file, execute:
```
-$ grep MyPatchableVar32 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.map -A2
- .data._gPcd_BinaryPatch_PcdMyPatchableVar32
- 0x0000000000001920 0x4 /tmp/PCDLesson.dll.m6t8YL.ltrans0.ltrans.o
- *fill* 0x0000000000001924 0xc
+$ grep PatchableInt32 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.map -A2
+ .data._gPcd_BinaryPatch_PcdPatchableInt32
+ 0x00000000000055a0 0x4 /tmp/PCDLesson.dll.96BX4a.ltrans0.ltrans.o
+ *fill* 0x00000000000055a4 0xc
```
-So as you can see the default value for our PCD is placed under 0x1920 offset.
+So as you can see the default value for our PCD is placed under the 0x55a0 offset.
-Now let's execute `GenPatchPcdTable` and create a file `PCDLessonPatchPcdTable` in app Build DEBUG folder:
+Now let's execute `GenPatchPcdTable` and create a file `PCDLessonPatchPcdTable` in the app Build `DEBUG` folder:
```
./BaseTools/BinWrappers/PosixLike/GenPatchPcdTable \
-m Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.map \
@@ -161,15 +180,15 @@ Checkout the created `PCDLessonPatchPcdTable` file.
```
$ cat Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLessonPatchPcdTable
PCD Name Offset Section Name
-PcdMyPatchableVar32 0x1920 .data
+PcdPatchableInt32 0x55A0 .data
```
As you can see it has the same offset that we've seen in a map file.
Now let's get a final look at our default PCD value in an *.elf file:
```
-hexdump -s 0x1920 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.efi -n 4
-0001920 3131 3131
-0001924
+hexdump -s 0x55A0 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.efi -n 4
+00055a0 3131 3131
+00055a4
```
Checkout help for the `PatchPcdValue` tool:
@@ -202,24 +221,27 @@ Options:
Now use it to patch our PCD in an *.elf file:
```
./BaseTools/BinWrappers/PosixLike/PatchPcdValue \
- --offset=0x1920 \
+ --offset=0x55a0 \
--value=0xDEADDEAD \
--type=UINT32 \
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.efi
```
Look at hexdump again:
```
-$ hexdump -s 0x1920 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.efi -n 4
-0001920 dead dead
-0001924
+$ hexdump -s 0x55A0 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.efi -n 4
+00055a0 dead dead
+00055a4
```
We've successfully changed our PCD in a binary!
-Now if you execute our app under OVMF prints for patchable PCDs would output:
+Now copy the modified `Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/PCDLesson/PCDLesson/DEBUG/PCDLesson.efi` file to the UEFI shared disk and execute our app under OVMF:
```
-PcdMyPatchableVar32=0xDEADDEAD
-PcdStatus=Success
-PcdMyPatchableVar32=44
-PcdMyPatchableVar32=45
+FS0:\> PCDLesson.efi
+...
+PcdPatchableInt32=0xDEADDEAD
+PcdPatchableInt32=0xDEADDEAD
+PcdPatchableInt32=43
+Status=Success
+PcdPatchableInt32=44
```