A shell section is similar to a function in other programming languages. You can pass multiple parameters to a shell section and receive multiple return values. Each shell section has a separate symbol table for storing its variables and their values.
The entrypoint sections used by the Setup program ([Identify], [ReturnOptions], [InstallOption]) are shell sections. The other types of sections ([Install] and [Detect]) are called by a command line in a shell section.
The following is the syntax for calling a shell section:
shell inf_file_path section_name [Args]*
You can use the shell command from within a shell section to call another shell section (in the same file or in a different INF file).
For a shell operation, Setup sets the value of the variable $ShellCode to one of the following:
!SHELL_CODE_OK |
Shelling operation was successful |
!SHELL_CODE_NO_SUCH_INF |
Named INF file could not be located |
!SHELL_CODE_NO_SUCH_SECTION |
The INF file did not contain named section |
!SHELL_CODE_ERROR |
Parsing error in INF section |
Programmers must check the value of $ShellCode before assuming that the return values and side-effects of the shelling operation actually apply.
Setup stores all its variable names and their values in its internal memory in an area called the symbol table. The shell statement has a special and very important effect on the symbol table.
When a shell statement is processed, a completely new symbol table is created. The original symbol table values are no longer directly accessible, and new variables and values are stored in this new, separate table. When the shelled section returns, this new symbol table is discarded. This behavior is similar to the “block scoping” rules common in procedural programming languages such as C.
The reason for such behavior is to avoid duplication or “collision” of variable names. The writer of an INF subroutine which is the target of a shell statement can be sure that variables he creates will not accidentally override global values.
This multi-level symbol table mechanism creates a new problem: how does a shelled section change or reference the value of a variable outside of its private, temporary symbol table? The answer is that Setup has special syntax for referencing variables which are nonlocal. The possibilities are:
local |
$(MyVar) |
reference to local variable MyVar |
global |
$(!MyVar) |
reference to global variable MyVar |
global |
$(!G:MyVar) |
reference to global variable MyVar |
parent |
$(!P:MyVar) |
reference to caller’s variable MyVar |
The outermost (or base) Setup symbol table is called the global symbol table. Variables created by Setup itself during initialization and the top-level INF file reside in the global symbol table. Setup allows access to three possibly distinct symbol tables: the local one, the one belonging to the shelling INF section, and the global one.
The Setup program stores a shell’s input parameters in the shell’s symbol table using variables of the form $N, where N refers to the zero-based position of the parameter in the argument list. The shell can then use the $(var) notation to retrieve the argument’s value, that is, $($0) retrieves the value of Arg0, $($1) is the value of Arg1, and so on. Using the Return command, a shell section can return zero or more values to the section that called it. The following example shows a shell section that retrieves its arguments and returns two values:
[SampleShellSection] ; retrieve the input parameters set Arg0 = $($0) set Arg1 = $($1) . . . ; return two values set Option = "OptionString" Return STATUS_SUCCESSFUL $(Option)
The Setup program stores a shell section’s return values in the symbol table of its parent shell section (that is, the shell that called it), using variables of the form $RN, where N refers to the zero-based position of value in the list of return values. The parent shell can then use the $(var) notation to retrieve the return values (that is, $($R0) retrieves the first return value, $($R1)the second return value, and so on). The Setup program uses the $RN variable to store the number of return values. In addition to the values returned by a shell section, the Setup program sets the ShellCode global variable to indicate whether errors occurred during its interpretation of the section. The following example shows the command lines that call a shell section, then retrieve the results:
; pass two parameters to AShellSection set Arg0 = "argument 0" set Arg1 = argument1 ; invoke section named AShellSection in the current inf file shell "" AShellSection $(Arg0) $(Arg1) ; check ShellCode for internal errors during AShellSection execution ifint $($ShellCode) != $(!SHELL_CODE_OK) exit endif ; get the return values set Status = $($R0) set Option = $($R1) ifint $($R#) > 2 set OptionText = $($R2) endif