1 /* 2 * PROJECT: ReactOS API Tests 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Tests for UEFI Firmware functions 5 * COPYRIGHT: Copyright 2023 Ratin Gao <ratin@knsoft.org> 6 */ 7 8 #include "precomp.h" 9 10 #include <ndk/psfuncs.h> 11 #include <ndk/setypes.h> 12 #include <ndk/sefuncs.h> 13 #include <ndk/obfuncs.h> 14 15 #define _A2W(quote) __A2W(quote) 16 #define __A2W(quote) L##quote 17 18 #define EFI_TEST_GUID_STRING "{8768B7AC-F82F-4120-B093-30DFA27DA3B5}" 19 #define EFI_TEST_VARIABLE_NAME "RosUefiVarTest" 20 21 #define EFI_DUMMY_NAMESPACE_GUID_STRING "{00000000-0000-0000-0000-000000000000}" 22 #define EFI_DUMMY_VARIABLE_NAME "" 23 24 typedef enum _FIRMWARE_TYPE 25 { 26 FirmwareTypeUnknown, 27 FirmwareTypeBios, 28 FirmwareTypeUefi, 29 FirmwareTypeMax 30 } FIRMWARE_TYPE, *PFIRMWARE_TYPE; 31 32 typedef 33 _Success_(return) 34 BOOL 35 WINAPI 36 FN_GetFirmwareType(_Out_ PFIRMWARE_TYPE FirmwareType); 37 38 static ULONG RandomSeed; 39 static DWORD EfiVariableValue; 40 41 static VOID test_GetFirmwareType(BOOL bIsUEFI) 42 { 43 BOOL bResult; 44 HMODULE hKernel32; 45 FN_GetFirmwareType* pfnGetFirmwareType; 46 FIRMWARE_TYPE FirmwareType = FirmwareTypeUnknown, FirmwareExpect; 47 48 /* Load functions */ 49 hKernel32 = GetModuleHandleW(L"kernel32.dll"); 50 if (hKernel32 == NULL) 51 { 52 skip("Module kernel32 not found\n"); 53 return; 54 } 55 pfnGetFirmwareType = (FN_GetFirmwareType*)GetProcAddress(hKernel32, "GetFirmwareType"); 56 if (pfnGetFirmwareType == NULL) 57 { 58 skip("GetFirmwareType (NT6.2+ API) not found\n"); 59 return; 60 } 61 62 /* Test GetFirmwareType, should return FirmwareTypeBios or FirmwareTypeUefi */ 63 bResult = pfnGetFirmwareType(&FirmwareType); 64 ok(bResult, 65 "GetFirmwareType failed with error: 0x%08lX\n", 66 GetLastError()); 67 68 if (!bResult) 69 return; 70 71 FirmwareExpect = (bIsUEFI ? FirmwareTypeUefi : FirmwareTypeBios); 72 ok(FirmwareType == FirmwareExpect, 73 "FirmwareType is %d, but %d is expected.\n", 74 FirmwareType, FirmwareExpect); 75 } 76 77 START_TEST(UEFIFirmware) 78 { 79 BOOL bResult, bResultTemp, bIsUEFI; 80 DWORD dwError, dwErrorTemp, dwLength, dwLengthTemp, dwValue; 81 HANDLE hToken; 82 TOKEN_PRIVILEGES Privilege; 83 NTSTATUS Status; 84 ULONG ReturnLength; 85 86 /* 87 * Check whether this test runs on legacy BIOS-based or UEFI system 88 * by calling GetFirmwareEnvironmentVariable with dummy name and GUID. 89 * It should fail with ERROR_INVALID_FUNCTION on the former and 90 * fail with another error on the latter. 91 */ 92 dwLength = GetFirmwareEnvironmentVariableW(_A2W(EFI_DUMMY_VARIABLE_NAME), 93 _A2W(EFI_DUMMY_NAMESPACE_GUID_STRING), 94 NULL, 95 0); 96 dwError = GetLastError(); 97 ok(dwLength == 0, "dwLength = %lu, expected 0\n", dwLength); 98 99 bIsUEFI = (dwLength == 0 && dwError != ERROR_INVALID_FUNCTION); 100 test_GetFirmwareType(bIsUEFI); 101 if (!bIsUEFI) 102 { 103 skip("Skipping tests that require UEFI environment.\n"); 104 return; 105 } 106 107 /* Test ANSI function too */ 108 dwLengthTemp = GetFirmwareEnvironmentVariableA(EFI_DUMMY_VARIABLE_NAME, 109 EFI_DUMMY_NAMESPACE_GUID_STRING, 110 NULL, 111 0); 112 dwErrorTemp = GetLastError(); 113 ok(dwLengthTemp == dwLength && dwErrorTemp == dwError, 114 "dwLength = %lu, LastError = %lu, expected bResult = %lu, LastError = %lu\n", 115 dwLengthTemp, 116 dwErrorTemp, 117 dwLength, 118 dwError); 119 120 /* Generate a random variable value to be used in this test */ 121 RandomSeed = GetTickCount(); 122 EfiVariableValue = RtlRandom(&RandomSeed); 123 124 /* Try to set firmware variable, should fail with ERROR_PRIVILEGE_NOT_HELD, 125 * because no SE_SYSTEM_ENVIRONMENT_NAME privilege enabled by default. */ 126 bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 127 _A2W(EFI_TEST_GUID_STRING), 128 &EfiVariableValue, 129 sizeof(EfiVariableValue)); 130 dwError = GetLastError(); 131 ok(!bResult && dwError == ERROR_PRIVILEGE_NOT_HELD, 132 "bResult = %d, LastError = %lu, expected bResult = 0, LastError = ERROR_PRIVILEGE_NOT_HELD\n", 133 bResult, 134 dwError); 135 136 /* Test ANSI function too */ 137 bResultTemp = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 138 EFI_TEST_GUID_STRING, 139 &EfiVariableValue, 140 sizeof(EfiVariableValue)); 141 dwErrorTemp = GetLastError(); 142 ok(bResultTemp == bResult && dwErrorTemp == dwError, 143 "bResult = %d, LastError = %lu, expected bResult = %d, LastError = %lu\n", 144 bResultTemp, 145 dwErrorTemp, 146 bResult, 147 dwError); 148 149 /* Enable SE_SYSTEM_ENVIRONMENT_NAME privilege required by the following tests */ 150 bResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); 151 if (!bResult) 152 { 153 skip("OpenProcessToken failed with error: 0x%08lX, aborting.\n", GetLastError()); 154 return; 155 } 156 Privilege.PrivilegeCount = 1; 157 Privilege.Privileges[0].Luid = RtlConvertUlongToLuid(SE_SYSTEM_ENVIRONMENT_PRIVILEGE); 158 Privilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 159 Status = NtAdjustPrivilegesToken(hToken, FALSE, &Privilege, sizeof(Privilege), NULL, &ReturnLength); 160 if (Status != STATUS_SUCCESS) 161 { 162 skip("NtAdjustPrivilegesToken failed with status: 0x%08lX, aborting.\n", Status); 163 NtClose(hToken); 164 return; 165 } 166 167 /* Set our test variable to UEFI firmware */ 168 bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 169 _A2W(EFI_TEST_GUID_STRING), 170 &EfiVariableValue, 171 sizeof(EfiVariableValue)); 172 ok(bResult, 173 "SetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n", 174 GetLastError()); 175 if (bResult) 176 { 177 /* Get the variable back and verify */ 178 dwLength = GetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 179 _A2W(EFI_TEST_GUID_STRING), 180 &dwValue, 181 sizeof(dwValue)); 182 ok(dwLength, 183 "GetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n", 184 GetLastError()); 185 if (dwLength) 186 { 187 ok(dwLength == sizeof(EfiVariableValue) && dwValue == EfiVariableValue, 188 "Retrieved variable different from what we set, " 189 "dwLength = %lu, dwValue = %lu, expected dwLength = %u, dwValue = %lu", 190 dwLength, 191 dwValue, 192 sizeof(EfiVariableValue), 193 EfiVariableValue); 194 } 195 } 196 197 /* Change variable value and test ANSI function */ 198 EfiVariableValue = RtlRandom(&RandomSeed); 199 bResult = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 200 EFI_TEST_GUID_STRING, 201 &EfiVariableValue, 202 sizeof(EfiVariableValue)); 203 ok(bResult, 204 "SetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n", 205 GetLastError()); 206 if (bResult) 207 { 208 /* Get the variable back and verify */ 209 dwLength = GetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 210 EFI_TEST_GUID_STRING, 211 &dwValue, 212 sizeof(dwValue)); 213 ok(dwLength, 214 "GetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n", 215 GetLastError()); 216 if (dwLength) 217 { 218 ok(dwLength == sizeof(EfiVariableValue) && dwValue == EfiVariableValue, 219 "Retrieved variable different from what we set, " 220 "dwLength = %lu, dwValue = %lu, expected dwLength = %u, dwValue = %lu", 221 dwLength, 222 dwValue, 223 sizeof(EfiVariableValue), 224 EfiVariableValue); 225 } 226 } 227 228 /* Delete the variable */ 229 bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 230 _A2W(EFI_TEST_GUID_STRING), 231 NULL, 232 0); 233 ok(bResult, 234 "SetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n", 235 GetLastError()); 236 if (bResult) 237 { 238 dwLength = GetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 239 _A2W(EFI_TEST_GUID_STRING), 240 &dwValue, 241 sizeof(dwValue)); 242 ok(dwLength == 0, "SetFirmwareEnvironmentVariableW didn't delete the variable!\n"); 243 } 244 245 /* Restore variable and test ANSI function */ 246 bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 247 _A2W(EFI_TEST_GUID_STRING), 248 &EfiVariableValue, 249 sizeof(EfiVariableValue)); 250 if (!bResult) 251 { 252 skip("SetFirmwareEnvironmentVariableW failed to restore variable with error: 0x%08lX\n", 253 GetLastError()); 254 goto _exit; 255 } 256 bResult = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 257 EFI_TEST_GUID_STRING, 258 NULL, 259 0); 260 ok(bResult, 261 "SetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n", 262 GetLastError()); 263 if (bResult) 264 { 265 dwLength = GetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 266 EFI_TEST_GUID_STRING, 267 &dwValue, 268 sizeof(dwValue)); 269 ok(dwLength == 0, "SetFirmwareEnvironmentVariableA didn't delete the variable!\n"); 270 } 271 272 _exit: 273 /* Restore the privilege */ 274 Privilege.Privileges[0].Attributes = 0; 275 Status = NtAdjustPrivilegesToken(hToken, FALSE, &Privilege, sizeof(Privilege), NULL, &ReturnLength); 276 ok(Status == STATUS_SUCCESS, "NtAdjustPrivilegesToken failed with status: 0x%08lX\n", Status); 277 NtClose(hToken); 278 } 279