ReactOS 0.4.15-dev-8127-g6338913
UEFIFirmware.c
Go to the documentation of this file.
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
24typedef enum _FIRMWARE_TYPE
25{
31
32typedef
33_Success_(return)
34BOOL
36FN_GetFirmwareType(_Out_ PFIRMWARE_TYPE FirmwareType);
37
38static ULONG RandomSeed;
39static DWORD EfiVariableValue;
40
41static VOID test_GetFirmwareType(BOOL bIsUEFI)
42{
43 BOOL bResult;
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
77START_TEST(UEFIFirmware)
78{
79 BOOL bResult, bResultTemp, bIsUEFI;
80 DWORD dwError, dwErrorTemp, dwLength, dwLengthTemp, dwValue;
81 HANDLE hToken;
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),
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,
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. */
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 */
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 */
151 if (!bResult)
152 {
153 skip("OpenProcessToken failed with error: 0x%08lX, aborting.\n", GetLastError());
154 return;
155 }
156 Privilege.PrivilegeCount = 1;
158 Privilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
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 */
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),
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);
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,
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 */
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),
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 */
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 }
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,
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;
276 ok(Status == STATUS_SUCCESS, "NtAdjustPrivilegesToken failed with status: 0x%08lX\n", Status);
277 NtClose(hToken);
278}
_FIRMWARE_TYPE
Definition: UEFIFirmware.c:25
@ FirmwareTypeUnknown
Definition: UEFIFirmware.c:26
@ FirmwareTypeUefi
Definition: UEFIFirmware.c:28
@ FirmwareTypeBios
Definition: UEFIFirmware.c:27
@ FirmwareTypeMax
Definition: UEFIFirmware.c:29
enum _FIRMWARE_TYPE FIRMWARE_TYPE
#define EFI_DUMMY_NAMESPACE_GUID_STRING
Definition: UEFIFirmware.c:21
enum _FIRMWARE_TYPE * PFIRMWARE_TYPE
#define EFI_TEST_VARIABLE_NAME
Definition: UEFIFirmware.c:19
#define _A2W(quote)
Definition: UEFIFirmware.c:15
#define EFI_TEST_GUID_STRING
Definition: UEFIFirmware.c:18
#define EFI_DUMMY_VARIABLE_NAME
Definition: UEFIFirmware.c:22
void _exit(int exitcode)
Definition: _exit.c:25
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
#define GetProcAddress(x, y)
Definition: compat.h:753
#define GetCurrentProcess()
Definition: compat.h:759
static DWORD DWORD * dwLength
Definition: fusion.c:86
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
BOOL WINAPI SetFirmwareEnvironmentVariableA(_In_ LPCSTR lpName, _In_ LPCSTR lpGuid, _In_reads_bytes_opt_(nSize) PVOID pValue, _In_ DWORD nSize)
Definition: sysinfo.c:496
BOOL WINAPI SetFirmwareEnvironmentVariableW(_In_ LPCWSTR lpName, _In_ LPCWSTR lpGuid, _In_reads_bytes_opt_(nSize) PVOID pValue, _In_ DWORD nSize)
Definition: sysinfo.c:481
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:25
HANDLE hKernel32
Definition: locale.c:13
#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE
Definition: security.c:676
#define _Success_(expr)
Definition: ms_sal.h:259
#define _Out_
Definition: ms_sal.h:345
NTSYSAPI ULONG NTAPI RtlRandom(_Inout_ PULONG Seed)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define L(x)
Definition: ntvdm.h:50
#define STATUS_SUCCESS
Definition: shellext.h:65
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtAdjustPrivilegesToken(_In_ HANDLE TokenHandle, _In_ BOOLEAN DisableAllPrivileges, _In_opt_ PTOKEN_PRIVILEGES NewState, _In_ ULONG BufferLength, _Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_PRIVILEGES PreviousState, _When_(PreviousState!=NULL, _Out_) PULONG ReturnLength)
Removes a certain amount of privileges of a token based upon the request by the caller.
Definition: tokenadj.c:451
uint32_t ULONG
Definition: typedefs.h:59
BOOL Privilege(LPTSTR pszPrivilege, BOOL bEnable)
Definition: user_lib.cpp:531
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WINAPI
Definition: msvc.h:6
#define ERROR_PRIVILEGE_NOT_HELD
Definition: winerror.h:796
FORCEINLINE LUID NTAPI_INLINE RtlConvertUlongToLuid(_In_ ULONG Val)
Definition: rtlfuncs.h:3541
#define TOKEN_ADJUST_PRIVILEGES
Definition: setypes.h:930
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63