20
20
#include <efi.h>
21
21
#include <efilib.h>
22
22
23
- #define GPU_EXTERNAL 0
23
+ #ifndef VERSION
24
+ #define VERSION L"(unknown)"
25
+ #endif
26
+
27
+ #define GPU_DEDICATED 0
24
28
#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)
25
33
26
34
#define G2P_NAME L"gpu-power-prefs"
27
35
#define GP_NAME L"gpu-policy"
@@ -36,16 +44,20 @@ static EFI_GUID g2pGuid =
36
44
static EFI_GUID gpGuid =
37
45
{ 0x7c436110 , 0xab2a , 0x4bbb , { 0xa8 , 0x80 , 0xfe , 0x41 , 0x99 , 0x5c , 0x9f , 0x82 }};
38
46
39
- static BOOLEAN verbose = TRUE ;
47
+ static UINT32 verbosity = 0 ;
40
48
41
49
static BOOLEAN GetEfiVar (EFI_GUID * guid , CHAR16 * name , CHAR8 * buf , UINTN * len , UINT32 * attrs )
42
50
{
43
51
EFI_STATUS status ;
44
52
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 );
46
58
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 ) {
49
61
Print (L"%a: %s: %r\n" , __func__ , name , status );
50
62
}
51
63
@@ -55,15 +67,20 @@ static BOOLEAN GetEfiVar(EFI_GUID *guid, CHAR16 *name, CHAR8 *buf, UINTN *len, U
55
67
static BOOLEAN SetEfiVar (EFI_GUID * guid , CHAR16 * name , CHAR8 * buf , UINTN len , UINT32 attrs )
56
68
{
57
69
EFI_STATUS status ;
58
- UINT32 access = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS ;
59
70
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 ;
62
79
}
63
80
64
81
status = uefi_call_wrapper (RT -> SetVariable , 5 , name , guid , attrs , len , buf );
65
82
if (EFI_ERROR (status )) {
66
- if (verbose ) {
83
+ if (verbosity ) {
67
84
Print (L"%a: %s: %r\n" , __func__ , name , status );
68
85
}
69
86
return FALSE;
@@ -72,13 +89,17 @@ static BOOLEAN SetEfiVar(EFI_GUID *guid, CHAR16 *name, CHAR8 *buf, UINTN len, UI
72
89
return TRUE;
73
90
}
74
91
75
- typedef BOOLEAN (* EditEfiVarCallback )(CHAR8 * buf , UINTN len , VOID * arg );
92
+ typedef BOOLEAN (* EditEfiVarCallback )(CHAR16 * name , CHAR8 * buf , UINTN len , VOID * arg );
76
93
static BOOLEAN EditEfiVar (EFI_GUID * guid , CHAR16 * name , EditEfiVarCallback cb , VOID * arg )
77
94
{
78
95
CHAR8 buf [1024 ];
79
96
UINTN len ;
80
97
UINT32 attrs ;
81
98
99
+ if (verbosity > 2 ) {
100
+ Print (L"%a(%g, %s, ..., ...)\n" , __func__ , guid , name );
101
+ }
102
+
82
103
if (!cb ) {
83
104
return FALSE;
84
105
}
@@ -90,43 +111,58 @@ static BOOLEAN EditEfiVar(EFI_GUID *guid, CHAR16 *name, EditEfiVarCallback cb, V
90
111
return FALSE;
91
112
}
92
113
93
- if (!cb (buf , len , arg )) {
114
+ if (!cb (name , buf , len , arg )) {
94
115
return FALSE;
95
116
}
96
117
97
118
return SetEfiVar (guid , name , buf , len , attrs );
98
119
}
99
120
100
- static BOOLEAN EditGpuPowerPrefsAndPolicy (CHAR8 * buf , UINTN len , VOID * arg )
121
+ static BOOLEAN EditGpuPowerPrefsAndPolicy (CHAR16 * name , CHAR8 * buf , UINTN len , VOID * arg )
101
122
{
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
+
102
137
buf [0 ] = (* (BOOLEAN * )arg ) ? 1 : 0 ;
103
138
return TRUE;
104
139
}
105
140
106
141
static BOOLEAN SetNextBootGpu (BOOLEAN internal )
107
142
{
108
- BOOLEAN err = FALSE;
143
+ BOOLEAN ret = FALSE;
109
144
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 );
113
147
114
- return ! err ;
148
+ return ret ;
115
149
}
116
150
117
151
static BOOLEAN DumpEfiVar (EFI_GUID * guid , CHAR16 * name )
118
152
{
119
153
CHAR8 buf [1024 ];
120
154
UINTN i , len = sizeof (buf );
121
155
156
+ ZeroMem (buf , len );
157
+
122
158
if (!GetEfiVar (guid , name , buf , & len , NULL )) {
123
159
return FALSE;
124
160
}
125
161
126
162
Print (L"%s: " , name , & guid );
127
163
128
164
for (i = 0 ; i < len ; ++ i ) {
129
- Print (L" %02x" , buf [i ]);
165
+ Print (L" %02x" , buf [i ] & 0xff );
130
166
}
131
167
132
168
Print (L"\n" );
@@ -139,12 +175,12 @@ static BOOLEAN DumpEfiVars(VOID)
139
175
{
140
176
BOOLEAN ret = FALSE;
141
177
178
+ ret |= DumpEfiVar (& appleNvGuid , GSCRS_NAME );
142
179
ret |= DumpEfiVar (& g2pGuid , G2P_NAME );
143
180
ret |= DumpEfiVar (& gpGuid , GP_NAME );
144
- ret |= DumpEfiVar (& appleNvGuid , GSCRS_NAME );
145
181
146
182
if (!ret ) {
147
- Print (L"No relevant EFI variables found .\n" );
183
+ Print (L"Nothing to dump .\n" );
148
184
}
149
185
150
186
return ret ;
@@ -162,14 +198,14 @@ static EFI_STATUS PrintUsageAndExit(EFI_HANDLE imageHandle, BOOLEAN error)
162
198
L"\n"
163
199
L"Options:\n"
164
200
L" -v Verbose operation\n"
165
- L" -p Dump relevant efi variables\n"
201
+ L" -p Dump important EFI variables\n"
166
202
L" -i Force integrated GPU on next boot\n"
167
203
L" -d Force dedicated GPU on next boot\n"
168
204
L"\n"
205
+ L"gpu-switch.efi " VERSION "\n"
169
206
L"Copyright (C) 2017 Joseph C. Lehner\n"
170
207
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" );
173
209
174
210
return Exit (imageHandle , error ? EFI_INVALID_PARAMETER : EFI_SUCCESS );
175
211
}
@@ -187,24 +223,30 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable
187
223
188
224
for (i = 0 ; i < argc ; ++ i ) {
189
225
if (!StrCmp (argv [i ], L"-v" )) {
190
- verbose = TRUE ;
226
+ ++ verbosity ;
191
227
} else if (!StrCmp (argv [i ], L"-h" )) {
192
228
return PrintUsageAndExit (imageHandle , FALSE);
193
229
} else if (!StrCmp (argv [i ], L"-i" )) {
194
230
gpu = GPU_INTERNAL ;
195
231
} else if (!StrCmp (argv [i ], L"-d" )) {
196
- gpu = GPU_EXTERNAL ;
232
+ gpu = GPU_DEDICATED ;
197
233
} else if (!StrCmp (argv [i ], L"-p" )) {
198
234
dump = TRUE;
199
235
}
200
236
}
201
237
202
- if (!dump && (gpu == ~0 )) {
238
+ if (!dump && (gpu == ~0U )) {
203
239
return PrintUsageAndExit (imageHandle , TRUE);
204
240
} else if (dump ) {
205
- status = DumpEfiVars ();
241
+ status = DumpEfiVars () ? EFI_SUCCESS : EFI_NOT_FOUND ;
206
242
} 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
+ }
208
250
}
209
251
210
252
return Exit (imageHandle , status );
0 commit comments