-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DasharoModulePkg: document how to add a new setting
Signed-off-by: Sergii Dmytruk <[email protected]>
- Loading branch information
1 parent
df259ad
commit 2bf3125
Showing
1 changed file
with
196 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
This document is meant to outline the process of adding a new Dasharo setting. | ||
If something isn't covered, follow structure of the code used for some similar | ||
variable. If possible, use alphabetic sorting of lists, although it's not a | ||
requirement. | ||
|
||
Examples below use a new setting called `NewSetting`/`NEW_SETTING` which should | ||
be replaced with an actual name of the setting. | ||
|
||
Basic variable implementation | ||
============================= | ||
|
||
EFI variables are managed by a dedicated library which is used by the UI code. | ||
It makes sense to start from here. | ||
|
||
Add variable name in `Include/DasharoOptions.h` | ||
----------------------------------------------- | ||
|
||
Add a new `#define DASHARO_VAR_*` near the top where other settings marked with | ||
`// Settings` are, for example: | ||
|
||
``` | ||
#define DASHARO_VAR_NEW_SETTING L"NewSetting" | ||
``` | ||
|
||
This is an EFI variable name. It should look roughly like the already existing | ||
ones. The rest of the code should use the macro name after adding | ||
`#include <DasharoOptions.h>` and not the string literal which can have typos. | ||
|
||
Add default value in `Library/DasharoVariablesLib/DasharoVariablesLib.c` | ||
------------------------------------------------------------------------ | ||
|
||
Add another `if`-statement to `GetVariableDefault()` setting default variable | ||
data, its size and additional EFI variable attributes if they are necessary. | ||
See below if variable data is not a primitive type. | ||
|
||
Updating `GetVariableDefault()` enables resetting and creation (see the next | ||
step) of the variable with the correct value. | ||
|
||
If the variable's data is a structure then additionally: | ||
1. Add a new `DASHARO_*` structure at the bottom of `Include/DasharoOptions.h`. | ||
2. Add the new structure to `VAR_DATA` in `Include/DasharoOptions.h` as well. | ||
|
||
Add variable creation in `Library/DasharoVariablesLib/DasharoVariablesLib.c` | ||
---------------------------------------------------------------------------- | ||
|
||
By adding one more line to `mAllVariables` array there. | ||
|
||
Adding the setting to Dasharo System Features | ||
============================================= | ||
|
||
Before a variable can become visible in the UI, the code which implements the UI | ||
part needs to become aware of it. | ||
|
||
Add storage for new variable | ||
---------------------------- | ||
|
||
Find `DASHARO_FEATURES_DATA` structure in | ||
`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesHii.h` and add a new | ||
field after `// Feature data` like: | ||
|
||
``` | ||
BOOLEAN NewSetting; | ||
``` | ||
|
||
Add initialization to constructor of `DasharoSystemFeaturesUiLib` | ||
----------------------------------------------------------------- | ||
|
||
Update `DasharoSystemFeaturesUiLibConstructor()` in | ||
`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c` by adding a new | ||
line like this: | ||
|
||
``` | ||
LOAD_VAR (DASHARO_VAR_NEW_SETTING, NewSetting); | ||
``` | ||
|
||
`NewSetting` here is a field of `DASHARO_FEATURES_DATA` from the above step. | ||
|
||
Add saving of new value | ||
----------------------- | ||
|
||
`DasharoSystemFeaturesRouteConfig()` in | ||
`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c` is responsible for | ||
writing changed values back into EFI variable storage. Add a line like this to | ||
the function: | ||
|
||
``` | ||
STORE_VAR (DASHARO_VAR_NEW_SETTING, NewSetting); | ||
``` | ||
|
||
Very similar to `LOAD_VAR`. | ||
|
||
Some variables can even be read-only, but add this line anyway for consistency. | ||
If no value change is detected, nothing gets written. | ||
|
||
Exposing the setting in Dasharo System Features UI | ||
================================================== | ||
|
||
A variable might exist without being visible to the user, it might be visible | ||
conditionally or unconditionally. The last two cases require updating UI forms | ||
and tying them with the new code. | ||
|
||
Add UI strings to `Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesStrings.uni` | ||
--------------------------------------------------------------------------------------- | ||
|
||
If your variable is called `DASHARO_VAR_NEW_SETTING`, add label and help | ||
prompt like the following: | ||
|
||
``` | ||
#string STR_NEW_SETTING_PROMPT #language en-US "<text that appears in the form>" | ||
#string STR_NEW_SETTING_HELP #language en-US "<text that appears in help section of the form>" | ||
``` | ||
|
||
The two IDs above (`STR_NEW_SETTING_PROMPT` and `STR_NEW_SETTING_HELP`) will be | ||
needed on modifying a form in the next step. | ||
|
||
Update `Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesVfr.vfr` UI form | ||
-------------------------------------------------------------------------------- | ||
|
||
The new setting will need to go to one of the sections surrounded by `form` and | ||
`endform`. In some cases it might be necessary to add a new section. | ||
|
||
Most of the settings are booleans that get represented as checkboxes in which | ||
case the added lines would look like this: | ||
|
||
``` | ||
checkbox varid = FeaturesData.NewSetting, | ||
prompt = STRING_TOKEN(STR_NEW_SETTING_PROMPT), | ||
help = STRING_TOKEN(STR_NEW_SETTING_HELP), | ||
flags = RESET_REQUIRED, | ||
endcheckbox; | ||
``` | ||
|
||
Making a setting resettable | ||
=========================== | ||
|
||
Not all UI elements described in VFR file can have their default specified there | ||
as well and that value might not be permanently fixed (i.e., configured at | ||
build-time or run-time). Handling such a situation requires writing code which | ||
provides default value through a callback which in this case is called | ||
`DasharoSystemFeaturesCallback()` in | ||
`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c` file. For the | ||
callback to know which value to provide, it gets an integer value known as | ||
question ID which is specified in VFR file as well. | ||
|
||
Create question ID | ||
------------------ | ||
|
||
Add a new definition at the bottom of | ||
`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesHii.h` like this one: | ||
|
||
``` | ||
#define NEW_SETTING_QUESTION_ID 0x8010 | ||
``` | ||
|
||
The integer value should be unique. | ||
|
||
Extend callback in `Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c` | ||
------------------------------------------------------------------------------- | ||
|
||
Handle a new case to `switch (QuestionId)` in `DasharoSystemFeaturesCallback()` | ||
like the following: | ||
|
||
``` | ||
case NEW_SETTING_QUESTION_ID: | ||
Value->b = DasharoGetVariableDefault (DASHARO_VAR_NEW_SETTING).Boolean; | ||
break; | ||
``` | ||
|
||
Depending on the variable type you want to change `->b` and `.Boolean` parts. | ||
|
||
Update UI element in VFR file | ||
----------------------------- | ||
|
||
Find the element in question in | ||
`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesVfr.vfr` and add two | ||
fields to it (update flags if they already exist): | ||
|
||
``` | ||
questionid = NEW_SETTING_QUESTION_ID, | ||
flags = RESET_REQUIRED | INTERACTIVE, | ||
``` | ||
|
||
`RESET_REQUIRED` flag means that resetting settings will affect this particular | ||
one as well. | ||
|
||
`INTERACTIVE` flag means that the callback will be invoked for this element. | ||
**Adding `questionid` without setting `INTERACTIVE` flag won't have any useful | ||
effect.** | ||
|
||
Topics not covered | ||
================== | ||
|
||
Could be added in the future: | ||
|
||
* Adding a new submenu. | ||
* Controlling feature visibility via PCDs and hiding them in VFR. |