Skip to content

Commit 290b6bb

Browse files
committed
It actually works now!
1 parent 06e0b26 commit 290b6bb

File tree

2 files changed

+73
-31
lines changed

2 files changed

+73
-31
lines changed

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ EFI_CRT_OBJS = $(EFILIB)/crt0-efi-$(ARCH).o
1111
EFI_LDS = $(EFILIB)/elf_$(ARCH)_efi.lds
1212

1313
CFLAGS = $(EFIINCS) -fno-stack-protector -fpic \
14-
-fshort-wchar -mno-red-zone -Wall
14+
-fshort-wchar -mno-red-zone -Wextra -DVERSION="L\"$(shell git describe --always)\""
1515
ifeq ($(ARCH),x86_64)
16-
CFLAGS += -DEFIX64 -DEFI_FUNCTION_WRAPPER -m64
16+
CFLAGS += -DEFI_FUNCTION_WRAPPER -m64
1717
endif
1818

1919
LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared \
@@ -22,7 +22,7 @@ LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared \
2222
all: $(TARGET)
2323

2424
clean:
25-
rm -f $(OBJS)
25+
rm -f $(OBJS) $(TARGET) gpu-switch.so
2626

2727
gpu-switch.so: $(OBJS)
2828
ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi

main.c

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,16 @@
2020
#include <efi.h>
2121
#include <efilib.h>
2222

23-
#define GPU_EXTERNAL 0
23+
#ifndef VERSION
24+
#define VERSION L"(unknown)"
25+
#endif
26+
27+
#define GPU_DEDICATED 0
2428
#define GPU_INTERNAL 1
29+
#define GPU_NAME(n) ((n) ? "internal" : "dedicated")
30+
31+
#define VAR_ACCESS_BS_RT (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)
32+
#define VAR_ATTR_MASK (VAR_ACCESS_BS_RT | EFI_VARIABLE_NON_VOLATILE)
2533

2634
#define G2P_NAME L"gpu-power-prefs"
2735
#define GP_NAME L"gpu-policy"
@@ -36,16 +44,20 @@ static EFI_GUID g2pGuid =
3644
static EFI_GUID gpGuid =
3745
{ 0x7c436110, 0xab2a, 0x4bbb, { 0xa8, 0x80, 0xfe, 0x41, 0x99, 0x5c, 0x9f, 0x82 }};
3846

39-
static BOOLEAN verbose = TRUE;
47+
static UINT32 verbosity = 0;
4048

4149
static BOOLEAN GetEfiVar(EFI_GUID *guid, CHAR16 *name, CHAR8 *buf, UINTN *len, UINT32 *attrs)
4250
{
4351
EFI_STATUS status;
4452

45-
status = uefi_call_wrapper(RT->GetVariable, 5, name, guid, attrs, len, *buf);
53+
if (verbosity > 2) {
54+
Print(L"%a(%g, %s, ..., %ld, %02x)\n", __func__, guid, name, *len, attrs ? *attrs : 0);
55+
}
56+
57+
status = uefi_call_wrapper(RT->GetVariable, 5, name, guid, attrs, len, buf);
4658
if (!EFI_ERROR(status)) {
47-
return len > 0;
48-
} else if (verbose && status != EFI_NOT_FOUND) {
59+
return *len > 0;
60+
} else if (verbosity && status != EFI_NOT_FOUND) {
4961
Print(L"%a: %s: %r\n", __func__, name, status);
5062
}
5163

@@ -55,15 +67,20 @@ static BOOLEAN GetEfiVar(EFI_GUID *guid, CHAR16 *name, CHAR8 *buf, UINTN *len, U
5567
static BOOLEAN SetEfiVar(EFI_GUID *guid, CHAR16 *name, CHAR8 *buf, UINTN len, UINT32 attrs)
5668
{
5769
EFI_STATUS status;
58-
UINT32 access = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
5970

60-
if (!(attrs & ~access)) {
61-
attrs |= access;
71+
if (verbosity > 2) {
72+
Print(L"%a(%g, %s, ..., %ld, %02x)\n", __func__, guid, name, len, attrs);
73+
}
74+
75+
attrs &= VAR_ATTR_MASK;
76+
77+
if (!(attrs & ~VAR_ACCESS_BS_RT)) {
78+
attrs |= VAR_ACCESS_BS_RT;
6279
}
6380

6481
status = uefi_call_wrapper(RT->SetVariable, 5, name, guid, attrs, len, buf);
6582
if (EFI_ERROR(status)) {
66-
if (verbose) {
83+
if (verbosity) {
6784
Print(L"%a: %s: %r\n", __func__, name, status);
6885
}
6986
return FALSE;
@@ -72,13 +89,17 @@ static BOOLEAN SetEfiVar(EFI_GUID *guid, CHAR16 *name, CHAR8 *buf, UINTN len, UI
7289
return TRUE;
7390
}
7491

75-
typedef BOOLEAN (*EditEfiVarCallback)(CHAR8 *buf, UINTN len, VOID *arg);
92+
typedef BOOLEAN (*EditEfiVarCallback)(CHAR16 *name, CHAR8 *buf, UINTN len, VOID *arg);
7693
static BOOLEAN EditEfiVar(EFI_GUID *guid, CHAR16 *name, EditEfiVarCallback cb, VOID *arg)
7794
{
7895
CHAR8 buf[1024];
7996
UINTN len;
8097
UINT32 attrs;
8198

99+
if (verbosity > 2) {
100+
Print(L"%a(%g, %s, ..., ...)\n", __func__, guid, name);
101+
}
102+
82103
if (!cb) {
83104
return FALSE;
84105
}
@@ -90,43 +111,58 @@ static BOOLEAN EditEfiVar(EFI_GUID *guid, CHAR16 *name, EditEfiVarCallback cb, V
90111
return FALSE;
91112
}
92113

93-
if (!cb(buf, len, arg)) {
114+
if (!cb(name, buf, len, arg)) {
94115
return FALSE;
95116
}
96117

97118
return SetEfiVar(guid, name, buf, len, attrs);
98119
}
99120

100-
static BOOLEAN EditGpuPowerPrefsAndPolicy(CHAR8 *buf, UINTN len, VOID *arg)
121+
static BOOLEAN EditGpuPowerPrefsAndPolicy(CHAR16 *name, CHAR8 *buf, UINTN len, VOID *arg)
101122
{
123+
if ((!StrCmp(name, L"gpu-power-prefs") && len != 4)
124+
|| (!StrCmp(name, L"gpu-policy") && len != 1))
125+
{
126+
if (verbosity) {
127+
Print(L"%a: unexpected length %ld for %s\n", __func__, len, name);
128+
}
129+
130+
return FALSE;
131+
}
132+
133+
if (verbosity > 2) {
134+
Print(L"%a(%s, ..., %ld, %a)\n", __func__, name, len, *(BOOLEAN*)arg ? "TRUE" : "FALSE");
135+
}
136+
102137
buf[0] = (*(BOOLEAN*)arg) ? 1 : 0;
103138
return TRUE;
104139
}
105140

106141
static BOOLEAN SetNextBootGpu(BOOLEAN internal)
107142
{
108-
BOOLEAN err = FALSE;
143+
BOOLEAN ret = FALSE;
109144

110-
err |= !EditEfiVar(&g2pGuid, G2P_NAME, &EditGpuPowerPrefsAndPolicy, &internal);
111-
err |= !EditEfiVar(&gpGuid, GP_NAME, &EditGpuPowerPrefsAndPolicy, &internal);
112-
err |= !EditEfiVar(&appleNvGuid, GSCRS_NAME, &EditGpuPowerPrefsAndPolicy, &internal);
145+
ret |= EditEfiVar(&g2pGuid, G2P_NAME, &EditGpuPowerPrefsAndPolicy, &internal);
146+
ret |= EditEfiVar(&gpGuid, GP_NAME, &EditGpuPowerPrefsAndPolicy, &internal);
113147

114-
return !err;
148+
return ret;
115149
}
116150

117151
static BOOLEAN DumpEfiVar(EFI_GUID *guid, CHAR16 *name)
118152
{
119153
CHAR8 buf[1024];
120154
UINTN i, len = sizeof(buf);
121155

156+
ZeroMem(buf, len);
157+
122158
if (!GetEfiVar(guid, name, buf, &len, NULL)) {
123159
return FALSE;
124160
}
125161

126162
Print(L"%s: ", name, &guid);
127163

128164
for (i = 0; i < len; ++i) {
129-
Print(L" %02x", buf[i]);
165+
Print(L" %02x", buf[i] & 0xff);
130166
}
131167

132168
Print(L"\n");
@@ -139,12 +175,12 @@ static BOOLEAN DumpEfiVars(VOID)
139175
{
140176
BOOLEAN ret = FALSE;
141177

178+
ret |= DumpEfiVar(&appleNvGuid, GSCRS_NAME);
142179
ret |= DumpEfiVar(&g2pGuid, G2P_NAME);
143180
ret |= DumpEfiVar(&gpGuid, GP_NAME);
144-
ret |= DumpEfiVar(&appleNvGuid, GSCRS_NAME);
145181

146182
if (!ret) {
147-
Print(L"No relevant EFI variables found.\n");
183+
Print(L"Nothing to dump.\n");
148184
}
149185

150186
return ret;
@@ -162,14 +198,14 @@ static EFI_STATUS PrintUsageAndExit(EFI_HANDLE imageHandle, BOOLEAN error)
162198
L"\n"
163199
L"Options:\n"
164200
L" -v Verbose operation\n"
165-
L" -p Dump relevant efi variables\n"
201+
L" -p Dump important EFI variables\n"
166202
L" -i Force integrated GPU on next boot\n"
167203
L" -d Force dedicated GPU on next boot\n"
168204
L"\n"
205+
L"gpu-switch.efi " VERSION "\n"
169206
L"Copyright (C) 2017 Joseph C. Lehner\n"
170207
L"Licensed under the GNU GPLv3; source:\n"
171-
L"https://github.com/jclehner/gpu-switch-efi\n"
172-
L"\n");
208+
L"https://github.com/jclehner/gpu-switch-efi\n");
173209

174210
return Exit(imageHandle, error ? EFI_INVALID_PARAMETER : EFI_SUCCESS);
175211
}
@@ -187,24 +223,30 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable
187223

188224
for (i = 0; i < argc; ++i) {
189225
if (!StrCmp(argv[i], L"-v")) {
190-
verbose = TRUE;
226+
++verbosity;
191227
} else if (!StrCmp(argv[i], L"-h")) {
192228
return PrintUsageAndExit(imageHandle, FALSE);
193229
} else if (!StrCmp(argv[i], L"-i")) {
194230
gpu = GPU_INTERNAL;
195231
} else if (!StrCmp(argv[i], L"-d")) {
196-
gpu = GPU_EXTERNAL;
232+
gpu = GPU_DEDICATED;
197233
} else if (!StrCmp(argv[i], L"-p")) {
198234
dump = TRUE;
199235
}
200236
}
201237

202-
if (!dump && (gpu == ~0)) {
238+
if (!dump && (gpu == ~0U)) {
203239
return PrintUsageAndExit(imageHandle, TRUE);
204240
} else if (dump) {
205-
status = DumpEfiVars();
241+
status = DumpEfiVars() ? EFI_SUCCESS : EFI_NOT_FOUND;
206242
} else {
207-
status = SetNextBootGpu(gpu);
243+
if (SetNextBootGpu(gpu)) {
244+
Print(L"Successfully switched to %a GPU\n", GPU_NAME(gpu));
245+
status = EFI_SUCCESS;
246+
} else {
247+
Print(L"Failed to switch to %a GPU\n", GPU_NAME(gpu));
248+
status = EFI_NOT_FOUND;
249+
}
208250
}
209251

210252
return Exit(imageHandle, status);

0 commit comments

Comments
 (0)