UEFI Shell Script Syntax for Automation

UEFI Shell scripting provides a pre-boot environment for automating hardware diagnostics, firmware updates, and operating system provisioning using script files with the .nsh extension. This article details the core syntax rules of the UEFI Shell scripting language, outlining how to implement variables, conditions, loops, and control flow directives to build functional automation routines before an operating system loads.

Script Files and Comments

UEFI Shell scripts use the .nsh file extension. The shell automatically executes a script named startup.nsh upon boot if it resides in the root of an accessible EFI System Partition.

Comments are designated using either the # symbol or the rem command. The interpreter ignores text following these markers on the same line:

# This is a comment
rem This is also a valid comment

Commands are case-insensitive. Standard CLI utilities (such as ls, cp, map, and echo) can be directly embedded into scripts.

Variables and Parameters

Variables in UEFI Shell scripts are created, modified, and dereferenced using a syntax similar to traditional DOS batch files:

  • Environment Variables: Defined using the set command and dereferenced by enclosing the identifier in percent signs:

    set TargetDisk FS0:
    echo The selected disk is %TargetDisk%
  • Script Arguments: Positional parameters passed into a script are accessed using numeric identifiers from %0 to %9:

    • %0 represents the name of the executing script.
    • %1 through %9 represent the first through ninth command-line arguments.
    • %* expands to all parameters passed to the script.

Conditional Statements

The if construct handles decision-making logic. Every if block must be closed with an endif directive, and optional alternative paths are defined using else.

if condition then
    # commands
else
    # alternate commands
endif

Common conditions include:

  • String Comparison: Checks equivalence between two values:

    if %1 == "flash" then
        echo Flashing firmware...
    endif
  • File Existence: Determines if a specified file or directory path exists:

    if exist FS0:\EFI\BOOT\BOOTX64.EFI then
        echo Bootloader found.
    endif
  • Error Level: Evaluates the exit code of the preceding command:

    if errorlevel 1 then
        echo The previous command failed.
    endif

Negation is supported by placing not immediately after if (for example, if not exist file.txt then).

Loops

The UEFI Shell provides the for loop to iterate through sets of items, files, or devices. The iteration block begins with for and ends with endfor:

for %i in FS0: FS1: FS2: do
    if exist %i\startup.nsh then
        echo Found startup script on %i
    endif
endfor

To iterate over files matching a pattern:

for %f in *.efi do
    echo Found binary: %f
endfor

The loop variable must be preceded by a single % sign.

Branching and Control Flow

Execution flow within scripts can be altered using labels and jumps:

  • Labels: Defined by a leading colon (:):

    :RetryBlock
  • Jumps: The goto command redirects execution to a declared label:

    goto RetryBlock
  • Terminating Execution: The exit command halts script processing:

    exit /b 0

    The /b switch terminates only the current script instead of closing the entire UEFI Shell, and appending an integer sets the return exit code.

Redirection and Output

Standard output and error streams can be redirected to text files using output operators:

  • > writes or overwrites standard output to a file (e.g., pci > pci_dump.txt).
  • >> appends standard output to an existing file.
  • echo -off suppresses the printing of command lines to the console during script execution, while echo -on restores it.