1*034cb968SGerd Hoffmann /*
2*034cb968SGerd Hoffmann * SPDX-License-Identifier: GPL-2.0-or-later
3*034cb968SGerd Hoffmann *
4*034cb968SGerd Hoffmann * uefi vars device - VarCheckPolicyLibMmiHandler implementation
5*034cb968SGerd Hoffmann *
6*034cb968SGerd Hoffmann * variable policy specs:
7*034cb968SGerd Hoffmann * https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Library/VariablePolicyLib/ReadMe.md
8*034cb968SGerd Hoffmann */
9*034cb968SGerd Hoffmann #include "qemu/osdep.h"
10*034cb968SGerd Hoffmann #include "system/dma.h"
11*034cb968SGerd Hoffmann #include "migration/vmstate.h"
12*034cb968SGerd Hoffmann
13*034cb968SGerd Hoffmann #include "hw/uefi/var-service.h"
14*034cb968SGerd Hoffmann #include "hw/uefi/var-service-api.h"
15*034cb968SGerd Hoffmann #include "hw/uefi/var-service-edk2.h"
16*034cb968SGerd Hoffmann
17*034cb968SGerd Hoffmann #include "trace/trace-hw_uefi.h"
18*034cb968SGerd Hoffmann
19*034cb968SGerd Hoffmann static void calc_policy(uefi_var_policy *pol);
20*034cb968SGerd Hoffmann
uefi_var_policy_post_load(void * opaque,int version_id)21*034cb968SGerd Hoffmann static int uefi_var_policy_post_load(void *opaque, int version_id)
22*034cb968SGerd Hoffmann {
23*034cb968SGerd Hoffmann uefi_var_policy *pol = opaque;
24*034cb968SGerd Hoffmann
25*034cb968SGerd Hoffmann calc_policy(pol);
26*034cb968SGerd Hoffmann return 0;
27*034cb968SGerd Hoffmann }
28*034cb968SGerd Hoffmann
29*034cb968SGerd Hoffmann const VMStateDescription vmstate_uefi_var_policy = {
30*034cb968SGerd Hoffmann .name = "uefi-var-policy",
31*034cb968SGerd Hoffmann .post_load = uefi_var_policy_post_load,
32*034cb968SGerd Hoffmann .fields = (VMStateField[]) {
33*034cb968SGerd Hoffmann VMSTATE_UINT32(entry_size, uefi_var_policy),
34*034cb968SGerd Hoffmann VMSTATE_VBUFFER_ALLOC_UINT32(entry, uefi_var_policy,
35*034cb968SGerd Hoffmann 0, NULL, entry_size),
36*034cb968SGerd Hoffmann VMSTATE_END_OF_LIST()
37*034cb968SGerd Hoffmann },
38*034cb968SGerd Hoffmann };
39*034cb968SGerd Hoffmann
print_policy_entry(variable_policy_entry * pe)40*034cb968SGerd Hoffmann static void print_policy_entry(variable_policy_entry *pe)
41*034cb968SGerd Hoffmann {
42*034cb968SGerd Hoffmann uint16_t *name = (void *)pe + pe->offset_to_name;
43*034cb968SGerd Hoffmann
44*034cb968SGerd Hoffmann fprintf(stderr, "%s:\n", __func__);
45*034cb968SGerd Hoffmann
46*034cb968SGerd Hoffmann fprintf(stderr, " name ´");
47*034cb968SGerd Hoffmann while (*name) {
48*034cb968SGerd Hoffmann fprintf(stderr, "%c", *name);
49*034cb968SGerd Hoffmann name++;
50*034cb968SGerd Hoffmann }
51*034cb968SGerd Hoffmann fprintf(stderr, "', version=%d.%d, size=%d\n",
52*034cb968SGerd Hoffmann pe->version >> 16, pe->version & 0xffff, pe->size);
53*034cb968SGerd Hoffmann
54*034cb968SGerd Hoffmann if (pe->min_size) {
55*034cb968SGerd Hoffmann fprintf(stderr, " size min=%d\n", pe->min_size);
56*034cb968SGerd Hoffmann }
57*034cb968SGerd Hoffmann if (pe->max_size != UINT32_MAX) {
58*034cb968SGerd Hoffmann fprintf(stderr, " size max=%u\n", pe->max_size);
59*034cb968SGerd Hoffmann }
60*034cb968SGerd Hoffmann if (pe->attributes_must_have) {
61*034cb968SGerd Hoffmann fprintf(stderr, " attr must=0x%x\n", pe->attributes_must_have);
62*034cb968SGerd Hoffmann }
63*034cb968SGerd Hoffmann if (pe->attributes_cant_have) {
64*034cb968SGerd Hoffmann fprintf(stderr, " attr cant=0x%x\n", pe->attributes_cant_have);
65*034cb968SGerd Hoffmann }
66*034cb968SGerd Hoffmann if (pe->lock_policy_type) {
67*034cb968SGerd Hoffmann fprintf(stderr, " lock policy type %d\n", pe->lock_policy_type);
68*034cb968SGerd Hoffmann }
69*034cb968SGerd Hoffmann }
70*034cb968SGerd Hoffmann
wildcard_str_equal(uefi_var_policy * pol,uefi_variable * var)71*034cb968SGerd Hoffmann static gboolean wildcard_str_equal(uefi_var_policy *pol,
72*034cb968SGerd Hoffmann uefi_variable *var)
73*034cb968SGerd Hoffmann {
74*034cb968SGerd Hoffmann return uefi_str_equal_ex(pol->name, pol->name_size,
75*034cb968SGerd Hoffmann var->name, var->name_size,
76*034cb968SGerd Hoffmann true);
77*034cb968SGerd Hoffmann }
78*034cb968SGerd Hoffmann
find_policy(uefi_vars_state * uv,QemuUUID guid,uint16_t * name,uint64_t name_size)79*034cb968SGerd Hoffmann static uefi_var_policy *find_policy(uefi_vars_state *uv, QemuUUID guid,
80*034cb968SGerd Hoffmann uint16_t *name, uint64_t name_size)
81*034cb968SGerd Hoffmann {
82*034cb968SGerd Hoffmann uefi_var_policy *pol;
83*034cb968SGerd Hoffmann
84*034cb968SGerd Hoffmann QTAILQ_FOREACH(pol, &uv->var_policies, next) {
85*034cb968SGerd Hoffmann if (!qemu_uuid_is_equal(&pol->entry->namespace, &guid)) {
86*034cb968SGerd Hoffmann continue;
87*034cb968SGerd Hoffmann }
88*034cb968SGerd Hoffmann if (!uefi_str_equal(pol->name, pol->name_size,
89*034cb968SGerd Hoffmann name, name_size)) {
90*034cb968SGerd Hoffmann continue;
91*034cb968SGerd Hoffmann }
92*034cb968SGerd Hoffmann return pol;
93*034cb968SGerd Hoffmann }
94*034cb968SGerd Hoffmann return NULL;
95*034cb968SGerd Hoffmann }
96*034cb968SGerd Hoffmann
wildcard_find_policy(uefi_vars_state * uv,uefi_variable * var)97*034cb968SGerd Hoffmann static uefi_var_policy *wildcard_find_policy(uefi_vars_state *uv,
98*034cb968SGerd Hoffmann uefi_variable *var)
99*034cb968SGerd Hoffmann {
100*034cb968SGerd Hoffmann uefi_var_policy *pol;
101*034cb968SGerd Hoffmann
102*034cb968SGerd Hoffmann QTAILQ_FOREACH(pol, &uv->var_policies, next) {
103*034cb968SGerd Hoffmann if (!qemu_uuid_is_equal(&pol->entry->namespace, &var->guid)) {
104*034cb968SGerd Hoffmann continue;
105*034cb968SGerd Hoffmann }
106*034cb968SGerd Hoffmann if (!wildcard_str_equal(pol, var)) {
107*034cb968SGerd Hoffmann continue;
108*034cb968SGerd Hoffmann }
109*034cb968SGerd Hoffmann return pol;
110*034cb968SGerd Hoffmann }
111*034cb968SGerd Hoffmann return NULL;
112*034cb968SGerd Hoffmann }
113*034cb968SGerd Hoffmann
calc_policy(uefi_var_policy * pol)114*034cb968SGerd Hoffmann static void calc_policy(uefi_var_policy *pol)
115*034cb968SGerd Hoffmann {
116*034cb968SGerd Hoffmann variable_policy_entry *pe = pol->entry;
117*034cb968SGerd Hoffmann unsigned int i;
118*034cb968SGerd Hoffmann
119*034cb968SGerd Hoffmann pol->name = (void *)pol->entry + pe->offset_to_name;
120*034cb968SGerd Hoffmann pol->name_size = pe->size - pe->offset_to_name;
121*034cb968SGerd Hoffmann
122*034cb968SGerd Hoffmann for (i = 0; i < pol->name_size / 2; i++) {
123*034cb968SGerd Hoffmann if (pol->name[i] == '#') {
124*034cb968SGerd Hoffmann pol->hashmarks++;
125*034cb968SGerd Hoffmann }
126*034cb968SGerd Hoffmann }
127*034cb968SGerd Hoffmann }
128*034cb968SGerd Hoffmann
uefi_vars_add_policy(uefi_vars_state * uv,variable_policy_entry * pe)129*034cb968SGerd Hoffmann uefi_var_policy *uefi_vars_add_policy(uefi_vars_state *uv,
130*034cb968SGerd Hoffmann variable_policy_entry *pe)
131*034cb968SGerd Hoffmann {
132*034cb968SGerd Hoffmann uefi_var_policy *pol, *p;
133*034cb968SGerd Hoffmann
134*034cb968SGerd Hoffmann pol = g_new0(uefi_var_policy, 1);
135*034cb968SGerd Hoffmann pol->entry = g_malloc(pe->size);
136*034cb968SGerd Hoffmann memcpy(pol->entry, pe, pe->size);
137*034cb968SGerd Hoffmann pol->entry_size = pe->size;
138*034cb968SGerd Hoffmann
139*034cb968SGerd Hoffmann calc_policy(pol);
140*034cb968SGerd Hoffmann
141*034cb968SGerd Hoffmann /* keep list sorted by priority, add to tail of priority group */
142*034cb968SGerd Hoffmann QTAILQ_FOREACH(p, &uv->var_policies, next) {
143*034cb968SGerd Hoffmann if ((p->hashmarks > pol->hashmarks) ||
144*034cb968SGerd Hoffmann (!p->name_size && pol->name_size)) {
145*034cb968SGerd Hoffmann QTAILQ_INSERT_BEFORE(p, pol, next);
146*034cb968SGerd Hoffmann return pol;
147*034cb968SGerd Hoffmann }
148*034cb968SGerd Hoffmann }
149*034cb968SGerd Hoffmann
150*034cb968SGerd Hoffmann QTAILQ_INSERT_TAIL(&uv->var_policies, pol, next);
151*034cb968SGerd Hoffmann return pol;
152*034cb968SGerd Hoffmann }
153*034cb968SGerd Hoffmann
uefi_vars_policy_check(uefi_vars_state * uv,uefi_variable * var,gboolean is_newvar)154*034cb968SGerd Hoffmann efi_status uefi_vars_policy_check(uefi_vars_state *uv,
155*034cb968SGerd Hoffmann uefi_variable *var,
156*034cb968SGerd Hoffmann gboolean is_newvar)
157*034cb968SGerd Hoffmann {
158*034cb968SGerd Hoffmann uefi_var_policy *pol;
159*034cb968SGerd Hoffmann variable_policy_entry *pe;
160*034cb968SGerd Hoffmann variable_lock_on_var_state *lvarstate;
161*034cb968SGerd Hoffmann uint16_t *lvarname;
162*034cb968SGerd Hoffmann size_t lvarnamesize;
163*034cb968SGerd Hoffmann uefi_variable *lvar;
164*034cb968SGerd Hoffmann
165*034cb968SGerd Hoffmann if (!uv->end_of_dxe) {
166*034cb968SGerd Hoffmann return EFI_SUCCESS;
167*034cb968SGerd Hoffmann }
168*034cb968SGerd Hoffmann
169*034cb968SGerd Hoffmann pol = wildcard_find_policy(uv, var);
170*034cb968SGerd Hoffmann if (!pol) {
171*034cb968SGerd Hoffmann return EFI_SUCCESS;
172*034cb968SGerd Hoffmann }
173*034cb968SGerd Hoffmann pe = pol->entry;
174*034cb968SGerd Hoffmann
175*034cb968SGerd Hoffmann uefi_trace_variable(__func__, var->guid, var->name, var->name_size);
176*034cb968SGerd Hoffmann print_policy_entry(pe);
177*034cb968SGerd Hoffmann
178*034cb968SGerd Hoffmann if ((var->attributes & pe->attributes_must_have) != pe->attributes_must_have) {
179*034cb968SGerd Hoffmann trace_uefi_vars_policy_deny("must-have-attr");
180*034cb968SGerd Hoffmann return EFI_INVALID_PARAMETER;
181*034cb968SGerd Hoffmann }
182*034cb968SGerd Hoffmann if ((var->attributes & pe->attributes_cant_have) != 0) {
183*034cb968SGerd Hoffmann trace_uefi_vars_policy_deny("cant-have-attr");
184*034cb968SGerd Hoffmann return EFI_INVALID_PARAMETER;
185*034cb968SGerd Hoffmann }
186*034cb968SGerd Hoffmann
187*034cb968SGerd Hoffmann if (var->data_size < pe->min_size) {
188*034cb968SGerd Hoffmann trace_uefi_vars_policy_deny("min-size");
189*034cb968SGerd Hoffmann return EFI_INVALID_PARAMETER;
190*034cb968SGerd Hoffmann }
191*034cb968SGerd Hoffmann if (var->data_size > pe->max_size) {
192*034cb968SGerd Hoffmann trace_uefi_vars_policy_deny("max-size");
193*034cb968SGerd Hoffmann return EFI_INVALID_PARAMETER;
194*034cb968SGerd Hoffmann }
195*034cb968SGerd Hoffmann
196*034cb968SGerd Hoffmann switch (pe->lock_policy_type) {
197*034cb968SGerd Hoffmann case VARIABLE_POLICY_TYPE_NO_LOCK:
198*034cb968SGerd Hoffmann break;
199*034cb968SGerd Hoffmann
200*034cb968SGerd Hoffmann case VARIABLE_POLICY_TYPE_LOCK_NOW:
201*034cb968SGerd Hoffmann trace_uefi_vars_policy_deny("lock-now");
202*034cb968SGerd Hoffmann return EFI_WRITE_PROTECTED;
203*034cb968SGerd Hoffmann
204*034cb968SGerd Hoffmann case VARIABLE_POLICY_TYPE_LOCK_ON_CREATE:
205*034cb968SGerd Hoffmann if (!is_newvar) {
206*034cb968SGerd Hoffmann trace_uefi_vars_policy_deny("lock-on-create");
207*034cb968SGerd Hoffmann return EFI_WRITE_PROTECTED;
208*034cb968SGerd Hoffmann }
209*034cb968SGerd Hoffmann break;
210*034cb968SGerd Hoffmann
211*034cb968SGerd Hoffmann case VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE:
212*034cb968SGerd Hoffmann lvarstate = (void *)pol->entry + sizeof(*pe);
213*034cb968SGerd Hoffmann lvarname = (void *)pol->entry + sizeof(*pe) + sizeof(*lvarstate);
214*034cb968SGerd Hoffmann lvarnamesize = pe->offset_to_name - sizeof(*pe) - sizeof(*lvarstate);
215*034cb968SGerd Hoffmann
216*034cb968SGerd Hoffmann uefi_trace_variable(__func__, lvarstate->namespace,
217*034cb968SGerd Hoffmann lvarname, lvarnamesize);
218*034cb968SGerd Hoffmann lvar = uefi_vars_find_variable(uv, lvarstate->namespace,
219*034cb968SGerd Hoffmann lvarname, lvarnamesize);
220*034cb968SGerd Hoffmann if (lvar && lvar->data_size == 1) {
221*034cb968SGerd Hoffmann uint8_t *value = lvar->data;
222*034cb968SGerd Hoffmann if (lvarstate->value == *value) {
223*034cb968SGerd Hoffmann return EFI_WRITE_PROTECTED;
224*034cb968SGerd Hoffmann }
225*034cb968SGerd Hoffmann }
226*034cb968SGerd Hoffmann break;
227*034cb968SGerd Hoffmann }
228*034cb968SGerd Hoffmann
229*034cb968SGerd Hoffmann return EFI_SUCCESS;
230*034cb968SGerd Hoffmann }
231*034cb968SGerd Hoffmann
uefi_vars_policies_clear(uefi_vars_state * uv)232*034cb968SGerd Hoffmann void uefi_vars_policies_clear(uefi_vars_state *uv)
233*034cb968SGerd Hoffmann {
234*034cb968SGerd Hoffmann uefi_var_policy *pol;
235*034cb968SGerd Hoffmann
236*034cb968SGerd Hoffmann while (!QTAILQ_EMPTY(&uv->var_policies)) {
237*034cb968SGerd Hoffmann pol = QTAILQ_FIRST(&uv->var_policies);
238*034cb968SGerd Hoffmann QTAILQ_REMOVE(&uv->var_policies, pol, next);
239*034cb968SGerd Hoffmann g_free(pol->entry);
240*034cb968SGerd Hoffmann g_free(pol);
241*034cb968SGerd Hoffmann }
242*034cb968SGerd Hoffmann }
243*034cb968SGerd Hoffmann
uefi_vars_mm_policy_error(mm_header * mhdr,mm_check_policy * mchk,uint64_t status)244*034cb968SGerd Hoffmann static size_t uefi_vars_mm_policy_error(mm_header *mhdr,
245*034cb968SGerd Hoffmann mm_check_policy *mchk,
246*034cb968SGerd Hoffmann uint64_t status)
247*034cb968SGerd Hoffmann {
248*034cb968SGerd Hoffmann mchk->result = status;
249*034cb968SGerd Hoffmann return sizeof(*mchk);
250*034cb968SGerd Hoffmann }
251*034cb968SGerd Hoffmann
uefi_vars_mm_check_policy_is_enabled(uefi_vars_state * uv,mm_header * mhdr,mm_check_policy * mchk,void * func)252*034cb968SGerd Hoffmann static uint32_t uefi_vars_mm_check_policy_is_enabled(uefi_vars_state *uv,
253*034cb968SGerd Hoffmann mm_header *mhdr,
254*034cb968SGerd Hoffmann mm_check_policy *mchk,
255*034cb968SGerd Hoffmann void *func)
256*034cb968SGerd Hoffmann {
257*034cb968SGerd Hoffmann mm_check_policy_is_enabled *mpar = func;
258*034cb968SGerd Hoffmann size_t length;
259*034cb968SGerd Hoffmann
260*034cb968SGerd Hoffmann length = sizeof(*mchk) + sizeof(*mpar);
261*034cb968SGerd Hoffmann if (mhdr->length < length) {
262*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_BAD_BUFFER_SIZE);
263*034cb968SGerd Hoffmann }
264*034cb968SGerd Hoffmann
265*034cb968SGerd Hoffmann mpar->state = TRUE;
266*034cb968SGerd Hoffmann mchk->result = EFI_SUCCESS;
267*034cb968SGerd Hoffmann return sizeof(*mchk);
268*034cb968SGerd Hoffmann }
269*034cb968SGerd Hoffmann
uefi_vars_mm_check_policy_register(uefi_vars_state * uv,mm_header * mhdr,mm_check_policy * mchk,void * func)270*034cb968SGerd Hoffmann static uint32_t uefi_vars_mm_check_policy_register(uefi_vars_state *uv,
271*034cb968SGerd Hoffmann mm_header *mhdr,
272*034cb968SGerd Hoffmann mm_check_policy *mchk,
273*034cb968SGerd Hoffmann void *func)
274*034cb968SGerd Hoffmann {
275*034cb968SGerd Hoffmann variable_policy_entry *pe = func;
276*034cb968SGerd Hoffmann uefi_var_policy *pol;
277*034cb968SGerd Hoffmann uint64_t length;
278*034cb968SGerd Hoffmann
279*034cb968SGerd Hoffmann if (uadd64_overflow(sizeof(*mchk), pe->size, &length)) {
280*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_BAD_BUFFER_SIZE);
281*034cb968SGerd Hoffmann }
282*034cb968SGerd Hoffmann if (mhdr->length < length) {
283*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_BAD_BUFFER_SIZE);
284*034cb968SGerd Hoffmann }
285*034cb968SGerd Hoffmann if (pe->size < sizeof(*pe)) {
286*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_BAD_BUFFER_SIZE);
287*034cb968SGerd Hoffmann }
288*034cb968SGerd Hoffmann if (pe->offset_to_name < sizeof(*pe)) {
289*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_BAD_BUFFER_SIZE);
290*034cb968SGerd Hoffmann }
291*034cb968SGerd Hoffmann
292*034cb968SGerd Hoffmann if (pe->lock_policy_type == VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE &&
293*034cb968SGerd Hoffmann pe->offset_to_name < sizeof(*pe) + sizeof(variable_lock_on_var_state)) {
294*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_BAD_BUFFER_SIZE);
295*034cb968SGerd Hoffmann }
296*034cb968SGerd Hoffmann
297*034cb968SGerd Hoffmann /* check space for minimum string length */
298*034cb968SGerd Hoffmann if (pe->size < (size_t)pe->offset_to_name) {
299*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_BAD_BUFFER_SIZE);
300*034cb968SGerd Hoffmann }
301*034cb968SGerd Hoffmann
302*034cb968SGerd Hoffmann if (!uefi_str_is_valid((void *)pe + pe->offset_to_name,
303*034cb968SGerd Hoffmann pe->size - pe->offset_to_name,
304*034cb968SGerd Hoffmann false)) {
305*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_INVALID_PARAMETER);
306*034cb968SGerd Hoffmann }
307*034cb968SGerd Hoffmann
308*034cb968SGerd Hoffmann pol = find_policy(uv, pe->namespace,
309*034cb968SGerd Hoffmann (void *)pe + pe->offset_to_name,
310*034cb968SGerd Hoffmann pe->size - pe->offset_to_name);
311*034cb968SGerd Hoffmann if (pol) {
312*034cb968SGerd Hoffmann return uefi_vars_mm_policy_error(mhdr, mchk, EFI_ALREADY_STARTED);
313*034cb968SGerd Hoffmann }
314*034cb968SGerd Hoffmann
315*034cb968SGerd Hoffmann uefi_vars_add_policy(uv, pe);
316*034cb968SGerd Hoffmann
317*034cb968SGerd Hoffmann mchk->result = EFI_SUCCESS;
318*034cb968SGerd Hoffmann return sizeof(*mchk);
319*034cb968SGerd Hoffmann }
320*034cb968SGerd Hoffmann
uefi_vars_mm_check_policy_proto(uefi_vars_state * uv)321*034cb968SGerd Hoffmann uint32_t uefi_vars_mm_check_policy_proto(uefi_vars_state *uv)
322*034cb968SGerd Hoffmann {
323*034cb968SGerd Hoffmann static const char *fnames[] = {
324*034cb968SGerd Hoffmann "zero",
325*034cb968SGerd Hoffmann "disable",
326*034cb968SGerd Hoffmann "is-enabled",
327*034cb968SGerd Hoffmann "register",
328*034cb968SGerd Hoffmann "dump",
329*034cb968SGerd Hoffmann "lock",
330*034cb968SGerd Hoffmann };
331*034cb968SGerd Hoffmann const char *fname;
332*034cb968SGerd Hoffmann mm_header *mhdr = (mm_header *) uv->buffer;
333*034cb968SGerd Hoffmann mm_check_policy *mchk = (mm_check_policy *) (uv->buffer + sizeof(*mhdr));
334*034cb968SGerd Hoffmann void *func = (uv->buffer + sizeof(*mhdr) + sizeof(*mchk));
335*034cb968SGerd Hoffmann
336*034cb968SGerd Hoffmann if (mhdr->length < sizeof(*mchk)) {
337*034cb968SGerd Hoffmann return UEFI_VARS_STS_ERR_BAD_BUFFER_SIZE;
338*034cb968SGerd Hoffmann }
339*034cb968SGerd Hoffmann
340*034cb968SGerd Hoffmann fname = mchk->command < ARRAY_SIZE(fnames)
341*034cb968SGerd Hoffmann ? fnames[mchk->command]
342*034cb968SGerd Hoffmann : "unknown";
343*034cb968SGerd Hoffmann trace_uefi_vars_policy_cmd(fname);
344*034cb968SGerd Hoffmann
345*034cb968SGerd Hoffmann switch (mchk->command) {
346*034cb968SGerd Hoffmann case VAR_CHECK_POLICY_COMMAND_DISABLE:
347*034cb968SGerd Hoffmann mchk->result = EFI_UNSUPPORTED;
348*034cb968SGerd Hoffmann break;
349*034cb968SGerd Hoffmann case VAR_CHECK_POLICY_COMMAND_IS_ENABLED:
350*034cb968SGerd Hoffmann uefi_vars_mm_check_policy_is_enabled(uv, mhdr, mchk, func);
351*034cb968SGerd Hoffmann break;
352*034cb968SGerd Hoffmann case VAR_CHECK_POLICY_COMMAND_REGISTER:
353*034cb968SGerd Hoffmann if (uv->policy_locked) {
354*034cb968SGerd Hoffmann mchk->result = EFI_WRITE_PROTECTED;
355*034cb968SGerd Hoffmann } else {
356*034cb968SGerd Hoffmann uefi_vars_mm_check_policy_register(uv, mhdr, mchk, func);
357*034cb968SGerd Hoffmann }
358*034cb968SGerd Hoffmann break;
359*034cb968SGerd Hoffmann case VAR_CHECK_POLICY_COMMAND_LOCK:
360*034cb968SGerd Hoffmann uv->policy_locked = true;
361*034cb968SGerd Hoffmann mchk->result = EFI_SUCCESS;
362*034cb968SGerd Hoffmann break;
363*034cb968SGerd Hoffmann default:
364*034cb968SGerd Hoffmann mchk->result = EFI_UNSUPPORTED;
365*034cb968SGerd Hoffmann break;
366*034cb968SGerd Hoffmann }
367*034cb968SGerd Hoffmann
368*034cb968SGerd Hoffmann uefi_trace_status(__func__, mchk->result);
369*034cb968SGerd Hoffmann return UEFI_VARS_STS_SUCCESS;
370*034cb968SGerd Hoffmann }
371