Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.

Commit d895789

Browse files
author
Andrei Warkentin
committed
Add SetCon tool.
Fixes #39 Signed-off-by: Andrei Warkentin <[email protected]>
1 parent deded02 commit d895789

File tree

4 files changed

+495
-3
lines changed

4 files changed

+495
-3
lines changed

Application/SetCon/SetCon.c

Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
/** @file
2+
3+
Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
4+
Copyright (C) 2016 Andrei Evgenievich Warkentin
5+
6+
SPDX-License-Identifier: BSD-2-Clause-Patent
7+
8+
**/
9+
10+
#include <Uefi.h>
11+
#include <Library/UefiLib.h>
12+
#include <Library/MemoryAllocationLib.h>
13+
#include <Library/UefiBootServicesTableLib.h>
14+
#include <Library/UefiRuntimeServicesTableLib.h>
15+
#include <Library/UefiApplicationEntryPoint.h>
16+
#include <Library/DevicePathLib.h>
17+
#include <Library/HandleParsingLib.h>
18+
#include <Library/MauUtilsLib.h>
19+
20+
STATIC
21+
EFI_STATUS
22+
GetVarPath (
23+
IN CHAR16 *Var,
24+
OUT EFI_DEVICE_PATH_PROTOCOL **OutPath,
25+
OUT UINT32 *Attributes
26+
)
27+
{
28+
EFI_STATUS Status;
29+
UINTN VariableSize = 0;
30+
VOID *Variable = NULL;
31+
32+
Status = gRT->GetVariable (
33+
Var,
34+
&gEfiGlobalVariableGuid,
35+
NULL,
36+
&VariableSize,
37+
NULL
38+
);
39+
if (Status == EFI_NOT_FOUND) {
40+
goto out;
41+
}
42+
43+
if (Status != EFI_BUFFER_TOO_SMALL) {
44+
goto out;
45+
}
46+
47+
Variable = AllocatePool (VariableSize);
48+
if (Variable == NULL) {
49+
Status = EFI_OUT_OF_RESOURCES;
50+
goto out;
51+
}
52+
53+
Status = gRT->GetVariable (
54+
Var,
55+
&gEfiGlobalVariableGuid,
56+
Attributes,
57+
&VariableSize,
58+
Variable
59+
);
60+
if (EFI_ERROR (Status)) {
61+
goto out;
62+
}
63+
64+
if (!IsDevicePathValid (Variable, VariableSize)) {
65+
Status = EFI_SUCCESS;
66+
*OutPath = NULL;
67+
goto out;
68+
}
69+
70+
*OutPath = Variable;
71+
return EFI_SUCCESS;
72+
73+
out:
74+
if (VariableSize != 0) {
75+
FreePool (Variable);
76+
}
77+
78+
return Status;
79+
}
80+
81+
STATIC
82+
VOID
83+
PrintVarPath (
84+
IN CHAR16 *Var,
85+
IN EFI_DEVICE_PATH_PROTOCOL *Paths
86+
)
87+
{
88+
UINTN PathSize;
89+
EFI_DEVICE_PATH_PROTOCOL *Path;
90+
91+
Print (L"%s:\n", Var);
92+
93+
while ((Path = GetNextDevicePathInstance (&Paths, &PathSize)) != NULL) {
94+
CHAR16 *PathString = ConvertDevicePathToText (Path, FALSE, FALSE);
95+
if (PathString == NULL) {
96+
Print (L" (corrupted)\n");
97+
} else {
98+
Print (L" %s\n", PathString);
99+
}
100+
101+
FreePool (PathString);
102+
FreePool (Path);
103+
}
104+
}
105+
106+
STATIC
107+
EFI_STATUS
108+
Usage (
109+
IN CHAR16 *Name
110+
)
111+
{
112+
Print (L"Usage: %s [-A] [-i handle-index] [-h handle] [-p path] [-a] VariableName\n", Name);
113+
return EFI_INVALID_PARAMETER;
114+
}
115+
116+
STATIC
117+
EFI_STATUS
118+
AutoPath (
119+
IN CHAR16 *VarName,
120+
OUT EFI_DEVICE_PATH_PROTOCOL **Paths
121+
)
122+
{
123+
UINTN Count;
124+
UINTN Index;
125+
EFI_GUID *Proto;
126+
EFI_STATUS Status;
127+
EFI_HANDLE *Handles;
128+
EFI_DEVICE_PATH_PROTOCOL *Build;
129+
130+
if (!StrnCmp (VarName, L"ConOut", StrLen (L"ConOut")) ||
131+
!StrnCmp (VarName, L"ErrOut", StrLen (L"ErrOut")))
132+
{
133+
Proto = &gEfiSimpleTextOutProtocolGuid;
134+
} else if (!StrnCmp (VarName, L"ConIn", StrLen (L"ConIn"))) {
135+
Proto = &gEfiSimpleTextInProtocolGuid;
136+
} else {
137+
return EFI_INVALID_PARAMETER;
138+
}
139+
140+
Status = gBS->LocateHandleBuffer (
141+
ByProtocol,
142+
Proto,
143+
NULL,
144+
&Count,
145+
&Handles
146+
);
147+
if (Status != EFI_SUCCESS) {
148+
return EFI_NOT_FOUND;
149+
}
150+
151+
Build = NULL;
152+
for (Index = 0; Index < Count; Index++) {
153+
EFI_DEVICE_PATH_PROTOCOL *Path;
154+
EFI_DEVICE_PATH_PROTOCOL *New;
155+
156+
Status = gBS->HandleProtocol (
157+
Handles[Index],
158+
&gEfiDevicePathProtocolGuid,
159+
(VOID **)&Path
160+
);
161+
if (Status != EFI_SUCCESS) {
162+
Status = EFI_SUCCESS;
163+
continue;
164+
}
165+
166+
New = AppendDevicePathInstance (Build, Path);
167+
if (New == NULL) {
168+
Status = EFI_OUT_OF_RESOURCES;
169+
goto out;
170+
}
171+
172+
if (Build != NULL) {
173+
FreePool (Build);
174+
}
175+
176+
Build = New;
177+
}
178+
179+
if (Build == NULL) {
180+
Status = EFI_NOT_FOUND;
181+
}
182+
183+
out:
184+
if (Status != EFI_SUCCESS) {
185+
if (Build != NULL) {
186+
FreePool (Build);
187+
}
188+
} else {
189+
*Paths = Build;
190+
}
191+
192+
FreePool (Handles);
193+
194+
return Status;
195+
}
196+
197+
EFI_STATUS
198+
EFIAPI
199+
EntryPoint (
200+
IN EFI_HANDLE ImageHandle,
201+
IN EFI_SYSTEM_TABLE *SystemTable
202+
)
203+
{
204+
BOOLEAN Set;
205+
BOOLEAN Append;
206+
BOOLEAN Auto;
207+
UINTN Argc;
208+
CHAR16 **Argv;
209+
EFI_STATUS Status;
210+
CHAR16 *VarName;
211+
UINT32 CurrentAttributes;
212+
EFI_DEVICE_PATH_PROTOCOL *Path;
213+
EFI_DEVICE_PATH_PROTOCOL *CurrentPath;
214+
GET_OPT_CONTEXT GetOptContext;
215+
216+
Status = GetShellArgcArgv (ImageHandle, &Argc, &Argv);
217+
if ((Status != EFI_SUCCESS) || (Argc < 1)) {
218+
Print (
219+
L"This program requires Microsoft Windows.\n"
220+
"Just kidding...only the UEFI Shell!\n"
221+
);
222+
return EFI_ABORTED;
223+
}
224+
225+
Set = FALSE;
226+
Append = FALSE;
227+
Auto = FALSE;
228+
Path = NULL;
229+
INIT_GET_OPT_CONTEXT (&GetOptContext);
230+
while ((Status = GetOpt (
231+
Argc,
232+
Argv,
233+
L"ihp",
234+
&GetOptContext
235+
)) == EFI_SUCCESS)
236+
{
237+
switch (GetOptContext.Opt) {
238+
case L'A':
239+
if (Set || Append) {
240+
return Usage (Argv[0]);
241+
}
242+
243+
Auto = TRUE;
244+
Set = TRUE;
245+
break;
246+
case L'a':
247+
248+
if (Auto) {
249+
return Usage (Argv[0]);
250+
}
251+
252+
Append = TRUE;
253+
break;
254+
case L'p':
255+
{
256+
if ((GetOptContext.OptArg == NULL) || Set || Auto) {
257+
return Usage (Argv[0]);
258+
}
259+
260+
Path = ConvertTextToDevicePath (GetOptContext.OptArg);
261+
if (Path == NULL) {
262+
Print (L"'%s' is not a valid device path\n");
263+
Status = EFI_INVALID_PARAMETER;
264+
}
265+
266+
Set = TRUE;
267+
break;
268+
}
269+
case L'h':
270+
{
271+
EFI_HANDLE Handle;
272+
273+
if ((GetOptContext.OptArg == NULL) || Set || Auto) {
274+
return Usage (Argv[0]);
275+
}
276+
277+
Handle = (VOID *)StrHexToUintn (GetOptContext.OptArg);
278+
279+
Path = DuplicateDevicePath (DevicePathFromHandle (Handle));
280+
if (Path == NULL) {
281+
Print (
282+
L"Could not get path for EFI_HANDLE %p\n",
283+
Handle
284+
);
285+
return EFI_INVALID_PARAMETER;
286+
}
287+
288+
Set = TRUE;
289+
break;
290+
}
291+
case L'i':
292+
{
293+
UINTN HandleIndex;
294+
EFI_HANDLE Handle;
295+
296+
if ((GetOptContext.OptArg == NULL) || Set || Auto) {
297+
return Usage (Argv[0]);
298+
}
299+
300+
HandleIndex = StrHexToUintn (GetOptContext.OptArg);
301+
Handle = ConvertHandleIndexToHandle (HandleIndex);
302+
if (Handle == NULL) {
303+
Print (L"Invalid EFI_HANDLE index %x\n", HandleIndex);
304+
return EFI_INVALID_PARAMETER;
305+
}
306+
307+
Path = DuplicateDevicePath (DevicePathFromHandle (Handle));
308+
if (Path == NULL) {
309+
Print (
310+
L"Could not get path for EFI_HANDLE index %x\n",
311+
HandleIndex
312+
);
313+
return EFI_INVALID_PARAMETER;
314+
}
315+
316+
Set = TRUE;
317+
break;
318+
}
319+
default:
320+
Print (L"Unknown option '%c'\n", GetOptContext.Opt);
321+
return Usage (Argv[0]);
322+
}
323+
}
324+
325+
if (Argc - GetOptContext.OptIndex < 1) {
326+
return Usage (Argv[0]);
327+
}
328+
329+
CurrentPath = NULL;
330+
VarName = Argv[GetOptContext.OptIndex + 0];
331+
Status = GetVarPath (VarName, &CurrentPath, &CurrentAttributes);
332+
if (Status != EFI_SUCCESS) {
333+
Print (L"Error reading variable '%s': %r\n", VarName, Status);
334+
goto out;
335+
}
336+
337+
if (!Set) {
338+
if (CurrentPath != NULL) {
339+
PrintVarPath (VarName, CurrentPath);
340+
}
341+
342+
goto out;
343+
}
344+
345+
if (Auto) {
346+
Status = AutoPath (VarName, &Path);
347+
if (Status != EFI_SUCCESS) {
348+
Print (
349+
L"Could not auto-build path for '%s': %r\n",
350+
VarName,
351+
Status
352+
);
353+
goto out;
354+
}
355+
} else if (Append) {
356+
EFI_DEVICE_PATH_PROTOCOL *NewPath;
357+
358+
NewPath = AppendDevicePathInstance (CurrentPath, Path);
359+
if (NewPath == NULL) {
360+
Print (L"Error appending path: %r\n");
361+
Status = EFI_OUT_OF_RESOURCES;
362+
goto out;
363+
}
364+
365+
FreePool (Path);
366+
Path = NewPath;
367+
}
368+
369+
Status = gRT->SetVariable (
370+
VarName,
371+
&gEfiGlobalVariableGuid,
372+
CurrentAttributes,
373+
GetDevicePathSize (Path),
374+
Path
375+
);
376+
377+
out:
378+
379+
if (CurrentPath != NULL) {
380+
FreePool (CurrentPath);
381+
}
382+
383+
if (Path != NULL) {
384+
FreePool (Path);
385+
}
386+
387+
return Status;
388+
}

0 commit comments

Comments
 (0)