xref: /qemu/hw/uefi/var-service-policy.c (revision 50aa3d0984d8a4a9c39d34e2f81e8a70674462e4)
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