Both BIOS and UEFI store variables in NVRAM - non-volatile RAM. The location of this is platform-specific - early BIOSes used the CMOS. BIOS variables, in CMOS or otherwise, were not standardised. Accessing their location sometimes was possible for the OS, sometimes not. Knowing their meaning meant knowing the BIOS version, potentially to a build level. Clearly, maintaining a catalogue of all BIOSes is untenable.
UEFI solves this problem. UEFI provides an extensible, standardised interface to access NVRAM variables - infact, it is one of the few runtime services that UEFI provides, indicating that the variables are not otherwise accessible to the OS. This means that at any point during the OS's execution, it can both get and set these variables.
Under the UEFI system table, under runtime services, there are 3 variable services provided.
typedef EFI_STATUS GetVariable ( IN CHAR16* VariableName, IN EFI_GUID* VendorGuid, OUT UINT32* Attributes OPTIONAL, IN OUT UINTN* DataSize, OUT VOID* Data OPTIONAL ); typedef EFI_STATUS GetNextVariableName ( IN OUT UINTN *VariableNameSize, IN OUT CHAR16 *VariableName, IN OUT EFI_GUID *VendorGuid ); typedef EFI_STATUS SetVariable ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data );