SkillAgentSearch skills...

UefiVarTool

Scriptable tool to read and write UEFI variables from EFI shell. View, save, edit and restore hidden UEFI (BIOS) Setup settings faster than with the OEM menu forms.

Install / Use

/learn @GeographicCone/UefiVarTool
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"><img alt="UEFI Variable Tool (UVT) Logo" src="https://github.com/GeographicCone/UefiVarTool/blob/master/extra/uvt-logo.png?raw=true" width="67%"/></p>

UEFI Variable Tool (UVT)

UEFI Variable Tool (UVT) is a command-line application that runs from the UEFI shell. It can be launched in seconds from any FAT flash drive with no prior machine-specific setup, and lets you view and modify the content of individual UEFI variables at a byte level.

UVT's purpose is to allow changing all the hidden UEFI (BIOS) Setup hardware settings. It is well-suited for situations when custom firmware, such as a modified BIOS that would unhide all the menu forms, cannot be flashed due to restrictive anti-features such as Boot Guard being enabled.

While various utilities have existed for a long time to allow doing just the same, making the functionality as such hardly a novelty, UVT aims to make the process as efficient and unencumbered as possible. To that effect:

  • It greatly streamlines the command-line argument syntax
  • It can also work in scripted mode to execute an arbitrarily-long series of operations from the standard input (stdin)
  • While in this mode, it allows defining aliases to identify data of interest (variable name, offset, and size), and referencing these later for read and write operations
  • The output format follows the input, which means it can be saved to a file and fed back as standard input to restore the saved settings later

UVT is free software, and full source code is available for anyone to tinker with. It is a quite heavily modified version of setup_var.efi by @datasone, to whom I originally made some improvement suggestions. He followed up on them and even graciously included me as a co-author in his commit, never mind that I had not at that point written a single line of code.

@datasone's last-posted version seemed at least 90% there but wasn't working for me in a couple of ways. Since he's probably busy with other stuff in his life, I decided it was my turn to contribute something. Hence this fork, which although is completely refactored to the point it might not look very much like the original, would have never been possible without all of @datasone's work, which he generously shared with the world. For that I am eternally grateful to him, and want everyone to know he deserves all the credit as the original author of this utility.

How to Use

The in-application usage information summary is reproduced below for reference:

Usage: uvt[.efi] [<Options>] <Op1> [<Op2> [... [<OpN>]]
- or - uvt[.efi] < <InputFile>
Where:
<Options>: Optional global-scope application settings
  -f --force     Force-write values even if already set as requested
  -h --help      Show usage information (precludes other operations)
  -r --restart   Upon successful completion, perform a system restart
  -s --simulate  Do not write, only simulate actions (will still read)
<Op#>: Operation(s) to perform, can be multiple, each in the format:
  <VarName>[(<VarId>)]:<Offset>[(<Size>)][=<Value>]
Arg Overview:
  <VarName>      UEFI variable name to read or write to, case-sensitive
  <VarId>        If two variables share a name, will prompt to use this
  <Offset>       Data starting position within the given UEFI variable
  <Size>         Optional, a byte (1) by default if omitted; little-endian
  <Value>        Value to write, 8 bytes (64 bits) maximum; read if absent
  <InputFile>    Script to run, same base format as arguments + see below
File Overview:
  #                                   Comment, ignored until end of line
  !<force|restart|simulate>           Set options, same as above arguments
  <Def>,<VarName>:<Offset>[(<Size>)]  Define a variable to reference later
  @<Def>[=<Value>]                    Assign to a referenced variable
Example Command Line:
  uvt -s Lang:0x00 Lang:0x00(4)=0x01020304 Lang:0x00(4)
  Read byte at offset 0, simulate-set the dword (4 bytes), then read again
Example Input File:
  !simulate              # Simulate only, do not perform actual writes
  Language,Lang:0x00(4)  # Define a reference under the alias "Language"
  @Language=0x01020304   # Write to the target referred to by "Language"

<Offset>, <Size> and <Value> can be decimal or hexadecimal: use prefix "0x"
File should be a UTF-16 LE text, UEFI firmware and shell version-dependent
Output saved to a file can be re-used as input again: format is the same

Prerequisites

You need to boot into UEFI shell on the machine where you want to use the utility. This typically involves setting up a FAT flash drive and placing an EFI shell binary under the path efi/boot/bootx64.efi. You can then place the UVT binary under efi/tools/uvt.efi and run it as uvt regardless of what the current directory is. More on this in the Background section.

On a broader note, you need to know the variable layout, which is specific to your particular hardware, and possibly even the firmware version. How to obtain this information is also addressed in the Background section.

Separately, it is possible to run UVT in an emulator. As this would be mostly of interest to a developer, it is described in the Building section.

Command Line

There are two ways to use UVT. The first one is to run it with command-line arguments.

UVT accepts two kinds of command-line arguments: operations and options. Arguments are separated with spaces. There is no limit on the number of arguments.

Options

Options start with a - (minus) sign and are used to define global-scope settings. Each option has a short and a long form, taking a single - and a letter or a double -- and a keyword respectively. The options are:

  • -f or --force Force-write values where the current values is equal to the new one. The default behavior is to skip such operations, and annotate such entries with an # Already comment in the output.
  • -h or --help Shows the usage information. If this option is selected, no other operations will be performed.
  • -r or --restart Reboots the system upon successful completion. No restart will be performed if any of the operations failed.
  • -s or --simulate If set, no changes will be made to UEFI variables. All the other aspects of the application will still be functioning exactly in the same way. This might be useful for checking what an operation would do, or whether the arguments are syntactically correct. If -f or --force is specified together with this option, no writing will happen regardless: the simulation takes precedence.

Operations

Operations define either reading (querying, or getting) or writing (assigning, or setting) a value. The syntax is:

<VarName>[(<VarId>)]:<Offset>[(<Size>)][=<Value>]

Where:

  • <VarName> is the UEFI variable name. It is case-sensitive and mandatory: there is no default.
  • <VarId> is an optional identifier to distinguish between variables in a situation when two or more share the same name. In the unlikely scenario this happens, the application will automatically list all the variables with the matching name, alongside with their respective identifiers.
  • <Offset> is the position of data within the variable where the value data starts. Remember the count starts from 0, not 1.
  • <Size> is the optional size of the variable: it defaults to a single byte, i.e. (1), which can also be specified, although that's unnecessary. The application can write at most 8 bytes (or 64 bits) at a time.
  • <Value> is the new value to be written at the given offset. The value must fit within the <Size> constraint, which is checked. Multi-byte values are little-endian, which means that if you write 0x01 to 4 bytes starting at offset 0x00, the value of 0x01 will be at the offset of 0x00 and not 0x03, although if you read these 4 bytes again, the result will also be shown as 0x00000001. If you are unfamiliar with the concept or do not understand its implications, it's best to write individual bytes, and that's what the vast majority of UEFI Setup settings are anyway. This part, alongside the = assignment operator, is optional: if absent, the default action is to query and output the current value.

For example:

  • uvt Lang:0x00 reads the byte value at offset 0x00 in the variable Lang
  • uvt -s Lang:0x00(4)=0x01020304 simulates writing a double-word (four-byte) value to an offset starting at 0x00 in the variable Lang
  • uvt Lang:0x00(4) reads again the double word that has just been written with the preceding command

An arbitrary number of command-line operations can be specified. They will be executed in the order entered. An error interrupts the processing of any further operations and arguments, terminating the application.

Numerical Values

Any number can be specified as either decimal (base 10) or hexadecimal (base 16). Hexadecimal values should be preceded by 0x or 0X, otherwise they will be parsed as decimal. Only digits 0-9 are allowed in decimal values. The additional digits a-f and A-F in hexadecimal values are case-insensitive.

Offsets and values are output in hexadecimal, while sizes are shown in decimal. When printed, hexadecimal values for offsets will be zero-padded to 2 bytes. Values will be zero-padded to their size. The padding does not have to be preserved in input, i.e. you can type 0x1 for a word-sized (two-byte) value, instead of writing 0x0001.

Output

UVT's output follows the same syntax as the input it accepts. This way, nearly everything it

View on GitHub
GitHub Stars71
CategoryDevelopment
Updated7d ago
Forks6

Languages

Rust

Security Score

95/100

Audited on Mar 26, 2026

No findings