1 /*
2  * cmd_pef.c
3  *
4  * A command interpreter for OpenIPMI
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2004 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #include <errno.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <OpenIPMI/ipmiif.h>
40 #include <OpenIPMI/ipmi_pef.h>
41 #include <OpenIPMI/ipmi_cmdlang.h>
42 #include <OpenIPMI/ipmi_mc.h>
43 
44 /* Internal includes, do not use in your programs */
45 #include <OpenIPMI/internal/ipmi_malloc.h>
46 #include <OpenIPMI/internal/locked_list.h>
47 
48 static locked_list_t *pefs;
49 
50 static void
pef_list_handler(ipmi_pef_t * pef,void * cb_data)51 pef_list_handler(ipmi_pef_t *pef, void *cb_data)
52 {
53     ipmi_cmd_info_t *cmd_info = cb_data;
54     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
55     char            pef_name[IPMI_PEF_NAME_LEN];
56 
57     if (cmdlang->err)
58 	return;
59 
60     ipmi_pef_get_name(pef, pef_name, sizeof(pef_name));
61 
62     ipmi_cmdlang_out(cmd_info, "Name", pef_name);
63 }
64 
65 static void
pef_list(ipmi_domain_t * domain,void * cb_data)66 pef_list(ipmi_domain_t *domain, void *cb_data)
67 {
68     ipmi_cmd_info_t *cmd_info = cb_data;
69     char             domain_name[IPMI_DOMAIN_NAME_LEN];
70 
71     ipmi_domain_get_name(domain, domain_name, sizeof(domain_name));
72     ipmi_cmdlang_out(cmd_info, "Domain", NULL);
73     ipmi_cmdlang_down(cmd_info);
74     ipmi_cmdlang_out(cmd_info, "Name", domain_name);
75     ipmi_cmdlang_out(cmd_info, "PEFs", NULL);
76     ipmi_cmdlang_down(cmd_info);
77     ipmi_pef_iterate_pefs(domain, pef_list_handler, cmd_info);
78     ipmi_cmdlang_up(cmd_info);
79     ipmi_cmdlang_up(cmd_info);
80 }
81 
82 static void
get_mc_name(ipmi_mc_t * mc,void * cb_data)83 get_mc_name(ipmi_mc_t *mc, void *cb_data)
84 {
85     ipmi_cmd_info_t *cmd_info = cb_data;
86     char            mc_name[IPMI_MC_NAME_LEN];
87 
88     ipmi_mc_get_name(mc, mc_name, sizeof(mc_name));
89     ipmi_cmdlang_out(cmd_info, "MC", mc_name);
90 }
91 
92 static void
pef_info(ipmi_pef_t * pef,void * cb_data)93 pef_info(ipmi_pef_t *pef, void *cb_data)
94 {
95     ipmi_cmd_info_t *cmd_info = cb_data;
96     char            pef_name[IPMI_PEF_NAME_LEN];
97 
98     ipmi_pef_get_name(pef, pef_name, sizeof(pef_name));
99 
100     ipmi_cmdlang_out(cmd_info, "PEF", NULL);
101     ipmi_cmdlang_down(cmd_info);
102     ipmi_cmdlang_out(cmd_info, "Name", pef_name);
103     ipmi_mc_pointer_cb(ipmi_pef_get_mc(pef), get_mc_name, cmd_info);
104     ipmi_cmdlang_up(cmd_info);
105 }
106 
107 static void
pef_new_done(ipmi_pef_t * pef,int err,void * cb_data)108 pef_new_done(ipmi_pef_t *pef, int err, void *cb_data)
109 {
110     ipmi_cmd_info_t *cmd_info = cb_data;
111     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
112     char            pef_name[IPMI_PEF_NAME_LEN];
113 
114     ipmi_cmdlang_lock(cmd_info);
115     if (err) {
116 	cmdlang->errstr = "Error allocating PEF";
117 	cmdlang->err = err;
118 	cmdlang->location = "cmd_pef.c(pef_new_done)";
119 	goto out;
120     }
121 
122     ipmi_pef_get_name(pef, pef_name, sizeof(pef_name));
123     ipmi_cmdlang_out(cmd_info, "PEF", pef_name);
124 
125  out:
126     ipmi_cmdlang_unlock(cmd_info);
127     ipmi_cmdlang_cmd_info_put(cmd_info);
128 }
129 
130 static void
pef_new(ipmi_mc_t * mc,void * cb_data)131 pef_new(ipmi_mc_t *mc, void *cb_data)
132 {
133     ipmi_cmd_info_t *cmd_info = cb_data;
134     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
135     int             rv;
136 
137     ipmi_cmdlang_cmd_info_get(cmd_info);
138     rv = ipmi_pef_alloc(mc, pef_new_done, cmd_info, NULL);
139     if (rv) {
140 	ipmi_cmdlang_cmd_info_put(cmd_info);
141 	cmdlang->errstr = "Error from ipmi_pef_alloc";
142 	cmdlang->err = rv;
143 	goto out_err;
144     }
145     return;
146 
147  out_err:
148     ipmi_mc_get_name(mc, cmdlang->objstr,
149 		     cmdlang->objstr_len);
150     cmdlang->location = "cmd_pef.c(pef_new)";
151 }
152 
153 static void
pef_close_done(ipmi_pef_t * pef,int err,void * cb_data)154 pef_close_done(ipmi_pef_t *pef, int err, void *cb_data)
155 {
156     ipmi_cmd_info_t *cmd_info = cb_data;
157     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
158     char            pef_name[IPMI_PEF_NAME_LEN];
159 
160     ipmi_cmdlang_lock(cmd_info);
161     if (err) {
162 	ipmi_pef_get_name(pef, cmdlang->objstr,
163 			  cmdlang->objstr_len);
164 	cmdlang->errstr = "Error closing PEF";
165 	cmdlang->err = err;
166 	cmdlang->location = "cmd_pef.c(pef_close_done)";
167 	goto out;
168     }
169 
170     ipmi_pef_get_name(pef, pef_name, sizeof(pef_name));
171     ipmi_cmdlang_out(cmd_info, "PEF destroyed", pef_name);
172 
173  out:
174     ipmi_cmdlang_unlock(cmd_info);
175     ipmi_cmdlang_cmd_info_put(cmd_info);
176 }
177 
178 static void
pef_close(ipmi_pef_t * pef,void * cb_data)179 pef_close(ipmi_pef_t *pef, void *cb_data)
180 {
181     ipmi_cmd_info_t *cmd_info = cb_data;
182     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
183     int             rv;
184 
185     ipmi_cmdlang_cmd_info_get(cmd_info);
186     rv = ipmi_pef_destroy(pef, pef_close_done, cmd_info);
187     if (rv) {
188 	ipmi_cmdlang_cmd_info_put(cmd_info);
189 	ipmi_pef_get_name(pef, cmdlang->objstr,
190 			      cmdlang->objstr_len);
191 	cmdlang->errstr = "Error closing PEF";
192 	cmdlang->err = rv;
193 	cmdlang->location = "cmd_pef.c(pef_close)";
194     }
195 }
196 
197 #define PEF_CONFIG_NAME_LEN 80
198 typedef struct pef_config_info_s
199 {
200     char              name[PEF_CONFIG_NAME_LEN];
201     ipmi_pef_config_t *config;
202 } pef_config_info_t;
203 
204 static unsigned int unique_num = 0;
205 
206 typedef struct find_config_s
207 {
208     char              *name;
209     ipmi_pef_config_t *config;
210     int               delete;
211 } find_config_t;
212 
213 static int
find_config_handler(void * cb_data,void * item1,void * item2)214 find_config_handler(void *cb_data, void *item1, void *item2)
215 {
216     pef_config_info_t *info = item1;
217     find_config_t     *find = cb_data;
218 
219     if (strcmp(find->name, info->name) == 0) {
220 	find->config = info->config;
221 	if (find->delete) {
222 	    locked_list_remove(pefs, item1, item2);
223 	    ipmi_mem_free(info);
224 	}
225 	return LOCKED_LIST_ITER_STOP;
226     }
227 
228     return LOCKED_LIST_ITER_CONTINUE;
229 }
230 
231 static ipmi_pef_config_t *
find_config(char * name,int delete)232 find_config(char *name, int delete)
233 {
234     find_config_t find;
235 
236     find.name = name;
237     find.config = NULL;
238     find.delete = delete;
239     locked_list_iterate(pefs, find_config_handler, &find);
240     return find.config;
241 }
242 
243 typedef void (*lp_set)(ipmi_cmd_info_t *cmd_info, char *val,
244 		       ipmi_pef_config_t *lanc, void *func);
245 typedef void (*lp_out)(ipmi_cmd_info_t *cmd_info, char *name,
246 		       ipmi_pef_config_t *lanc, void *func);
247 typedef struct lp_item_s
248 {
249     lp_set set;
250     lp_out out;
251 } lp_item_t;
252 
253 static void
set_retint(ipmi_cmd_info_t * cmd_info,char * val,ipmi_pef_config_t * lanc,void * func)254 set_retint(ipmi_cmd_info_t *cmd_info, char *val,
255 	   ipmi_pef_config_t *lanc, void *func)
256 {
257     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
258     int            (*f)(ipmi_pef_config_t *l, unsigned int v) = func;
259     int            v;
260 
261     ipmi_cmdlang_get_int(val, &v, cmd_info);
262     if (!cmdlang->err) {
263 	cmdlang->err = f(lanc, v);
264 	if (cmdlang->err) {
265 	    cmdlang->errstr = "Error setting parameter";
266 	}
267     }
268 }
269 static void
out_retint(ipmi_cmd_info_t * cmd_info,char * name,ipmi_pef_config_t * lanc,void * func)270 out_retint(ipmi_cmd_info_t *cmd_info, char *name,
271 	   ipmi_pef_config_t *lanc, void *func)
272 {
273     unsigned int   (*f)(ipmi_pef_config_t *l) = func;
274     ipmi_cmdlang_out_int(cmd_info, name, f(lanc));
275 }
276 static lp_item_t lp_retint = {set_retint, out_retint};
277 
278 static void
set_retbool(ipmi_cmd_info_t * cmd_info,char * val,ipmi_pef_config_t * lanc,void * func)279 set_retbool(ipmi_cmd_info_t *cmd_info, char *val,
280 	    ipmi_pef_config_t *lanc, void *func)
281 {
282     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
283     int            (*f)(ipmi_pef_config_t *l, unsigned int v) = func;
284     int            v;
285 
286     ipmi_cmdlang_get_bool(val, &v, cmd_info);
287     if (!cmdlang->err) {
288 	cmdlang->err = f(lanc, v);
289 	if (cmdlang->err) {
290 	    cmdlang->errstr = "Error setting parameter";
291 	}
292     }
293 }
294 static void
out_retbool(ipmi_cmd_info_t * cmd_info,char * name,ipmi_pef_config_t * lanc,void * func)295 out_retbool(ipmi_cmd_info_t *cmd_info, char *name,
296 	    ipmi_pef_config_t *lanc, void *func)
297 {
298     unsigned int   (*f)(ipmi_pef_config_t *l) = func;
299     ipmi_cmdlang_out_bool(cmd_info, name, f(lanc));
300 }
301 static lp_item_t lp_retbool = {set_retbool, out_retbool};
302 
303 static void
set_int(ipmi_cmd_info_t * cmd_info,char * val,ipmi_pef_config_t * lanc,void * func)304 set_int(ipmi_cmd_info_t *cmd_info, char *val,
305 	ipmi_pef_config_t *lanc, void *func)
306 {
307     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
308     int            (*f)(ipmi_pef_config_t *l, unsigned int v) = func;
309     int            v;
310 
311     ipmi_cmdlang_get_int(val, &v, cmd_info);
312     if (!cmdlang->err) {
313 	cmdlang->err = f(lanc, v);
314 	if (cmdlang->err) {
315 	    cmdlang->errstr = "Error setting parameter";
316 	}
317     }
318 }
319 static void
out_int(ipmi_cmd_info_t * cmd_info,char * name,ipmi_pef_config_t * lanc,void * func)320 out_int(ipmi_cmd_info_t *cmd_info, char *name,
321 	ipmi_pef_config_t *lanc, void *func)
322 {
323     unsigned int   v;
324     int            rv;
325     int            (*f)(ipmi_pef_config_t *l, unsigned int *v) = func;
326 
327     rv = f(lanc, &v);
328     if (!rv)
329 	ipmi_cmdlang_out_int(cmd_info, name, v);
330 }
331 static lp_item_t lp_int = {set_int, out_int};
332 
333 static void
set_guid(ipmi_cmd_info_t * cmd_info,char * val,ipmi_pef_config_t * lanc,void * func)334 set_guid(ipmi_cmd_info_t *cmd_info, char *val,
335 	 ipmi_pef_config_t *lanc, void *func)
336 {
337     unsigned char  v[16];
338     char           tmp[3];
339     char           *end;
340     int            i;
341     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
342     int            (*f)(ipmi_pef_config_t *l, unsigned char *v,
343 			unsigned int dl) = func;
344 
345     if (strlen(val) != 32) {
346 	cmdlang->err = EINVAL;
347 	cmdlang->errstr = "Invalid GUID";
348 	return;
349     }
350 
351     for (i=0; i<16; i++) {
352 	memset(tmp, 0, sizeof(tmp));
353 	memcpy(tmp, val+(i*2), 2);
354 	v[i] = strtoul(tmp, &end, 16);
355 	if (*end != '\0') {
356 	    cmdlang->err = EINVAL;
357 	    cmdlang->errstr = "Invalid GUID";
358 	    return;
359 	}
360     }
361     if (!cmdlang->err) {
362 	cmdlang->err = f(lanc, v, sizeof(v));
363 	if (cmdlang->err) {
364 	    cmdlang->errstr = "Error setting parameter";
365 	}
366     }
367 }
368 static void
out_guid(ipmi_cmd_info_t * cmd_info,char * name,ipmi_pef_config_t * lanc,void * func)369 out_guid(ipmi_cmd_info_t *cmd_info, char *name,
370        ipmi_pef_config_t *lanc, void *func)
371 {
372     int            rv;
373     int            (*f)(ipmi_pef_config_t *l, unsigned char *v,
374 			unsigned int *dl) = func;
375     unsigned char  v[16];
376     unsigned int   len = sizeof(v);
377     char           str[33];
378     char           *s;
379     int            i;
380 
381     rv = f(lanc, (unsigned char *) &v, &len);
382     if (!rv) {
383 	s = str;
384 	for (i=0; i<16; i++)
385 	    s += sprintf(s, "%2.2x", v[i]);
386 	ipmi_cmdlang_out(cmd_info, name, str);
387     }
388 }
389 static lp_item_t lp_guid = {set_guid, out_guid};
390 
391 static struct lps_s
392 {
393     char      *name;
394     lp_item_t *lpi;
395     void      *get_func;
396     void      *set_func;
397 } lps[] =
398 /* read-only */
399 #define FR(name, type) { #name, &lp_ ## type, ipmi_pefconfig_get_ ## name, \
400 		         NULL }
401 /* Writable */
402 #define F(name, type) { #name, &lp_ ## type, ipmi_pefconfig_get_ ## name, \
403 		        ipmi_pefconfig_set_ ## name }
404 {
405     F(alert_startup_delay_enabled, retbool),
406     F(startup_delay_enabled, retbool),
407     F(event_messages_enabled, retbool),
408     F(pef_enabled, retbool),
409     F(diagnostic_interrupt_enabled, retbool),
410     F(oem_action_enabled, retbool),
411     F(power_cycle_enabled, retbool),
412     F(reset_enabled, retbool),
413     F(power_down_enabled, retbool),
414     F(alert_enabled, retbool),
415     F(startup_delay, int),
416     F(alert_startup_delay, int),
417     F(guid_enabled, retbool),
418     F(guid_val, guid),
419     FR(num_event_filters, retint),
420     FR(num_alert_policies, retint),
421     FR(num_alert_strings, retint),
422     { NULL }
423 };
424 
425 /*
426  * Selector-based get/out routines.
427  */
428 typedef void (*ulp_set)(ipmi_cmd_info_t *cmd_info, int sel, char *val,
429 			ipmi_pef_config_t *lanc, void *func);
430 typedef void (*ulp_out)(ipmi_cmd_info_t *cmd_info, int sel, char *name,
431 			ipmi_pef_config_t *lanc, void *func);
432 typedef struct ulp_item_s
433 {
434     ulp_set set;
435     ulp_out out;
436 } ulp_item_t;
437 
438 static void
uset_bool(ipmi_cmd_info_t * cmd_info,int sel,char * val,ipmi_pef_config_t * lanc,void * func)439 uset_bool(ipmi_cmd_info_t *cmd_info, int sel, char *val,
440 	 ipmi_pef_config_t *lanc, void *func)
441 {
442     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
443     int            (*f)(ipmi_pef_config_t *l, unsigned int sel,
444 			unsigned int v) = func;
445     int            v;
446 
447     ipmi_cmdlang_get_bool(val, &v, cmd_info);
448     if (!cmdlang->err) {
449 	cmdlang->err = f(lanc, sel, v);
450 	if (cmdlang->err) {
451 	    cmdlang->errstr = "Error setting parameter";
452 	}
453     }
454 }
455 static void
uout_bool(ipmi_cmd_info_t * cmd_info,int sel,char * name,ipmi_pef_config_t * lanc,void * func)456 uout_bool(ipmi_cmd_info_t *cmd_info, int sel, char *name,
457 	 ipmi_pef_config_t *lanc, void *func)
458 {
459     unsigned int   v;
460     int            rv;
461     int            (*f)(ipmi_pef_config_t *l, unsigned int sel,
462 			unsigned int *v) = func;
463 
464     rv = f(lanc, sel, &v);
465     if (!rv)
466 	ipmi_cmdlang_out_bool(cmd_info, name, v);
467 }
468 static ulp_item_t lp_ubool = {uset_bool, uout_bool};
469 
470 static void
uset_int(ipmi_cmd_info_t * cmd_info,int sel,char * val,ipmi_pef_config_t * lanc,void * func)471 uset_int(ipmi_cmd_info_t *cmd_info, int sel, char *val,
472 	 ipmi_pef_config_t *lanc, void *func)
473 {
474     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
475     int            (*f)(ipmi_pef_config_t *l, unsigned int sel,
476 			unsigned int v) = func;
477     int            v;
478 
479     ipmi_cmdlang_get_int(val, &v, cmd_info);
480     if (!cmdlang->err) {
481 	cmdlang->err = f(lanc, sel, v);
482 	if (cmdlang->err) {
483 	    cmdlang->errstr = "Error setting parameter";
484 	}
485     }
486 }
487 static void
uout_int(ipmi_cmd_info_t * cmd_info,int sel,char * name,ipmi_pef_config_t * lanc,void * func)488 uout_int(ipmi_cmd_info_t *cmd_info, int sel, char *name,
489 	 ipmi_pef_config_t *lanc, void *func)
490 {
491     unsigned int   v;
492     int            rv;
493     int            (*f)(ipmi_pef_config_t *l, unsigned int sel,
494 			unsigned int *v) = func;
495 
496     rv = f(lanc, sel, &v);
497     if (!rv)
498 	ipmi_cmdlang_out_int(cmd_info, name, v);
499 }
500 static ulp_item_t lp_uint = {uset_int, uout_int};
501 
502 static void
uset_str(ipmi_cmd_info_t * cmd_info,int sel,char * val,ipmi_pef_config_t * lanc,void * func)503 uset_str(ipmi_cmd_info_t *cmd_info, int sel, char *val,
504 	 ipmi_pef_config_t *lanc, void *func)
505 {
506     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
507     int            (*f)(ipmi_pef_config_t *l, unsigned int sel,
508 			char *v) = func;
509 
510     if (!cmdlang->err) {
511 	cmdlang->err = f(lanc, sel, val);
512 	if (cmdlang->err) {
513 	    cmdlang->errstr = "Error setting parameter";
514 	}
515     }
516 }
517 static void
uout_str(ipmi_cmd_info_t * cmd_info,int sel,char * name,ipmi_pef_config_t * lanc,void * func)518 uout_str(ipmi_cmd_info_t *cmd_info, int sel, char *name,
519 	 ipmi_pef_config_t *lanc, void *func)
520 {
521     char          v[100];
522     int           rv;
523     int           (*f)(ipmi_pef_config_t *l, unsigned int sel,
524 		       char *v, unsigned int *dl) = func;
525     unsigned int  len = sizeof(v);
526 
527     rv = f(lanc, sel, v, &len);
528     if (!rv)
529 	ipmi_cmdlang_out(cmd_info, name, v);
530 }
531 static ulp_item_t lp_ustr = {uset_str, uout_str};
532 
533 /*
534  * event-filter table items
535  */
536 static struct ulps_s
537 {
538     char       *name;
539     ulp_item_t *lpi;
540     void       *get_func;
541     void       *set_func;
542 } elps[] =
543 {
544     F(enable_filter, ubool),
545     F(filter_type, uint),
546     F(diagnostic_interrupt, ubool),
547     F(oem_action, ubool),
548     F(power_cycle, ubool),
549     F(reset, ubool),
550     F(power_down, ubool),
551     F(alert, ubool),
552     F(alert_policy_number, uint),
553     F(event_severity, uint),
554     F(generator_id_addr, uint),
555     F(generator_id_channel_lun, uint),
556     F(sensor_type, uint),
557     F(sensor_number, uint),
558     F(event_trigger, uint),
559     F(data1_offset_mask, uint),
560     F(data1_mask, uint),
561     F(data1_compare1, uint),
562     F(data1_compare2, uint),
563     F(data2_mask, uint),
564     F(data2_compare1, uint),
565     F(data2_compare2, uint),
566     F(data3_mask, uint),
567     F(data3_compare1, uint),
568     F(data3_compare2, uint),
569     { NULL }
570 };
571 
572 /*
573  * Alert policy table items
574  */
575 static struct ulps_s plps[] =
576 {
577     F(policy_num, uint),
578     F(enabled, ubool),
579     F(policy, uint),
580     F(channel, uint),
581     F(destination_selector, uint),
582     F(alert_string_event_specific, ubool),
583     F(alert_string_selector, uint),
584     { NULL }
585 };
586 
587 /*
588  * Alert string items
589  */
590 static struct ulps_s slps[] =
591 {
592     F(event_filter, uint),
593     F(alert_string_set, uint),
594     F(alert_string, ustr),
595     { NULL }
596 };
597 
598 static void
config_info(ipmi_cmd_info_t * cmd_info,ipmi_pef_config_t * config)599 config_info(ipmi_cmd_info_t *cmd_info, ipmi_pef_config_t *config)
600 {
601     int i;
602     int j;
603     int num;
604 
605     /* Basic items */
606     for (i=0; lps[i].name; i++) {
607 	lp_item_t *lp = lps[i].lpi;
608 	lp->out(cmd_info, lps[i].name, config, lps[i].get_func);
609     }
610 
611     /* per-event-filter table items */
612     num = ipmi_pefconfig_get_num_event_filters(config);
613     for (j=0; j<num; j++) {
614 	struct ulps_s *lps = elps;
615 	ipmi_cmdlang_out(cmd_info, "Event Filter", NULL);
616 	ipmi_cmdlang_down(cmd_info);
617 	ipmi_cmdlang_out_int(cmd_info, "Number", j);
618 	for (i=0; lps[i].name; i++) {
619 	    ulp_item_t *lp = lps[i].lpi;
620 	    lp->out(cmd_info, j, lps[i].name, config, lps[i].get_func);
621 	}
622 	ipmi_cmdlang_up(cmd_info);
623     }
624 
625     /* per-alert policy table items */
626     num = ipmi_pefconfig_get_num_alert_policies(config);
627     for (j=0; j<num; j++) {
628 	struct ulps_s *lps = plps;
629 	ipmi_cmdlang_out(cmd_info, "Alert Policy", NULL);
630 	ipmi_cmdlang_down(cmd_info);
631 	ipmi_cmdlang_out_int(cmd_info, "Number", j);
632 	for (i=0; lps[i].name; i++) {
633 	    ulp_item_t *lp = lps[i].lpi;
634 	    lp->out(cmd_info, j, lps[i].name, config, lps[i].get_func);
635 	}
636 	ipmi_cmdlang_up(cmd_info);
637     }
638 
639     /* per-alert string items */
640     num = ipmi_pefconfig_get_num_alert_strings(config);
641     for (j=0; j<num; j++) {
642 	struct ulps_s *lps = slps;
643 	ipmi_cmdlang_out(cmd_info, "Alert String", NULL);
644 	ipmi_cmdlang_down(cmd_info);
645 	ipmi_cmdlang_out_int(cmd_info, "Number", j);
646 	for (i=0; lps[i].name; i++) {
647 	    ulp_item_t *lp = lps[i].lpi;
648 	    lp->out(cmd_info, j, lps[i].name, config, lps[i].get_func);
649 	}
650 	ipmi_cmdlang_up(cmd_info);
651     }
652 }
653 
654 static void
pef_config_get_done(ipmi_pef_t * pef,int err,ipmi_pef_config_t * config,void * cb_data)655 pef_config_get_done(ipmi_pef_t        *pef,
656 		    int               err,
657 		    ipmi_pef_config_t *config,
658 		    void              *cb_data)
659 {
660     ipmi_cmd_info_t   *cmd_info = cb_data;
661     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
662     char              pef_name[IPMI_PEF_NAME_LEN];
663     pef_config_info_t *info;
664 
665     ipmi_cmdlang_lock(cmd_info);
666     if (err) {
667 	cmdlang->errstr = "Error getting PEF";
668 	cmdlang->err = err;
669 	goto out;
670     }
671 
672     ipmi_pef_get_name(pef, pef_name, sizeof(pef_name));
673 
674     info = ipmi_mem_alloc(sizeof(*info));
675     if (!info) {
676 	cmdlang->errstr = "Out of memory";
677 	cmdlang->err = ENOMEM;
678 	ipmi_pef_free_config(config);
679 	goto out;
680     }
681     snprintf(info->name, sizeof(info->name), "%s.%u",
682 	     pef_name, unique_num);
683     info->config = config;
684     if (!locked_list_add(pefs, info, NULL)) {
685 	cmdlang->errstr = "Out of memory";
686 	cmdlang->err = ENOMEM;
687 	ipmi_pef_free_config(config);
688 	ipmi_mem_free(info);
689 	goto out;
690     }
691     unique_num++;
692 
693     ipmi_cmdlang_out(cmd_info, "PEF Config", NULL);
694     ipmi_cmdlang_down(cmd_info);
695     ipmi_cmdlang_out(cmd_info, "Name", info->name);
696     config_info(cmd_info, config);
697     ipmi_cmdlang_up(cmd_info);
698 
699  out:
700     if (cmdlang->err) {
701 	ipmi_pef_get_name(pef, cmdlang->objstr,
702 			      cmdlang->objstr_len);
703 	cmdlang->location = "cmd_pef.c(pef_config_get_done)";
704     }
705     ipmi_cmdlang_unlock(cmd_info);
706     ipmi_cmdlang_cmd_info_put(cmd_info);
707 }
708 
709 static void
pef_config_get(ipmi_pef_t * pef,void * cb_data)710 pef_config_get(ipmi_pef_t *pef, void *cb_data)
711 {
712     ipmi_cmd_info_t *cmd_info = cb_data;
713     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
714     int             rv;
715 
716     ipmi_cmdlang_cmd_info_get(cmd_info);
717     rv = ipmi_pef_get_config(pef, pef_config_get_done, cmd_info);
718     if (rv) {
719 	ipmi_pef_get_name(pef, cmdlang->objstr,
720 			      cmdlang->objstr_len);
721 	ipmi_cmdlang_cmd_info_put(cmd_info);
722 	cmdlang->errstr = "Error getting PEF";
723 	cmdlang->err = rv;
724 	cmdlang->location = "cmd_pef.c(pef_config_get)";
725     }
726 }
727 
728 typedef struct pef_config_op_s
729 {
730     char            name[PEF_CONFIG_NAME_LEN];
731     ipmi_cmd_info_t *cmd_info;
732 } pef_config_op_t;
733 
734 static void
pef_config_set_done(ipmi_pef_t * pef,int err,void * cb_data)735 pef_config_set_done(ipmi_pef_t *pef,
736 		    int        err,
737 		    void       *cb_data)
738 {
739     pef_config_op_t *info = cb_data;
740     ipmi_cmd_info_t *cmd_info = info->cmd_info;
741     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
742 
743     ipmi_cmdlang_lock(cmd_info);
744     if (err) {
745 	ipmi_pef_get_name(pef, cmdlang->objstr,
746 			      cmdlang->objstr_len);
747 	cmdlang->errstr = "Error setting PEF";
748 	cmdlang->err = err;
749 	cmdlang->location = "cmd_pef.c(pef_config_set_done)";
750 	goto out;
751     }
752 
753     ipmi_cmdlang_out(cmd_info, "PEF config set", info->name);
754 
755  out:
756     ipmi_mem_free(info);
757     ipmi_cmdlang_unlock(cmd_info);
758     ipmi_cmdlang_cmd_info_put(cmd_info);
759 }
760 
761 static void
pef_config_set(ipmi_pef_t * pef,void * cb_data)762 pef_config_set(ipmi_pef_t *pef, void *cb_data)
763 {
764     ipmi_cmd_info_t   *cmd_info = cb_data;
765     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
766     int               rv;
767     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
768     int               argc = ipmi_cmdlang_get_argc(cmd_info);
769     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
770     ipmi_pef_config_t *lanc;
771     pef_config_op_t   *info;
772     char              *name;
773 
774     if ((argc - curr_arg) < 1) {
775 	/* Not enough parameters */
776 	cmdlang->errstr = "Not enough parameters";
777 	cmdlang->err = EINVAL;
778 	goto out_err;
779     }
780 
781     name = argv[curr_arg];
782     curr_arg++;
783     lanc = find_config(name, 0);
784     if (!lanc) {
785 	cmdlang->errstr = "Invalid PEF config";
786 	cmdlang->err = EINVAL;
787 	goto out_err;
788     }
789 
790     info = ipmi_mem_alloc(sizeof(*info));
791     if (!info) {
792 	cmdlang->errstr = "Out of memory";
793 	cmdlang->err = ENOMEM;
794 	goto out_err;
795     }
796     info->cmd_info = cmd_info;
797     strncpy(info->name, name, sizeof(info->name) - 1);
798     info->name[sizeof(info->name) - 1] = '\0';
799 
800     ipmi_cmdlang_cmd_info_get(cmd_info);
801     rv = ipmi_pef_set_config(pef, lanc, pef_config_set_done, info);
802     if (rv) {
803 	ipmi_cmdlang_cmd_info_put(cmd_info);
804 	cmdlang->errstr = "Error setting PEF";
805 	cmdlang->err = rv;
806 	ipmi_mem_free(info);
807 	goto out_err;
808     }
809 
810     return;
811 
812  out_err:
813     ipmi_pef_get_name(pef, cmdlang->objstr,
814 			  cmdlang->objstr_len);
815     cmdlang->location = "cmd_pef.c(pef_config_set)";
816 }
817 
818 static void
pef_config_unlock_done(ipmi_pef_t * pef,int err,void * cb_data)819 pef_config_unlock_done(ipmi_pef_t *pef,
820 		       int        err,
821 		       void       *cb_data)
822 {
823     pef_config_op_t *info = cb_data;
824     ipmi_cmd_info_t *cmd_info = info->cmd_info;
825     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
826 
827     ipmi_cmdlang_lock(cmd_info);
828     if (err) {
829 	ipmi_pef_get_name(pef, cmdlang->objstr,
830 			      cmdlang->objstr_len);
831 	cmdlang->errstr = "Error unlocking PEF";
832 	cmdlang->err = err;
833 	cmdlang->location = "cmd_pef.c(pef_config_unlock_done)";
834 	goto out;
835     }
836 
837     ipmi_cmdlang_out(cmd_info, "PEF config unlocked", info->name);
838 
839  out:
840     ipmi_mem_free(info);
841     ipmi_cmdlang_unlock(cmd_info);
842     ipmi_cmdlang_cmd_info_put(cmd_info);
843 }
844 
845 static void
pef_config_unlock(ipmi_pef_t * pef,void * cb_data)846 pef_config_unlock(ipmi_pef_t *pef, void *cb_data)
847 {
848     ipmi_cmd_info_t   *cmd_info = cb_data;
849     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
850     int               rv;
851     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
852     int               argc = ipmi_cmdlang_get_argc(cmd_info);
853     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
854     ipmi_pef_config_t *lanc;
855     pef_config_op_t   *info;
856     char              *name;
857 
858     if ((argc - curr_arg) < 1) {
859 	/* Not enough parameters */
860 	cmdlang->errstr = "Not enough parameters";
861 	cmdlang->err = EINVAL;
862 	goto out_err;
863     }
864 
865     name = argv[curr_arg];
866     curr_arg++;
867     lanc = find_config(name, 0);
868     if (!lanc) {
869 	cmdlang->errstr = "Invalid PEF config";
870 	cmdlang->err = EINVAL;
871 	goto out_err;
872     }
873 
874     info = ipmi_mem_alloc(sizeof(*info));
875     if (!info) {
876 	cmdlang->errstr = "Out of memory";
877 	cmdlang->err = ENOMEM;
878 	goto out_err;
879     }
880     info->cmd_info = cmd_info;
881     strncpy(info->name, name, sizeof(info->name) - 1);
882     info->name[sizeof(info->name) - 1] = '\0';
883 
884     ipmi_cmdlang_cmd_info_get(cmd_info);
885     rv = ipmi_pef_clear_lock(pef, lanc, pef_config_unlock_done, info);
886     if (rv) {
887 	ipmi_cmdlang_cmd_info_put(cmd_info);
888 	cmdlang->errstr = "Error clearing PEF lock";
889 	cmdlang->err = rv;
890 	ipmi_mem_free(info);
891 	goto out_err;
892     }
893 
894     return;
895 
896  out_err:
897     ipmi_pef_get_name(pef, cmdlang->objstr,
898 			  cmdlang->objstr_len);
899     cmdlang->location = "cmd_pef.c(pef_config_unlock)";
900 }
901 
902 static void
pef_config_close(ipmi_cmd_info_t * cmd_info)903 pef_config_close(ipmi_cmd_info_t *cmd_info)
904 {
905     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
906     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
907     int               argc = ipmi_cmdlang_get_argc(cmd_info);
908     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
909     ipmi_pef_config_t *lanc;
910     char              *lanc_name;
911 
912     if ((argc - curr_arg) < 1) {
913 	/* Not enough parameters */
914 	cmdlang->errstr = "Not enough parameters";
915 	cmdlang->err = EINVAL;
916 	lanc_name = "";
917 	goto out_err;
918     }
919     lanc_name = argv[curr_arg];
920 
921     lanc = find_config(lanc_name, 1);
922     if (!lanc) {
923 	cmdlang->errstr = "Invalid PEF config";
924 	cmdlang->err = EINVAL;
925 	goto out_err;
926     }
927 
928     ipmi_pef_free_config(lanc);
929     ipmi_cmdlang_out(cmd_info, "PEF config destroyed", lanc_name);
930     return;
931 
932  out_err:
933     strncpy(cmdlang->objstr, lanc_name, cmdlang->objstr_len);
934     cmdlang->location = "cmd_pef.c(pef_config_close)";
935 }
936 
937 static int
pef_config_list_handler(void * cb_data,void * item1,void * item2)938 pef_config_list_handler(void *cb_data, void *item1, void *item2)
939 {
940     ipmi_cmd_info_t   *cmd_info = cb_data;
941     pef_config_info_t *info = item1;
942 
943     ipmi_cmdlang_out(cmd_info, "Name", info->name);
944     return LOCKED_LIST_ITER_CONTINUE;
945 }
946 
947 static void
pef_config_list(ipmi_cmd_info_t * cmd_info)948 pef_config_list(ipmi_cmd_info_t *cmd_info)
949 {
950     ipmi_cmdlang_out(cmd_info, "PEF Configs", NULL);
951     ipmi_cmdlang_down(cmd_info);
952     locked_list_iterate(pefs, pef_config_list_handler, cmd_info);
953     ipmi_cmdlang_up(cmd_info);
954 }
955 
956 static int
pef_config_info_handler(void * cb_data,void * item1,void * item2)957 pef_config_info_handler(void *cb_data, void *item1, void *item2)
958 {
959     ipmi_cmd_info_t   *cmd_info = cb_data;
960     pef_config_info_t *info = item1;
961 
962     ipmi_cmdlang_out(cmd_info, "PEF Config", NULL);
963     ipmi_cmdlang_down(cmd_info);
964     ipmi_cmdlang_out(cmd_info, "Name", info->name);
965     config_info(cmd_info, info->config);
966     ipmi_cmdlang_up(cmd_info);
967     return LOCKED_LIST_ITER_CONTINUE;
968 }
969 
970 static void
pef_config_info(ipmi_cmd_info_t * cmd_info)971 pef_config_info(ipmi_cmd_info_t *cmd_info)
972 {
973     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
974     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
975     int               argc = ipmi_cmdlang_get_argc(cmd_info);
976     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
977     ipmi_pef_config_t *lanc;
978 
979     if ((argc - curr_arg) < 1) {
980 	locked_list_iterate(pefs, pef_config_info_handler, cmd_info);
981     } else {
982 	lanc = find_config(argv[curr_arg], 0);
983 	if (!lanc) {
984 	    cmdlang->errstr = "Invalid PEF config";
985 	    cmdlang->err = EINVAL;
986 	    goto out_err;
987 	}
988 	ipmi_cmdlang_out(cmd_info, "PEF Config", NULL);
989 	ipmi_cmdlang_down(cmd_info);
990 	ipmi_cmdlang_out(cmd_info, "Name", argv[curr_arg]);
991 	config_info(cmd_info, lanc);
992 	ipmi_cmdlang_up(cmd_info);
993     }
994     return;
995 
996  out_err:
997     strncpy(cmdlang->objstr, argv[curr_arg], cmdlang->objstr_len);
998     cmdlang->location = "cmd_pef.c(pef_config_info)";
999 }
1000 
1001 static void
pef_config_update(ipmi_cmd_info_t * cmd_info)1002 pef_config_update(ipmi_cmd_info_t *cmd_info)
1003 {
1004     ipmi_cmdlang_t    *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
1005     int               curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
1006     int               argc = ipmi_cmdlang_get_argc(cmd_info);
1007     char              **argv = ipmi_cmdlang_get_argv(cmd_info);
1008     ipmi_pef_config_t *lanc;
1009     int               i;
1010     char              *name;
1011     char              *val;
1012     char              *lanc_name;
1013     int               sel;
1014 
1015     if ((argc - curr_arg) < 3) {
1016 	/* Not enough parameters */
1017 	cmdlang->errstr = "Not enough parameters";
1018 	cmdlang->err = EINVAL;
1019 	lanc_name = "";
1020 	goto out_err;
1021     }
1022     lanc_name = argv[curr_arg];
1023     curr_arg++;
1024 
1025     lanc = find_config(lanc_name, 0);
1026     if (!lanc) {
1027 	cmdlang->errstr = "Invalid PEF config";
1028 	cmdlang->err = EINVAL;
1029 	goto out_err;
1030     }
1031 
1032     name = argv[curr_arg];
1033     curr_arg++;
1034     val = argv[curr_arg];
1035     curr_arg++;
1036 
1037     /* Basic items */
1038     for (i=0; lps[i].name; i++) {
1039 	if (strcmp(lps[i].name, name) == 0) {
1040 	    lp_item_t *lp = lps[i].lpi;
1041 	    if (!lp->set) {
1042 		cmdlang->errstr = "Parameter is read-only";
1043 		cmdlang->err = EINVAL;
1044 		goto out_err;
1045 	    }
1046 	    lp->set(cmd_info, val, lanc, lps[i].set_func);
1047 	    goto out;
1048 	}
1049     }
1050 
1051     /* per-event filter items */
1052     for (i=0; elps[i].name; i++) {
1053 	struct ulps_s *lps = elps;
1054 	if (strcmp(lps[i].name, name) == 0) {
1055 	    ulp_item_t *lp = lps[i].lpi;
1056 
1057 	    if ((argc - curr_arg) < 1) {
1058 		/* Not enough parameters */
1059 		cmdlang->errstr = "Not enough parameters";
1060 		cmdlang->err = EINVAL;
1061 		goto out_err;
1062 	    }
1063 	    if (!lp->set) {
1064 		cmdlang->errstr = "Parameter is read-only";
1065 		cmdlang->err = EINVAL;
1066 		goto out_err;
1067 	    }
1068 	    ipmi_cmdlang_get_int(val, &sel, cmd_info);
1069 	    if (cmdlang->err) {
1070 		cmdlang->errstr = "selector invalid";
1071 		goto out_err;
1072 	    }
1073 	    val = argv[curr_arg];
1074 	    curr_arg++;
1075 	    lp->set(cmd_info, sel, val, lanc, lps[i].set_func);
1076 	    goto out;
1077 	}
1078     }
1079 
1080     /* per-event filter items */
1081     for (i=0; plps[i].name; i++) {
1082 	struct ulps_s *lps = plps;
1083 	if (strcmp(lps[i].name, name) == 0) {
1084 	    ulp_item_t *lp = lps[i].lpi;
1085 
1086 	    if ((argc - curr_arg) < 1) {
1087 		/* Not enough parameters */
1088 		cmdlang->errstr = "Not enough parameters";
1089 		cmdlang->err = EINVAL;
1090 		goto out_err;
1091 	    }
1092 	    if (!lp->set) {
1093 		cmdlang->errstr = "Parameter is read-only";
1094 		cmdlang->err = EINVAL;
1095 		goto out_err;
1096 	    }
1097 	    ipmi_cmdlang_get_int(val, &sel, cmd_info);
1098 	    if (cmdlang->err) {
1099 		cmdlang->errstr = "selector invalid";
1100 		goto out_err;
1101 	    }
1102 	    val = argv[curr_arg];
1103 	    curr_arg++;
1104 	    lp->set(cmd_info, sel, val, lanc, lps[i].set_func);
1105 	    goto out;
1106 	}
1107     }
1108 
1109     /* per-event filter items */
1110     for (i=0; slps[i].name; i++) {
1111 	struct ulps_s *lps = slps;
1112 	if (strcmp(lps[i].name, name) == 0) {
1113 	    ulp_item_t *lp = lps[i].lpi;
1114 
1115 	    if ((argc - curr_arg) < 1) {
1116 		/* Not enough parameters */
1117 		cmdlang->errstr = "Not enough parameters";
1118 		cmdlang->err = EINVAL;
1119 		goto out_err;
1120 	    }
1121 	    if (!lp->set) {
1122 		cmdlang->errstr = "Parameter is read-only";
1123 		cmdlang->err = EINVAL;
1124 		goto out_err;
1125 	    }
1126 	    ipmi_cmdlang_get_int(val, &sel, cmd_info);
1127 	    if (cmdlang->err) {
1128 		cmdlang->errstr = "selector invalid";
1129 		goto out_err;
1130 	    }
1131 	    val = argv[curr_arg];
1132 	    curr_arg++;
1133 	    lp->set(cmd_info, sel, val, lanc, lps[i].set_func);
1134 	    goto out;
1135 	}
1136     }
1137 
1138     cmdlang->errstr = "Invalid parameter name";
1139     cmdlang->err = EINVAL;
1140     goto out_err;
1141 
1142  out:
1143     ipmi_cmdlang_out(cmd_info, "PEF config updated", lanc_name);
1144     return;
1145 
1146  out_err:
1147     strncpy(cmdlang->objstr, lanc_name, cmdlang->objstr_len);
1148     cmdlang->location = "cmd_pef.c(pef_config_update)";
1149 }
1150 
1151 typedef struct pet_mc_unlock_s
1152 {
1153     char            name[IPMI_MC_NAME_LEN];
1154     ipmi_cmd_info_t *cmd_info;
1155 } pef_mc_unlock_t;
1156 
1157 static void
pef_unlock_mc_done2(ipmi_pef_t * pef,int err,void * cb_data)1158 pef_unlock_mc_done2(ipmi_pef_t *pef, int err, void *cb_data)
1159 {
1160     pef_mc_unlock_t *info = cb_data;
1161     ipmi_cmd_info_t *cmd_info = info->cmd_info;
1162     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
1163 
1164     ipmi_cmdlang_lock(cmd_info);
1165     if (err) {
1166 	ipmi_pef_get_name(pef, cmdlang->objstr,
1167 			  cmdlang->objstr_len);
1168 	cmdlang->errstr = "Error unlocking MC PEF";
1169 	cmdlang->err = err;
1170 	cmdlang->location = "cmd_pef.c(pef_unlock_mc_done)";
1171 	goto out;
1172     }
1173 
1174     ipmi_cmdlang_out(cmd_info, "PEF unlocked", info->name);
1175 
1176  out:
1177     ipmi_cmdlang_unlock(cmd_info);
1178     ipmi_cmdlang_cmd_info_put(cmd_info);
1179     ipmi_pef_destroy(pef, NULL, NULL);
1180     ipmi_mem_free(info);
1181 }
1182 
1183 static void
pef_unlock_mc_done1(ipmi_pef_t * pef,int err,void * cb_data)1184 pef_unlock_mc_done1(ipmi_pef_t *pef, int err, void *cb_data)
1185 {
1186     pef_mc_unlock_t *info = cb_data;
1187     ipmi_cmd_info_t *cmd_info = info->cmd_info;
1188     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
1189     int             rv;
1190 
1191     if (err) {
1192 	ipmi_cmdlang_lock(cmd_info);
1193 	cmdlang->errstr = "Error unlocking MC PEF";
1194 	cmdlang->err = err;
1195 	cmdlang->location = "cmd_pef.c(pef_unlock_mc_done)";
1196 	ipmi_cmdlang_unlock(cmd_info);
1197 	goto out_err;
1198     }
1199 
1200     rv = ipmi_pef_clear_lock(pef, NULL, pef_unlock_mc_done2, info);
1201     if (rv) {
1202 	ipmi_cmdlang_lock(cmd_info);
1203 	cmdlang->errstr = "Error from ipmi_pef_clear_lock";
1204 	cmdlang->err = rv;
1205 	ipmi_cmdlang_unlock(cmd_info);
1206 	goto out_err;
1207     }
1208     return;
1209 
1210  out_err:
1211     ipmi_pef_destroy(pef, NULL, NULL);
1212     ipmi_cmdlang_cmd_info_put(cmd_info);
1213     ipmi_mem_free(info);
1214 }
1215 
1216 static void
pef_unlock_mc(ipmi_mc_t * mc,void * cb_data)1217 pef_unlock_mc(ipmi_mc_t *mc, void *cb_data)
1218 {
1219     pef_mc_unlock_t *info;
1220     ipmi_cmd_info_t *cmd_info = cb_data;
1221     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
1222     int             rv;
1223 
1224     info = ipmi_mem_alloc(sizeof(*info));
1225     if (!info) {
1226 	cmdlang->errstr = "Out of memory";
1227 	cmdlang->err = ENOMEM;
1228 	goto out_err;
1229     }
1230     info->cmd_info = cmd_info;
1231     ipmi_mc_get_name(mc, info->name, sizeof(info->name));
1232 
1233     ipmi_cmdlang_cmd_info_get(cmd_info);
1234     rv = ipmi_pef_alloc(mc, pef_unlock_mc_done1, info, NULL);
1235     if (rv) {
1236 	ipmi_cmdlang_cmd_info_put(cmd_info);
1237 	cmdlang->errstr = "Error from ipmi_pef_alloc";
1238 	cmdlang->err = rv;
1239 	ipmi_mem_free(info);
1240 	goto out_err;
1241     }
1242     return;
1243 
1244  out_err:
1245     ipmi_mc_get_name(mc, cmdlang->objstr,
1246 		     cmdlang->objstr_len);
1247     cmdlang->location = "cmd_pef.c(pef_unlock_mc)";
1248 }
1249 
1250 static ipmi_cmdlang_cmd_t *pef_cmds;
1251 static ipmi_cmdlang_cmd_t *config_cmds;
1252 
1253 static ipmi_cmdlang_init_t cmds_pef[] =
1254 {
1255     { "pef", NULL,
1256       "- Commands dealing with PEF Parameters (pefs)",
1257       NULL, NULL, &pef_cmds},
1258     { "list", &pef_cmds,
1259       "- List all the pefs in the system",
1260       ipmi_cmdlang_domain_handler, pef_list,  NULL },
1261     { "new", &pef_cmds,
1262       "<mc> - Create a pef for the given MC.",
1263       ipmi_cmdlang_mc_handler, pef_new, NULL },
1264     { "info", &pef_cmds,
1265       "<pef> - Dump information about a pef",
1266       ipmi_cmdlang_pef_handler, pef_info, NULL },
1267     { "config", &pef_cmds,
1268       "- Commands dealing with PEF configs",
1269       NULL, NULL, &config_cmds },
1270     { "list", &config_cmds,
1271       "- List the lan configurations that currently exist",
1272       pef_config_list, NULL, NULL },
1273     { "info", &config_cmds,
1274       "<config> - List info on lan configuration",
1275       pef_config_info, NULL, NULL },
1276     { "get", &config_cmds,
1277       "<pef> - Fetch the PEF information for the pef",
1278       ipmi_cmdlang_pef_handler, pef_config_get, NULL },
1279     { "set", &config_cmds,
1280       "<pef> <pef config> - Set the PEF information for the pef",
1281       ipmi_cmdlang_pef_handler, pef_config_set, NULL },
1282     { "unlock", &config_cmds,
1283       "<pef> <pef config> - Unlock, but do not set the config",
1284       ipmi_cmdlang_pef_handler, pef_config_unlock, NULL },
1285     { "update", &config_cmds,
1286       "<pef config> <parm> [selector] <value> - Set the given parameter"
1287       " in the pef config to the given value.  If the parameter has"
1288       " a selector of some type, the selector must be given, otherwise"
1289       " no selector should be given.",
1290       pef_config_update, NULL, NULL },
1291     { "close", &config_cmds,
1292       "<pef config> - free the config",
1293       pef_config_close, NULL, NULL },
1294     { "unlock_mc", &pef_cmds,
1295       "<mc> - Unlock the pef for the given mc",
1296       ipmi_cmdlang_mc_handler, pef_unlock_mc, NULL },
1297     { "close", &pef_cmds,
1298       "<pef> - Close the pef",
1299       ipmi_cmdlang_pef_handler, pef_close, NULL },
1300 };
1301 #define CMDS_PEF_LEN (sizeof(cmds_pef)/sizeof(ipmi_cmdlang_init_t))
1302 
1303 int
ipmi_cmdlang_pef_init(os_handler_t * os_hnd)1304 ipmi_cmdlang_pef_init(os_handler_t *os_hnd)
1305 {
1306     int rv;
1307 
1308     pefs = locked_list_alloc(os_hnd);
1309     if (!pefs)
1310 	return ENOMEM;
1311 
1312     rv = ipmi_cmdlang_reg_table(cmds_pef, CMDS_PEF_LEN);
1313     if (rv) {
1314 	locked_list_destroy(pefs);
1315 	pefs = NULL;
1316     }
1317 
1318     return rv;
1319 }
1320 
1321 static int
config_destroy_handler(void * cb_data,void * item1,void * item2)1322 config_destroy_handler(void *cb_data, void *item1, void *item2)
1323 {
1324     pef_config_info_t *info = item1;
1325 
1326     ipmi_pef_free_config(info->config);
1327     ipmi_mem_free(info);
1328     return LOCKED_LIST_ITER_CONTINUE;
1329 }
1330 
1331 void
ipmi_cmdlang_pef_shutdown(void)1332 ipmi_cmdlang_pef_shutdown(void)
1333 {
1334     locked_list_iterate(pefs, config_destroy_handler, NULL);
1335     locked_list_destroy(pefs);
1336     pefs = NULL;
1337 }
1338