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 static ULONG RandomSeed; 25 static DWORD EfiVariableValue; 26 27 static VOID test_GetFirmwareType(BOOL bIsUEFI) 28 { 29 #if (_WIN32_WINNT >= 0x0602) 30 BOOL bResult; 31 FIRMWARE_TYPE FirmwareType = FirmwareTypeUnknown, FirmwareExpect; 32 33 /* Test GetFirmwareType, should return FirmwareTypeBios or FirmwareTypeUefi */ 34 bResult = GetFirmwareType(&FirmwareType); 35 36 ok(bResult, 37 "GetFirmwareType failed with error: 0x%08lX\n", 38 GetLastError()); 39 40 if (!bResult) 41 return; 42 43 FirmwareExpect = (bIsUEFI ? FirmwareTypeUefi : FirmwareTypeBios); 44 ok(FirmwareType == FirmwareExpect, 45 "FirmwareType is %d, but %d is expected.\n", 46 FirmwareType, FirmwareExpect); 47 #else 48 skip("This test can be run only when compiled for NT >= 6.2.\n"); 49 #endif 50 } 51 52 START_TEST(UEFIFirmware) 53 { 54 BOOL bResult, bResultTemp, bIsUEFI; 55 DWORD dwError, dwErrorTemp, dwLength, dwLengthTemp, dwValue; 56 HANDLE hToken; 57 TOKEN_PRIVILEGES Privilege; 58 NTSTATUS Status; 59 ULONG ReturnLength; 60 61 /* 62 * Check whether this test runs on legacy BIOS-based or UEFI system 63 * by calling GetFirmwareEnvironmentVariable with dummy name and GUID. 64 * It should fail with ERROR_INVALID_FUNCTION on the former and 65 * fail with another error on the latter. 66 */ 67 dwLength = GetFirmwareEnvironmentVariableW(_A2W(EFI_DUMMY_VARIABLE_NAME), 68 _A2W(EFI_DUMMY_NAMESPACE_GUID_STRING), 69 NULL, 70 0); 71 dwError = GetLastError(); 72 ok(dwLength == 0, "dwLength = %lu, expected 0\n", dwLength); 73 74 bIsUEFI = (dwLength == 0 && dwError != ERROR_INVALID_FUNCTION); 75 test_GetFirmwareType(bIsUEFI); 76 if (!bIsUEFI) 77 { 78 skip("Skipping tests that require UEFI environment.\n"); 79 return; 80 } 81 82 /* Test ANSI function too */ 83 dwLengthTemp = GetFirmwareEnvironmentVariableA(EFI_DUMMY_VARIABLE_NAME, 84 EFI_DUMMY_NAMESPACE_GUID_STRING, 85 NULL, 86 0); 87 dwErrorTemp = GetLastError(); 88 ok(dwLengthTemp == dwLength && dwErrorTemp == dwError, 89 "dwLength = %lu, LastError = %lu, expected bResult = %lu, LastError = %lu\n", 90 dwLengthTemp, 91 dwErrorTemp, 92 dwLength, 93 dwError); 94 95 /* Generate a random variable value to be used in this test */ 96 RandomSeed = GetTickCount(); 97 EfiVariableValue = RtlRandom(&RandomSeed); 98 99 /* Try to set firmware variable, should fail with ERROR_PRIVILEGE_NOT_HELD, 100 * because no SE_SYSTEM_ENVIRONMENT_NAME privilege enabled by default. */ 101 bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 102 _A2W(EFI_TEST_GUID_STRING), 103 &EfiVariableValue, 104 sizeof(EfiVariableValue)); 105 dwError = GetLastError(); 106 ok(!bResult && dwError == ERROR_PRIVILEGE_NOT_HELD, 107 "bResult = %d, LastError = %lu, expected bResult = 0, LastError = ERROR_PRIVILEGE_NOT_HELD\n", 108 bResult, 109 dwError); 110 111 /* Test ANSI function too */ 112 bResultTemp = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 113 EFI_TEST_GUID_STRING, 114 &EfiVariableValue, 115 sizeof(EfiVariableValue)); 116 dwErrorTemp = GetLastError(); 117 ok(bResultTemp == bResult && dwErrorTemp == dwError, 118 "bResult = %d, LastError = %lu, expected bResult = %d, LastError = %lu\n", 119 bResultTemp, 120 dwErrorTemp, 121 bResult, 122 dwError); 123 124 /* Enable SE_SYSTEM_ENVIRONMENT_NAME privilege required by the following tests */ 125 bResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); 126 if (!bResult) 127 { 128 skip("OpenProcessToken failed with error: 0x%08lX, aborting.\n", GetLastError()); 129 return; 130 } 131 Privilege.PrivilegeCount = 1; 132 Privilege.Privileges[0].Luid = RtlConvertUlongToLuid(SE_SYSTEM_ENVIRONMENT_PRIVILEGE); 133 Privilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 134 Status = NtAdjustPrivilegesToken(hToken, FALSE, &Privilege, sizeof(Privilege), NULL, &ReturnLength); 135 if (Status != STATUS_SUCCESS) 136 { 137 skip("NtAdjustPrivilegesToken failed with status: 0x%08lX, aborting.\n", Status); 138 NtClose(hToken); 139 return; 140 } 141 142 /* Set our test variable to UEFI firmware */ 143 bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 144 _A2W(EFI_TEST_GUID_STRING), 145 &EfiVariableValue, 146 sizeof(EfiVariableValue)); 147 ok(bResult, 148 "SetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n", 149 GetLastError()); 150 if (bResult) 151 { 152 /* Get the variable back and verify */ 153 dwLength = GetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 154 _A2W(EFI_TEST_GUID_STRING), 155 &dwValue, 156 sizeof(dwValue)); 157 ok(dwLength, 158 "GetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n", 159 GetLastError()); 160 if (dwLength) 161 { 162 ok(dwLength == sizeof(EfiVariableValue) && dwValue == EfiVariableValue, 163 "Retrieved variable different from what we set, " 164 "dwLength = %lu, dwValue = %lu, expected dwLength = %u, dwValue = %lu", 165 dwLength, 166 dwValue, 167 sizeof(EfiVariableValue), 168 EfiVariableValue); 169 } 170 } 171 172 /* Change variable value and test ANSI function */ 173 EfiVariableValue = RtlRandom(&RandomSeed); 174 bResult = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 175 EFI_TEST_GUID_STRING, 176 &EfiVariableValue, 177 sizeof(EfiVariableValue)); 178 ok(bResult, 179 "SetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n", 180 GetLastError()); 181 if (bResult) 182 { 183 /* Get the variable back and verify */ 184 dwLength = GetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 185 EFI_TEST_GUID_STRING, 186 &dwValue, 187 sizeof(dwValue)); 188 ok(dwLength, 189 "GetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n", 190 GetLastError()); 191 if (dwLength) 192 { 193 ok(dwLength == sizeof(EfiVariableValue) && dwValue == EfiVariableValue, 194 "Retrieved variable different from what we set, " 195 "dwLength = %lu, dwValue = %lu, expected dwLength = %u, dwValue = %lu", 196 dwLength, 197 dwValue, 198 sizeof(EfiVariableValue), 199 EfiVariableValue); 200 } 201 } 202 203 /* Delete the variable */ 204 bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 205 _A2W(EFI_TEST_GUID_STRING), 206 NULL, 207 0); 208 ok(bResult, 209 "SetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n", 210 GetLastError()); 211 if (bResult) 212 { 213 dwLength = GetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 214 _A2W(EFI_TEST_GUID_STRING), 215 &dwValue, 216 sizeof(dwValue)); 217 ok(dwLength == 0, "SetFirmwareEnvironmentVariableW didn't delete the variable!\n"); 218 } 219 220 /* Restore variable and test ANSI function */ 221 bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME), 222 _A2W(EFI_TEST_GUID_STRING), 223 &EfiVariableValue, 224 sizeof(EfiVariableValue)); 225 if (!bResult) 226 { 227 skip("SetFirmwareEnvironmentVariableW failed to restore variable with error: 0x%08lX\n", 228 GetLastError()); 229 goto _exit; 230 } 231 bResult = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 232 EFI_TEST_GUID_STRING, 233 NULL, 234 0); 235 ok(bResult, 236 "SetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n", 237 GetLastError()); 238 if (bResult) 239 { 240 dwLength = GetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME, 241 EFI_TEST_GUID_STRING, 242 &dwValue, 243 sizeof(dwValue)); 244 ok(dwLength == 0, "SetFirmwareEnvironmentVariableA didn't delete the variable!\n"); 245 } 246 247 _exit: 248 /* Restore the privilege */ 249 Privilege.Privileges[0].Attributes = 0; 250 Status = NtAdjustPrivilegesToken(hToken, FALSE, &Privilege, sizeof(Privilege), NULL, &ReturnLength); 251 ok(Status == STATUS_SUCCESS, "NtAdjustPrivilegesToken failed with status: 0x%08lX\n", Status); 252 NtClose(hToken); 253 } 254