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/UefiVarToolREADME
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:
-for--forceForce-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# Alreadycomment in the output.-hor--helpShows the usage information. If this option is selected, no other operations will be performed.-ror--restartReboots the system upon successful completion. No restart will be performed if any of the operations failed.-sor--simulateIf 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-for--forceis 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 write0x01to 4 bytes starting at offset0x00, the value of0x01will be at the offset of0x00and not0x03, although if you read these 4 bytes again, the result will also be shown as0x00000001. 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:0x00reads the byte value at offset0x00in the variableLanguvt -s Lang:0x00(4)=0x01020304simulates writing a double-word (four-byte) value to an offset starting at0x00in the variableLanguvt 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
