AMI TSE Setup Menu: VFR, SD, UNI, and HII Callbacks
The AMI TSE (Text Setup Environment) is a core component of the AMI Aptio BIOS setup interface. It provides the framework for presenting firmware configuration menus, displaying hardware information, handling user interactions, and managing configuration settings.
Developers customizing an Aptio Setup menu need to understand several interconnected components: VFR form definitions, IFR intermediate representations, AMI-specific SD files, UNI language resources, HII packages, callback functions, and UEFI variable services.
These components divide the work of building a Setup interface into distinct responsibilities. VFR describes forms and questions, IFR represents the compiled form structure, SD files support modular customization in AMI projects, and UNI files provide localized strings. HII connects forms and strings to the firmware’s user interface infrastructure, while callbacks and variable services implement interactive behavior and configuration persistence.
This guide explains the architecture and development workflow, using common Aptio project conventions. Exact file names, build tokens, callback mechanisms, and HII interfaces can vary between Aptio releases and OEM implementations, so examples should be validated against the target source tree.
For a broader introduction to UEFI firmware architecture, see UEFI BIOS Explained: Architecture and Boot Flow.
🏗️ 1. Understanding the TSE Form Architecture #
The Setup interface is built around forms, questions, and associated string resources. In standard UEFI terminology, the Human Interface Infrastructure (HII) provides the framework for storing these resources and presenting form-based configuration interfaces.
1.1 Form, VFR, IFR, and HII #
The relationship between Form, VFR, IFR, and HII is fundamental to Setup development.
| Concept | Description |
|---|---|
| Form | A logical page containing configuration questions, text, options, and navigation elements |
| VFR | Visual Form Representation, a source language used to describe forms and their controls |
| IFR | Internal Forms Representation, a binary opcode format generated from form definitions |
| HII Database | Stores HII package lists containing forms, strings, and other user-interface resources |
| Forms Browser | Processes form definitions, displays supported controls, and coordinates user interactions |
| UNI | A source format used to define localized strings referenced by HII resources |
| SD | An AMI-specific source mechanism commonly used for modular Setup customization in Aptio projects |
A form is conceptually similar to a page in a user interface, but VFR is not HTML. It uses a declarative syntax designed for firmware configuration forms.
For example, VFR can define a one-of question with several permitted values, a checkbox backed by a configuration variable, or a navigation element that opens another form.
The VFR compiler translates source definitions into IFR opcodes. The resulting form package can then be installed into the HII Database, where a compatible Forms Browser processes the form structure.
The standard UEFI specification describes this model in its Human Interface Infrastructure documentation.
1.2 The role of AMI’s TSE #
AMI’s TSE provides the Setup user-interface environment used by supported Aptio firmware implementations.
TSE is associated with the traditional text-oriented Setup experience, although the exact presentation capabilities depend on the firmware configuration and licensed AMI products. AMI separately offers graphical Setup functionality through its Aptio Extensible Setup Architecture (ESA).
The TSE implementation integrates with the platform’s form definitions, HII resources, navigation behavior, and OEM customization mechanisms.
Typical responsibilities include:
- Displaying forms and their questions.
- Translating HII string tokens into localized text.
- Processing user input and selections.
- Invoking supported callback mechanisms.
- Reading configuration variables for Setup controls.
- Applying configuration changes according to the platform’s save and reset policies.
AMI’s terminology and implementation details are vendor-specific. Developers should distinguish the TSE framework in an Aptio project from the standardized UEFI HII interfaces on which form-based configuration is built.
1.3 Modular Setup customization #
Aptio projects commonly divide Setup definitions among VFR, SD, UNI, and header files.
This structure allows different teams to maintain platform, CPU, chipset, storage, security, and OEM-specific content separately.
For example, an OEM can add a read-only hardware-revision field to an existing form without maintaining a separate copy of the entire core VFR file, provided the target project’s SD integration mechanism supports that insertion point.
This reduces unnecessary duplication and makes customization changes easier to identify during firmware-core upgrades.
📁 2. Organizing Setup Menu Files #
A typical Aptio project contains multiple files that contribute to the Setup interface.
A simplified directory structure might look like this:
Setup/
├── Main.vfr
├── Advanced.vfr
├── Chipset.vfr
├── Boot.vfr
├── Security.vfr
├── SaveExit.vfr
├── SD/
│ ├── Platform.sd
│ ├── CPU.sd
│ ├── Chipset.sd
│ ├── SIO.sd
│ ├── ACPI.sd
│ └── OEM.sd
├── UNI/
│ ├── Platform.uni
│ ├── CPU.uni
│ ├── Chipset.uni
│ ├── SIO.uni
│ ├── ACPI.uni
│ └── OEM.uni
└── Include/
├── SetupDefinitions.h
└── Setup.h
The actual layout varies between platforms. Some projects keep SD and UNI files alongside their corresponding modules, while others generate intermediate VFR files during the build.
2.1 VFR files: Form structure and control definitions #
VFR files describe the visible structure of Setup forms, including form-set identifiers, titles, navigation, questions, options, and associated help text.
A form-set GUID identifies a group of related forms. Each form within the group has a form identifier, and questions can reference configuration variables or invoke supported interaction callbacks.
For example, a form-set might contain a Main form and a separate Processor Configuration form. A goto statement can provide navigation between those forms.
2.2 SD files: Modular OEM customization #
SD files are an AMI-specific customization mechanism used in supported Aptio projects. They are not a standard UEFI source format.
An SD file can contain conditional Setup definitions that are incorporated into VFR or other generated source through the project’s preprocessing and build tools.
This provides a way to add OEM-specific controls without directly modifying the original core VFR file.
The available conditional symbols, insertion points, and build behavior depend on the implementation supplied with the target Aptio release.
2.3 UNI files: Localized string resources #
UNI files define strings associated with identifiers referenced by form definitions.
Examples include form titles, control prompts, help text, option labels, and dynamically displayed hardware information.
The string package generated from UNI resources is made available through HII. The Forms Browser uses the active language configuration and available translations to determine which text to display.
Firmware string resources use Unicode-based representations. Language declarations and accepted language codes must follow the conventions supported by the target toolchain and HII package format.
2.4 Header files: Definitions and configuration data #
Header files such as SetupDefinitions.h and Setup.h commonly provide identifiers, data structures, GUID definitions, and other symbols referenced by Setup code.
Their contents can vary significantly between projects.
For example, a Setup header might define the structure corresponding to the Setup UEFI variable, while another header supplies form-set GUIDs and string-related definitions.
These files connect the declarative interface to the code and storage definitions used by the firmware.
🔄 3. How SD Files Are Integrated into VFR #
One of the advantages of the Aptio Setup framework is that it can support modular insertion of OEM-specific definitions into existing forms.
The precise mechanism depends on the project’s build system, but a common pattern uses preprocessor definitions and include files to select the relevant SD content.
3.1 Example: Main form and OEM content #
A simplified VFR source file might contain the following structure:
formset
guid = MAIN_FORM_SET_GUID,
title = STRING_TOKEN(STR_MAIN),
help = STRING_TOKEN(STR_MAIN_HELP),
class = MAIN_FORM_SET_CLASS,
subclass = 0,
#define MAIN_FORM_SET
form formid = AUTO_ID(MAIN_MAIN),
title = STRING_TOKEN(STR_MAIN);
#define FORM_SET_GOTO
#include <SetupDefinitions.h>
#undef FORM_SET_GOTO
endform;
endformset;The exact syntax for form-set classes, automatic identifiers, and include processing depends on the VFR compiler and Aptio project conventions. The example illustrates the general organization rather than a universal source template.
Within an OEM SD file, conditional directives can control whether a definition is included in a particular form or insertion context.
For example:
#ifdef MAIN_FORM_SET
#ifdef FORM_SET_GOTO
text
help = STRING_TOKEN(STR_CHIP_SCH_REV_HELP),
text = STRING_TOKEN(STR_CHIP_SCH_REV_NAME),
text = STRING_TOKEN(STR_CHIP_SCH_REV_VALUE),
flags = 0,
key = 0;
#endif
#endifHere, the conditions identify the intended form context and insertion point according to the project’s conventions.
The resulting definition adds a read-only text item to the form when the relevant conditions are satisfied.
The use of #ifdef, the names of the symbols, and the location where the SD content is incorporated are all project-specific. Standard UEFI does not require AMI SD files or this particular preprocessing mechanism.
3.2 What happens during compilation #
In a typical Aptio build, the Setup generation pipeline performs several related operations:
- Reads the VFR source and project-specific definitions.
- Processes applicable includes and conditional customization content.
- Compiles the resulting form definitions into IFR.
- Processes UNI resources into HII string packages.
- Packages or links the resulting resources into the firmware component.
The actual order and intermediate outputs depend on the project build rules.
For example, a generated VFR source might contain the expanded text statement from the OEM SD file, while the compiled IFR contains the corresponding binary form opcodes.
The resulting HII package list includes the form and string resources needed by the Setup interface.
3.3 Why this separation is useful #
Modular SD customization can reduce the number of core source files that an OEM must maintain independently.
It is especially valuable when a board requires additional hardware information, custom menus, or product-specific configuration options.
However, the separation does not guarantee automatic compatibility across core releases. If an insertion point disappears or the underlying form structure changes, the SD customization must still be reviewed and adapted.
📝 4. VFR and UNI Examples #
VFR describes the form structure and controls, while UNI defines their displayed text.
4.1 Defining a form and navigation item #
The following example illustrates a form that links to another form:
formset
guid = SYSTEM_CONFIGURATION_GUID,
title = STRING_TOKEN(STR_ADVANCED_TITLE),
help = STRING_TOKEN(STR_ADVANCED_HELP),
class = EFI_ADVANCED_CLASS,
subclass = 0,
form formid = 1,
title = STRING_TOKEN(STR_ADVANCED_TITLE);
goto 2,
prompt = STRING_TOKEN(STR_PROCESSOR_FORM_TITLE),
help = STRING_TOKEN(STR_PROCESSOR_FORM_HELP);
endform;
form formid = 2,
title = STRING_TOKEN(STR_PROCESSOR_FORM_TITLE);
// Processor configuration questions can be added here.
endform;
endformset;The goto statement creates a navigation item for the target form identifier. The referenced form must exist in the relevant form set or be resolved according to the platform’s supported form-navigation mechanism.
4.2 Defining English and localized strings #
A UNI file can associate multiple language translations with the same string identifier:
#string STR_ADVANCED_TITLE
#language eng "Advanced Configuration"
#string STR_ADVANCED_HELP
#language eng "Configure advanced system settings."
#string STR_PROCESSOR_FORM_TITLE
#language eng "Processor Configuration"
#string STR_PROCESSOR_FORM_HELP
#language eng "Configure supported processor options."Additional translations can be defined for the language codes supported by the project.
The string identifier remains the reference used by VFR, while the string package supplies the appropriate translation.
This arrangement keeps UI wording separate from the form’s structural definition and allows translations to be maintained independently.
🌐 5. Configuring Multi-Language Support #
Multilingual Setup depends on the language resources compiled into the HII packages, the language configuration recognized by the firmware, and the capabilities of the Setup interface.
5.1 Adding a language #
Some Aptio projects expose configuration tokens similar to the following:
NUMBER_OF_LANGUAGE_STRINGS = 2
SUPPORTED_LANGUAGES = "$(DEFAULT_LANGUAGE) eng"
DEFAULT_LANGUAGE = "jpn"
CJK_CHARACTERS_SUPPORT = "Enable"These token names and their accepted values are project-specific examples, not standard UEFI configuration variables.
Before adding a language, verify the target project’s supported language-code format, font implementation, string-gathering rules, and build configuration.
Japanese, Chinese, and other languages using large character sets may require additional font or rendering support. Enabling a language token alone does not guarantee that every character can be displayed correctly.
5.2 Providing translations #
A UNI string can contain translations for several languages:
#string STR_GENERAL_HELP
#language eng "General Help"
#language fra "Aide générale"A third translation can be added using the language-code convention supported by the target toolchain.
The exact language identifier format differs between legacy implementations and modern language-code conventions. Use the same convention consistently across the language declarations, generated HII packages, and firmware language configuration.
5.3 Verify string package generation #
After changing language resources, confirm that the build processes the expected UNI files and generates the required string packages.
If a string is missing or displayed incorrectly, check:
- Whether the string identifier is defined.
- Whether the file containing the definition is included in the build.
- Whether the target language is included in the generated package.
- Whether the selected language code is recognized.
- Whether the required font or character coverage is available.
These checks help distinguish a missing string definition from a language-selection or rendering problem.
🎛️ 6. Common TSE Control Types #
UEFI form definitions provide several question and display types. Aptio TSE renders these according to its supported user-interface behavior.
The following examples use standard-style VFR syntax. Exact compiler compatibility and available flags should be checked against the VFR compiler bundled with the target Aptio release.
6.1 text: Read-only information
#
A text statement displays information without directly allowing the user to edit an associated configuration variable.
It is useful for displaying hardware revisions, processor information, firmware versions, or other dynamically generated status values.
text
help = STRING_TOKEN(STR_PROCESSOR_MICROCODE_HELP),
text = STRING_TOKEN(STR_PROCESSOR_MICROCODE_STRING),
text = STRING_TOKEN(STR_PROCESSOR_MICROCODE_VALUE),
flags = 0,
key = 0;The string tokens identify the displayed text. The actual values must be provided by the relevant string resources or updated through the platform’s supported HII mechanism.
For example, a firmware initialization module may retrieve the processor microcode revision and update the appropriate HII string before the Setup form is displayed.
6.2 oneof: Select one option from a list
#
A oneof question presents a set of permitted values and associates the selected value with a configuration variable.
A simplified USB Legacy Support example is:
oneof varid = USB_SUPPORT_SETUP.UsbLegacySupport,
prompt = STRING_TOKEN(STR_USB_LEGACY_SUPPORT),
help = STRING_TOKEN(STR_USB_LEGACY_SUPPORT_HELP),
flags = RESET_REQUIRED,
key = USB_LEGACY_SUPPORT_KEY;
option text = STRING_TOKEN(STR_USB_ENABLED),
value = 0,
flags = DEFAULT;
option text = STRING_TOKEN(STR_USB_DISABLED),
value = 1,
flags = 0;
option text = STRING_TOKEN(STR_USB_AUTO),
value = 2,
flags = 0;
endoneof;The variable field stores the selected option value. The numerical meanings of these values depend on the firmware implementation.
In this example, the value 0 is the default option. RESET_REQUIRED indicates that a system reset is required for the affected setting to take effect, where supported by the platform’s Forms Browser.
The question-level key identifies the question to the callback mechanism. It should not be confused with the numeric value assigned to each option.
6.3 checkbox: Enable or disable a setting
#
A checkbox represents a Boolean-style choice associated with a configuration variable.
checkbox varid = SETUP_DATA.OnboardLAN,
prompt = STRING_TOKEN(STR_ONBOARD_LAN_PROMPT),
help = STRING_TOKEN(STR_ONBOARD_LAN_PROMPT_HELP),
flags = CHECKBOX_DEFAULT | RESET_REQUIRED,
key = ONBOARD_LAN_KEY;
endcheckbox;CHECKBOX_DEFAULT describes the default checkbox state according to the applicable VFR definitions. It does not independently define the live value of the underlying configuration variable.
The field SETUP_DATA.OnboardLAN stores the setting, while the Forms Browser and Setup implementation determine how the current value, default state, and save behavior are handled.
For an interactive checkbox, add the appropriate interaction flag supported by the target VFR compiler and install the relevant callback implementation.
6.4 numeric: Enter a numerical value
#
A numeric question allows users to specify a value within defined limits.
numeric varid = TIMEOUT.Value,
prompt = STRING_TOKEN(STR_BOOT_TIMEOUT),
help = STRING_TOKEN(STR_BOOT_TIMEOUT_HELP),
minimum = 0,
maximum = 0xFFFF,
step = 1,
default = DEFAULT_BOOT_TIMEOUT,
flags = 0;
endnumeric;The minimum, maximum, and step constraints define the permitted range and increments. The default value provides the baseline used by the form’s default mechanism.
The data type and storage layout must be consistent with the configuration variable associated with the question.
For production Setup menus, check whether a setting requires special validation, confirmation, or a system reset before the changed value takes effect.
🔔 7. Setup Callbacks and Dynamic HII Updates #
Some Setup options need to trigger platform-specific actions when a user changes a value. Others need their displayed text refreshed to reflect dynamic hardware information.
Aptio supports Setup-specific callback integration, while standard UEFI defines interfaces for configuration access, form interaction, and HII resource management.
7.1 Adding an initialization entry point #
In some Aptio projects, an eLink such as SetupStringInit provides an integration point for initializing OEM Setup strings or preparing form-specific resources.
A typical implementation may need to:
- Identify the target form set or class that requires initialization.
- Locate the required HII interfaces.
- Retrieve the relevant hardware or platform data.
- Add or update string resources.
- Refresh the relevant form or use the supported mechanism to ensure updated resources become visible.
The name SetupStringInit and the way it is linked are Aptio-specific conventions. Verify the actual parent list and function prototype in the target project.
Dynamic string changes should use the HII interfaces supported by that firmware. Updating a string resource does not automatically guarantee that an already rendered form refreshes immediately.
7.2 Standard callback architecture #
In standard UEFI HII configuration workflows, a driver can expose EFI_HII_CONFIG_ACCESS_PROTOCOL.
The protocol includes methods for extracting configuration, routing configuration changes, and handling callbacks when supported form questions are interacted with.
The Forms Browser communicates with the relevant driver using question identifiers and browser-action information. For example, a callback may distinguish a value that is about to change from one that has already changed.
Aptio 4 may also provide legacy HII interfaces or vendor-specific form-update methods. Older interfaces such as EFI_HII_PROTOCOL.UpdateForm() should be used only when supported by the specific firmware implementation.
7.3 Adding interaction flags and question keys #
The following example associates a callback key with a fan-detection checkbox:
checkbox varid = SETUP_DATA.Fan_Detect,
prompt = STRING_TOKEN(STR_FAN_DETECT),
help = STRING_TOKEN(STR_FAN_DETECT_HELP),
flags = INTERACTIVE | RESET_REQUIRED,
key = FAN_DETECT_KEY;
endcheckbox;The callback can use the question identifier to determine which setting generated the request.
A fan-control selector can be defined similarly:
oneof varid = SETUP_DATA.Fan1_Control,
prompt = STRING_TOKEN(STR_FAN1_CONTROL),
help = STRING_TOKEN(STR_FAN1_CONTROL_HELP),
flags = INTERACTIVE | RESET_REQUIRED,
key = FAN1_CONTROL_KEY;
option text = STRING_TOKEN(STR_ENABLED),
value = 1,
flags = DEFAULT;
option text = STRING_TOKEN(STR_DISABLED),
value = 0,
flags = 0;
option text = STRING_TOKEN(STR_AUTO),
value = 2,
flags = 0;
endoneof;The callback implementation should validate the proposed value, perform any required platform checks, and return an appropriate status.
For settings involving hardware control, validation should account for the device’s supported range, current operating state, and whether the change can be applied immediately or only after a reboot.
7.4 Reset-required and interactive behavior #
INTERACTIVE and RESET_REQUIRED serve different purposes.
INTERACTIVE indicates that the question supports interaction through the applicable Forms Browser and callback behavior.
RESET_REQUIRED indicates that a change requires a reset before it takes effect, where supported by the implementation.
A callback should not assume that the user has already committed the change merely because a question interaction occurred. The form browser may provide actions associated with proposed changes, committed changes, or other stages of interaction.
Use the callback action definitions supported by the target environment to determine the appropriate processing point.
💾 8. Setup Variable Storage and Access #
Setup forms commonly display and modify values stored in UEFI variables. The firmware uses variable names and vendor GUIDs to identify individual variables.
In many Aptio implementations, the variable named Setup contains a structure such as SETUP_DATA. The structure definition, variable GUID, attributes, and field layout are specific to the platform.
8.1 Where Setup values are stored #
Setup configuration is typically persisted in a nonvolatile UEFI variable store, often backed by flash storage.
It is not universally stored in CMOS. CMOS may hold selected legacy configuration values on some platforms, but modern UEFI firmware generally uses its variable services for many Setup settings.
The storage model can be summarized as follows:
| Feature | Description |
|---|---|
| Variable name | Identifies the variable, such as Setup |
| Variable GUID | Identifies the variable namespace |
| Data structure | Defines the fields stored in the variable |
| Nonvolatile storage | Allows values to persist across power cycles |
| Variable attributes | Define access and persistence characteristics |
| UEFI variable services | Provide interfaces for reading and updating the variable |
The definitions are commonly found in project-specific files such as Setup.h or other OEM headers.
8.2 Variable access during PEI, DXE, and runtime #
Variable access depends on the firmware phase and the interfaces available in that phase.
PEI: PEIMs use the relevant PEI variable PPIs, such as the read-only variable PPI where provided. Some implementations also expose variable-write support through an appropriate PPI. UEFI Runtime Services are not the normal interface during PEI.
DXE: Drivers can use the Runtime Services interface after it becomes available, including GetVariable() and SetVariable(), subject to platform policy and service initialization.
After operating-system handoff: The operating system may use its supported firmware-variable interface, subject to operating-system permissions, platform policy, and the attributes of the target variable.
The availability of variable services does not imply that every variable is writable from every phase or execution context.
8.3 GUID-based variable identification #
A UEFI variable is identified by its name and vendor GUID.
For example:
EFI_GUID gSetupGuid = SETUP_GUID;The exact macro or GUID definition must come from the target platform’s headers.
To access the Setup variable, the caller needs the correct variable name, GUID, expected data structure, and permissions for the intended operation.
Reading or writing a variable under the wrong GUID can fail even when the name matches an existing variable.
🧪 9. Reading and Writing Setup Data Safely #
A common mistake in firmware code is passing an unallocated data pointer to GetVariable() or assuming that a Setup variable always has a fixed size.
The correct approach is to query the variable size first, allocate an appropriate buffer, read the data, and then update the value.
9.1 Example: Read, modify, and write the Setup variable #
The following example assumes execution in a DXE environment where gRT and gBS are available and the platform defines SETUP_DATA and SETUP_GUID.
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Setup.h>
EFI_STATUS
UpdateSetupData (
VOID
)
{
EFI_STATUS Status;
EFI_GUID SetupGuid = SETUP_GUID;
UINTN VariableSize = 0;
UINT32 VariableAttributes = 0;
SETUP_DATA *SetupData = NULL;
//
// Query the variable size and retrieve its existing attributes.
//
Status = gRT->GetVariable (
L"Setup",
&SetupGuid,
&VariableAttributes,
&VariableSize,
NULL
);
if (Status != EFI_BUFFER_TOO_SMALL) {
return Status;
}
//
// Confirm that the variable contains the expected structure.
//
if (VariableSize < sizeof (SETUP_DATA)) {
return EFI_BAD_BUFFER_SIZE;
}
//
// Allocate a buffer large enough for the existing variable.
//
Status = gBS->AllocatePool (
EfiBootServicesData,
VariableSize,
(VOID **)&SetupData
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Read the variable contents.
//
Status = gRT->GetVariable (
L"Setup",
&SetupGuid,
&VariableAttributes,
&VariableSize,
SetupData
);
if (EFI_ERROR (Status)) {
gBS->FreePool (SetupData);
return Status;
}
//
// Modify the field according to the platform's definition.
// The value 2 is only an example and must be valid for this field.
//
SetupData->IdeController = 2;
//
// Write the updated structure using the existing variable attributes.
//
Status = gRT->SetVariable (
L"Setup",
&SetupGuid,
VariableAttributes,
VariableSize,
SetupData
);
gBS->FreePool (SetupData);
return Status;
}This is an illustrative implementation, not a universal Aptio Setup API. Confirm the exact structure size, field definition, variable attributes, and write policy before using it.
9.2 Why the size query matters #
The first GetVariable() call uses a zero data size and a null data buffer.
When the variable exists and the buffer is too small, the service returns EFI_BUFFER_TOO_SMALL and supplies the required buffer size.
The caller then allocates the buffer and performs the second read.
This prevents the firmware code from writing the variable into an uninitialized pointer or assuming that a stored structure has the expected size.
9.3 Why existing attributes must be preserved #
UEFI variable attributes control how a variable persists and which execution contexts may access it.
The example retrieves the current attributes and passes them to SetVariable() rather than blindly applying every common attribute.
This is important because the target variable might not use exactly the same combination of nonvolatile, boot-service, and runtime-access attributes as another platform.
Even with the correct attributes, a write can fail because of storage exhaustion, protection policy, authentication requirements, or platform-specific restrictions.
9.4 Verify the changed value #
After a successful write, read the variable again and check that the expected field has the intended value.
If the field controls hardware behavior, also verify whether the configuration takes effect immediately or only after the firmware applies the setting during a later boot.
Where an option is marked RESET_REQUIRED, the user interface should communicate the need for a reset rather than implying that the hardware configuration has already changed.
🔍 10. Debugging Common TSE Development Problems #
Setup customization can fail at several points in the build and execution pipeline. Separating these stages makes diagnosis much easier.
| Symptom | Likely causes | Recommended checks |
|---|---|---|
| Form is missing from Setup | VFR not included, incorrect form-set GUID, package registration failure | Inspect generated IFR and HII package registration |
| OEM control does not appear | SD conditions not satisfied, incorrect include point, token disabled | Inspect preprocessed VFR and build definitions |
| String displays incorrectly | Missing UNI token, unsupported language, incorrect language configuration | Inspect generated string packages and language declarations |
| Control displays an incorrect value | Wrong variable GUID, field offset, type, or initialization | Inspect the backing variable and structure definition |
| Selection does not invoke the callback | Missing interactive flag, incorrect question key, callback not installed | Inspect the VFR question and callback registration |
| Variable read fails | Incorrect name or GUID, unsupported phase interface, insufficient buffer | Validate the variable identity and GetVariable workflow |
| Variable write fails | Incorrect attributes, protected variable, storage exhaustion, access policy | Inspect status codes and variable-store policy |
| Setting changes but has no effect | Reset required, incorrect application logic, hardware restrictions | Verify the setting’s consumer and activation timing |
10.1 Inspect generated IFR #
If a VFR control does not appear, inspect the generated intermediate form representation rather than relying exclusively on the original source.
Confirm that the expected question and form opcodes exist and that the form set is included in the installed HII package list.
When an SD file is responsible for the insertion, also inspect the preprocessed or generated VFR output to determine whether the conditional inclusion occurred.
10.2 Inspect HII string resources #
If the form structure is present but a displayed string is missing, check the UNI source, generated string package, package registration, and active language configuration.
Dynamic string updates should be verified independently from static string compilation. A correctly compiled UNI token may still display an initial value if the runtime update routine is not executed.
10.3 Diagnose callbacks separately from persistence #
A user interaction, a callback invocation, and a persistent variable update are separate events.
A callback can be triggered without a successful variable write, and a variable can be updated without the intended hardware setting taking effect.
Instrument these steps independently using the diagnostics supported by the firmware project. Record the question identifier, requested value, callback action, returned status, and final stored variable value.
✅ Conclusion: Building Maintainable AMI TSE Setup Customizations #
AMI TSE provides a framework for implementing the BIOS Setup interface, while VFR, IFR, UNI, HII, and the Aptio-specific SD mechanism divide the work of describing forms, compiling their structure, managing localized strings, and integrating OEM controls.
For firmware developers, the key relationships are:
- VFR defines forms, questions, navigation, and interaction attributes.
- IFR encodes compiled forms as binary opcodes.
- SD supports modular Setup customization in applicable Aptio projects.
- UNI defines localized strings that are packaged for HII.
- HII and the Forms Browser connect form resources to the Setup interface.
- Callbacks implement supported interactive behavior and dynamic configuration logic.
- UEFI variable services provide access to persistent configuration data, subject to the current firmware phase and platform policy.
Keeping these responsibilities separate makes the Setup interface easier to extend and maintain across product variants.
The most important practical discipline is to validate the complete path: confirm that the correct source definitions are generated, that forms and strings are registered in HII, that callbacks use the expected interfaces, and that variable operations handle buffer sizes, GUIDs, attributes, and error conditions correctly.
Because Aptio implementations vary, developers should treat the examples as starting points and verify syntax, build tokens, callback conventions, and variable definitions against the exact core release used by their platform.