]> Git Repo - J-u-boot.git/blob - boot/cedit.c
Merge patch series "Add support for MediaTek MT8365 EVK Board"
[J-u-boot.git] / boot / cedit.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Implementation of configuration editor
4  *
5  * Copyright 2023 Google LLC
6  * Written by Simon Glass <[email protected]>
7  */
8
9 #define LOG_CATEGORY LOGC_EXPO
10
11 #include <common.h>
12 #include <abuf.h>
13 #include <cedit.h>
14 #include <cli.h>
15 #include <dm.h>
16 #include <env.h>
17 #include <expo.h>
18 #include <malloc.h>
19 #include <menu.h>
20 #include <rtc.h>
21 #include <video.h>
22 #include <linux/delay.h>
23 #include "scene_internal.h"
24
25 enum {
26         CMOS_MAX_BITS   = 2048,
27         CMOS_MAX_BYTES  = CMOS_MAX_BITS / 8,
28 };
29
30 #define CMOS_BYTE(bit)  ((bit) / 8)
31 #define CMOS_BIT(bit)   ((bit) % 8)
32
33 /**
34  * struct cedit_iter_priv - private data for cedit operations
35  *
36  * @buf: Buffer to use when writing settings to the devicetree
37  * @node: Node to read from when reading settings from devicetree
38  * @verbose: true to show writing to environment variables
39  * @mask: Mask bits for the CMOS RAM. If a bit is set the byte containing it
40  * will be written
41  * @value: Value bits for CMOS RAM. This is the actual value written
42  * @dev: RTC device to write to
43  */
44 struct cedit_iter_priv {
45         struct abuf *buf;
46         ofnode node;
47         bool verbose;
48         u8 *mask;
49         u8 *value;
50         struct udevice *dev;
51 };
52
53 int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
54 {
55         struct scene_obj_txt *txt;
56         struct scene_obj *obj;
57         struct scene *scn;
58         int y;
59
60         scn = expo_lookup_scene_id(exp, scene_id);
61         if (!scn)
62                 return log_msg_ret("scn", -ENOENT);
63
64         txt = scene_obj_find_by_name(scn, "prompt");
65         if (txt)
66                 scene_obj_set_pos(scn, txt->obj.id, 0, vpriv->ysize - 50);
67
68         txt = scene_obj_find_by_name(scn, "title");
69         if (txt)
70                 scene_obj_set_pos(scn, txt->obj.id, 200, 10);
71
72         y = 100;
73         list_for_each_entry(obj, &scn->obj_head, sibling) {
74                 switch (obj->type) {
75                 case SCENEOBJT_NONE:
76                 case SCENEOBJT_IMAGE:
77                 case SCENEOBJT_TEXT:
78                         break;
79                 case SCENEOBJT_MENU:
80                         scene_obj_set_pos(scn, obj->id, 50, y);
81                         scene_menu_arrange(scn, (struct scene_obj_menu *)obj);
82                         y += 50;
83                         break;
84                 case SCENEOBJT_TEXTLINE:
85                         scene_obj_set_pos(scn, obj->id, 50, y);
86                         scene_textline_arrange(scn,
87                                         (struct scene_obj_textline *)obj);
88                         y += 50;
89                         break;
90                 }
91         }
92
93         return 0;
94 }
95
96 int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
97                   struct scene **scnp)
98 {
99         struct video_priv *vid_priv;
100         struct udevice *dev;
101         struct scene *scn;
102         uint scene_id;
103         int ret;
104
105         /* For now we only support a video console */
106         ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
107         if (ret)
108                 return log_msg_ret("vid", ret);
109         ret = expo_set_display(exp, dev);
110         if (ret)
111                 return log_msg_ret("dis", ret);
112
113         ret = expo_first_scene_id(exp);
114         if (ret < 0)
115                 return log_msg_ret("scn", ret);
116         scene_id = ret;
117
118         ret = expo_set_scene_id(exp, scene_id);
119         if (ret)
120                 return log_msg_ret("sid", ret);
121
122         exp->popup = true;
123
124         /* This is not supported for now */
125         if (0)
126                 expo_set_text_mode(exp, true);
127
128         vid_priv = dev_get_uclass_priv(dev);
129
130         scn = expo_lookup_scene_id(exp, scene_id);
131         scene_highlight_first(scn);
132
133         cedit_arange(exp, vid_priv, scene_id);
134
135         ret = expo_calc_dims(exp);
136         if (ret)
137                 return log_msg_ret("dim", ret);
138
139         *vid_privp = vid_priv;
140         *scnp = scn;
141
142         return scene_id;
143 }
144
145 int cedit_run(struct expo *exp)
146 {
147         struct cli_ch_state s_cch, *cch = &s_cch;
148         struct video_priv *vid_priv;
149         uint scene_id;
150         struct scene *scn;
151         bool done;
152         int ret;
153
154         cli_ch_init(cch);
155         ret = cedit_prepare(exp, &vid_priv, &scn);
156         if (ret < 0)
157                 return log_msg_ret("prep", ret);
158         scene_id = ret;
159
160         done = false;
161         do {
162                 struct expo_action act;
163                 int ichar, key;
164
165                 ret = expo_render(exp);
166                 if (ret)
167                         break;
168
169                 ichar = cli_ch_process(cch, 0);
170                 if (!ichar) {
171                         while (!ichar && !tstc()) {
172                                 schedule();
173                                 mdelay(2);
174                                 ichar = cli_ch_process(cch, -ETIMEDOUT);
175                         }
176                         if (!ichar) {
177                                 ichar = getchar();
178                                 ichar = cli_ch_process(cch, ichar);
179                         }
180                 }
181
182                 key = 0;
183                 if (ichar) {
184                         key = bootmenu_conv_key(ichar);
185                         if (key == BKEY_NONE || key >= BKEY_FIRST_EXTRA)
186                                 key = ichar;
187                 }
188                 if (!key)
189                         continue;
190
191                 ret = expo_send_key(exp, key);
192                 if (ret)
193                         break;
194
195                 ret = expo_action_get(exp, &act);
196                 if (!ret) {
197                         switch (act.type) {
198                         case EXPOACT_POINT_OBJ:
199                                 scene_set_highlight_id(scn, act.select.id);
200                                 cedit_arange(exp, vid_priv, scene_id);
201                                 break;
202                         case EXPOACT_OPEN:
203                                 scene_set_open(scn, act.select.id, true);
204                                 cedit_arange(exp, vid_priv, scene_id);
205                                 break;
206                         case EXPOACT_CLOSE:
207                                 scene_set_open(scn, act.select.id, false);
208                                 cedit_arange(exp, vid_priv, scene_id);
209                                 break;
210                         case EXPOACT_SELECT:
211                                 scene_set_open(scn, scn->highlight_id, false);
212                                 cedit_arange(exp, vid_priv, scene_id);
213                                 break;
214                         case EXPOACT_QUIT:
215                                 log_debug("quitting\n");
216                                 done = true;
217                                 break;
218                         default:
219                                 break;
220                         }
221                 }
222         } while (!done);
223
224         if (ret)
225                 return log_msg_ret("end", ret);
226
227         return 0;
228 }
229
230 static int check_space(int ret, struct abuf *buf)
231 {
232         if (ret == -FDT_ERR_NOSPACE) {
233                 if (!abuf_realloc_inc(buf, CEDIT_SIZE_INC))
234                         return log_msg_ret("spc", -ENOMEM);
235                 ret = fdt_resize(abuf_data(buf), abuf_data(buf),
236                                  abuf_size(buf));
237                 if (ret)
238                         return log_msg_ret("res", -EFAULT);
239         }
240
241         return 0;
242 }
243
244 /**
245  * get_cur_menuitem_text() - Get the text of the currently selected item
246  *
247  * Looks up the object for the current item, finds text object for it and looks
248  * up the string for that text
249  *
250  * @menu: Menu to look at
251  * @strp: Returns a pointer to the next
252  * Return: 0 if OK, -ENOENT if something was not found
253  */
254 static int get_cur_menuitem_text(const struct scene_obj_menu *menu,
255                                  const char **strp)
256 {
257         struct scene *scn = menu->obj.scene;
258         const struct scene_menitem *mi;
259         const struct scene_obj_txt *txt;
260         const char *str;
261
262         mi = scene_menuitem_find(menu, menu->cur_item_id);
263         if (!mi)
264                 return log_msg_ret("mi", -ENOENT);
265
266         txt = scene_obj_find(scn, mi->label_id, SCENEOBJT_TEXT);
267         if (!txt)
268                 return log_msg_ret("txt", -ENOENT);
269
270         str = expo_get_str(scn->expo, txt->str_id);
271         if (!str)
272                 return log_msg_ret("str", -ENOENT);
273         *strp = str;
274
275         return 0;
276 }
277
278 static int write_dt_string(struct abuf *buf, const char *name, const char *str)
279 {
280         int ret, i;
281
282         /* write the text of the current item */
283         ret = -EAGAIN;
284         for (i = 0; ret && i < 2; i++) {
285                 ret = fdt_property_string(abuf_data(buf), name, str);
286                 if (!i) {
287                         ret = check_space(ret, buf);
288                         if (ret)
289                                 return log_msg_ret("rs2", -ENOMEM);
290                 }
291         }
292
293         /* this should not happen */
294         if (ret)
295                 return log_msg_ret("str", -EFAULT);
296
297         return 0;
298 }
299
300 static int h_write_settings(struct scene_obj *obj, void *vpriv)
301 {
302         struct cedit_iter_priv *priv = vpriv;
303         struct abuf *buf = priv->buf;
304         int ret;
305
306         switch (obj->type) {
307         case SCENEOBJT_NONE:
308         case SCENEOBJT_IMAGE:
309         case SCENEOBJT_TEXT:
310                 break;
311         case SCENEOBJT_TEXTLINE: {
312                 const struct scene_obj_textline *tline;
313
314                 tline = (struct scene_obj_textline *)obj;
315                 ret = write_dt_string(buf, obj->name, abuf_data(&tline->buf));
316                 if (ret)
317                         return log_msg_ret("wr2", ret);
318                 break;
319         }
320         case SCENEOBJT_MENU: {
321                 const struct scene_obj_menu *menu;
322                 const char *str;
323                 char name[80];
324                 int i;
325
326                 /* write the ID of the current item */
327                 menu = (struct scene_obj_menu *)obj;
328                 ret = -EAGAIN;
329                 for (i = 0; ret && i < 2; i++) {
330                         ret = fdt_property_u32(abuf_data(buf), obj->name,
331                                                menu->cur_item_id);
332                         if (!i) {
333                                 ret = check_space(ret, buf);
334                                 if (ret)
335                                         return log_msg_ret("res", -ENOMEM);
336                         }
337                 }
338                 /* this should not happen */
339                 if (ret)
340                         return log_msg_ret("wrt", -EFAULT);
341
342                 ret = get_cur_menuitem_text(menu, &str);
343                 if (ret)
344                         return log_msg_ret("mis", ret);
345
346                 /* write the text of the current item */
347                 snprintf(name, sizeof(name), "%s-str", obj->name);
348                 ret = write_dt_string(buf, name, str);
349                 if (ret)
350                         return log_msg_ret("wr2", ret);
351
352                 break;
353         }
354         }
355
356         return 0;
357 }
358
359 int cedit_write_settings(struct expo *exp, struct abuf *buf)
360 {
361         struct cedit_iter_priv priv;
362         void *fdt;
363         int ret;
364
365         abuf_init(buf);
366         if (!abuf_realloc(buf, CEDIT_SIZE_INC))
367                 return log_msg_ret("buf", -ENOMEM);
368
369         fdt = abuf_data(buf);
370         ret = fdt_create(fdt, abuf_size(buf));
371         if (!ret)
372                 ret = fdt_finish_reservemap(fdt);
373         if (!ret)
374                 ret = fdt_begin_node(fdt, "");
375         if (!ret)
376                 ret = fdt_begin_node(fdt, CEDIT_NODE_NAME);
377         if (ret) {
378                 log_debug("Failed to start FDT (err=%d)\n", ret);
379                 return log_msg_ret("sta", -EINVAL);
380         }
381
382         /* write out the items */
383         priv.buf = buf;
384         ret = expo_iter_scene_objs(exp, h_write_settings, &priv);
385         if (ret) {
386                 log_debug("Failed to write settings (err=%d)\n", ret);
387                 return log_msg_ret("set", ret);
388         }
389
390         ret = fdt_end_node(fdt);
391         if (!ret)
392                 ret = fdt_end_node(fdt);
393         if (!ret)
394                 ret = fdt_finish(fdt);
395         if (ret) {
396                 log_debug("Failed to finish FDT (err=%d)\n", ret);
397                 return log_msg_ret("fin", -EINVAL);
398         }
399
400         return 0;
401 }
402
403 static int h_read_settings(struct scene_obj *obj, void *vpriv)
404 {
405         struct cedit_iter_priv *priv = vpriv;
406         ofnode node = priv->node;
407
408         switch (obj->type) {
409         case SCENEOBJT_NONE:
410         case SCENEOBJT_IMAGE:
411         case SCENEOBJT_TEXT:
412                 break;
413         case SCENEOBJT_TEXTLINE: {
414                 const struct scene_obj_textline *tline;
415                 const char *val;
416                 int len;
417
418                 tline = (struct scene_obj_textline *)obj;
419
420                 val = ofnode_read_prop(node, obj->name, &len);
421                 if (len >= tline->max_chars)
422                         return log_msg_ret("str", -ENOSPC);
423                 strcpy(abuf_data(&tline->buf), val);
424                 break;
425         }
426         case SCENEOBJT_MENU: {
427                 struct scene_obj_menu *menu;
428                 uint val;
429
430                 if (ofnode_read_u32(node, obj->name, &val))
431                         return log_msg_ret("rd", -ENOENT);
432                 menu = (struct scene_obj_menu *)obj;
433                 menu->cur_item_id = val;
434
435                 break;
436         }
437         }
438
439         return 0;
440 }
441
442 int cedit_read_settings(struct expo *exp, oftree tree)
443 {
444         struct cedit_iter_priv priv;
445         ofnode root, node;
446         int ret;
447
448         root = oftree_root(tree);
449         if (!ofnode_valid(root))
450                 return log_msg_ret("roo", -ENOENT);
451         node = ofnode_find_subnode(root, CEDIT_NODE_NAME);
452         if (!ofnode_valid(node))
453                 return log_msg_ret("pat", -ENOENT);
454
455         /* read in the items */
456         priv.node = node;
457         ret = expo_iter_scene_objs(exp, h_read_settings, &priv);
458         if (ret) {
459                 log_debug("Failed to read settings (err=%d)\n", ret);
460                 return log_msg_ret("set", ret);
461         }
462
463         return 0;
464 }
465
466 static int h_write_settings_env(struct scene_obj *obj, void *vpriv)
467 {
468         const struct scene_obj_menu *menu;
469         struct cedit_iter_priv *priv = vpriv;
470         char name[80], var[60];
471         const char *str;
472         int val, ret;
473
474         snprintf(var, sizeof(var), "c.%s", obj->name);
475
476         switch (obj->type) {
477         case SCENEOBJT_NONE:
478         case SCENEOBJT_IMAGE:
479         case SCENEOBJT_TEXT:
480                 break;
481         case SCENEOBJT_MENU:
482                 menu = (struct scene_obj_menu *)obj;
483                 val = menu->cur_item_id;
484
485                 if (priv->verbose)
486                         printf("%s=%d\n", var, val);
487
488                 ret = env_set_ulong(var, val);
489                 if (ret)
490                         return log_msg_ret("set", ret);
491
492                 ret = get_cur_menuitem_text(menu, &str);
493                 if (ret)
494                         return log_msg_ret("mis", ret);
495
496                 snprintf(name, sizeof(name), "c.%s-str", obj->name);
497                 if (priv->verbose)
498                         printf("%s=%s\n", name, str);
499
500                 ret = env_set(name, str);
501                 if (ret)
502                         return log_msg_ret("st2", ret);
503                 break;
504         case SCENEOBJT_TEXTLINE: {
505                 const struct scene_obj_textline *tline;
506
507                 tline = (struct scene_obj_textline *)obj;
508                 str = abuf_data(&tline->buf);
509                 ret = env_set(var, str);
510                 if (ret)
511                         return log_msg_ret("set", ret);
512
513                 if (priv->verbose)
514                         printf("%s=%s\n", var, str);
515
516                 break;
517         }
518         }
519
520         return 0;
521 }
522
523 int cedit_write_settings_env(struct expo *exp, bool verbose)
524 {
525         struct cedit_iter_priv priv;
526         int ret;
527
528         /* write out the items */
529         priv.verbose = verbose;
530         ret = expo_iter_scene_objs(exp, h_write_settings_env, &priv);
531         if (ret) {
532                 log_debug("Failed to write settings to env (err=%d)\n", ret);
533                 return log_msg_ret("set", ret);
534         }
535
536         return 0;
537 }
538
539 static int h_read_settings_env(struct scene_obj *obj, void *vpriv)
540 {
541         struct cedit_iter_priv *priv = vpriv;
542         struct scene_obj_menu *menu;
543         char var[60];
544         int val;
545
546         snprintf(var, sizeof(var), "c.%s", obj->name);
547
548         switch (obj->type) {
549         case SCENEOBJT_NONE:
550         case SCENEOBJT_IMAGE:
551         case SCENEOBJT_TEXT:
552                 break;
553         case SCENEOBJT_MENU:
554                 menu = (struct scene_obj_menu *)obj;
555                 val = env_get_ulong(var, 10, 0);
556                 if (priv->verbose)
557                         printf("%s=%d\n", var, val);
558                 if (!val)
559                         return log_msg_ret("get", -ENOENT);
560
561                 /*
562                  * note that no validation is done here, to make sure the ID is
563                  * valid * and actually points to a menu item
564                  */
565                 menu->cur_item_id = val;
566                 break;
567         case SCENEOBJT_TEXTLINE: {
568                 const struct scene_obj_textline *tline;
569                 const char *value;
570
571                 tline = (struct scene_obj_textline *)obj;
572                 value = env_get(var);
573                 if (value && strlen(value) >= tline->max_chars)
574                         return log_msg_ret("str", -ENOSPC);
575                 if (!value)
576                         value = "";
577                 if (priv->verbose)
578                         printf("%s=%s\n", var, value);
579                 strcpy(abuf_data(&tline->buf), value);
580                 break;
581         }
582         }
583
584         return 0;
585 }
586
587 int cedit_read_settings_env(struct expo *exp, bool verbose)
588 {
589         struct cedit_iter_priv priv;
590         int ret;
591
592         /* write out the items */
593         priv.verbose = verbose;
594         ret = expo_iter_scene_objs(exp, h_read_settings_env, &priv);
595         if (ret) {
596                 log_debug("Failed to read settings from env (err=%d)\n", ret);
597                 return log_msg_ret("set", ret);
598         }
599
600         return 0;
601 }
602
603 /**
604  * get_cur_menuitem_seq() - Get the sequence number of a menu's current item
605  *
606  * Enumerates the items of a menu (0, 1, 2) and returns the sequence number of
607  * the currently selected item. If the first item is selected, this returns 0;
608  * if the second, 1; etc.
609  *
610  * @menu: Menu to check
611  * Return: Sequence number on success, else -ve error value
612  */
613 static int get_cur_menuitem_seq(const struct scene_obj_menu *menu)
614 {
615         const struct scene_menitem *mi;
616         int seq, found;
617
618         seq = 0;
619         found = -1;
620         list_for_each_entry(mi, &menu->item_head, sibling) {
621                 if (mi->id == menu->cur_item_id) {
622                         found = seq;
623                         break;
624                 }
625                 seq++;
626         }
627
628         if (found == -1)
629                 return log_msg_ret("nf", -ENOENT);
630
631         return found;
632 }
633
634 static int h_write_settings_cmos(struct scene_obj *obj, void *vpriv)
635 {
636         const struct scene_obj_menu *menu;
637         struct cedit_iter_priv *priv = vpriv;
638         int val, ret;
639         uint i, seq;
640
641         if (obj->type != SCENEOBJT_MENU)
642                 return 0;
643
644         menu = (struct scene_obj_menu *)obj;
645         val = menu->cur_item_id;
646
647         ret = get_cur_menuitem_seq(menu);
648         if (ret < 0)
649                 return log_msg_ret("cur", ret);
650         seq = ret;
651         log_debug("%s: seq=%d\n", menu->obj.name, seq);
652
653         /* figure out where to place this item */
654         if (!obj->bit_length)
655                 return log_msg_ret("len", -EINVAL);
656         if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS)
657                 return log_msg_ret("bit", -E2BIG);
658
659         for (i = 0; i < obj->bit_length; i++, seq >>= 1) {
660                 uint bitnum = obj->start_bit + i;
661
662                 priv->mask[CMOS_BYTE(bitnum)] |= 1 << CMOS_BIT(bitnum);
663                 if (seq & 1)
664                         priv->value[CMOS_BYTE(bitnum)] |= BIT(CMOS_BIT(bitnum));
665                 log_debug("bit %x %x %x\n", bitnum,
666                           priv->mask[CMOS_BYTE(bitnum)],
667                           priv->value[CMOS_BYTE(bitnum)]);
668         }
669
670         return 0;
671 }
672
673 int cedit_write_settings_cmos(struct expo *exp, struct udevice *dev,
674                               bool verbose)
675 {
676         struct cedit_iter_priv priv;
677         int ret, i, count, first, last;
678
679         /* write out the items */
680         priv.mask = calloc(1, CMOS_MAX_BYTES);
681         if (!priv.mask)
682                 return log_msg_ret("mas", -ENOMEM);
683         priv.value = calloc(1, CMOS_MAX_BYTES);
684         if (!priv.value) {
685                 free(priv.mask);
686                 return log_msg_ret("val", -ENOMEM);
687         }
688
689         ret = expo_iter_scene_objs(exp, h_write_settings_cmos, &priv);
690         if (ret) {
691                 log_debug("Failed to write CMOS (err=%d)\n", ret);
692                 ret = log_msg_ret("set", ret);
693                 goto done;
694         }
695
696         /* write the data to the RTC */
697         first = CMOS_MAX_BYTES;
698         last = -1;
699         for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {
700                 if (priv.mask[i]) {
701                         log_debug("Write byte %x: %x\n", i, priv.value[i]);
702                         ret = rtc_write8(dev, i, priv.value[i]);
703                         if (ret) {
704                                 ret = log_msg_ret("wri", ret);
705                                 goto done;
706                         }
707                         count++;
708                         first = min(first, i);
709                         last = max(last, i);
710                 }
711         }
712         if (verbose) {
713                 printf("Write %d bytes from offset %x to %x\n", count, first,
714                        last);
715         }
716
717 done:
718         free(priv.mask);
719         free(priv.value);
720         return ret;
721 }
722
723 static int h_read_settings_cmos(struct scene_obj *obj, void *vpriv)
724 {
725         struct cedit_iter_priv *priv = vpriv;
726         const struct scene_menitem *mi;
727         struct scene_obj_menu *menu;
728         int val, ret;
729         uint i;
730
731         if (obj->type != SCENEOBJT_MENU)
732                 return 0;
733
734         menu = (struct scene_obj_menu *)obj;
735
736         /* figure out where to place this item */
737         if (!obj->bit_length)
738                 return log_msg_ret("len", -EINVAL);
739         if (obj->start_bit + obj->bit_length > CMOS_MAX_BITS)
740                 return log_msg_ret("bit", -E2BIG);
741
742         val = 0;
743         for (i = 0; i < obj->bit_length; i++) {
744                 uint bitnum = obj->start_bit + i;
745                 uint offset = CMOS_BYTE(bitnum);
746
747                 /* read the byte if not already read */
748                 if (!priv->mask[offset]) {
749                         ret = rtc_read8(priv->dev, offset);
750                         if (ret < 0)
751                                 return  log_msg_ret("rea", ret);
752                         priv->value[offset] = ret;
753
754                         /* mark it as read */
755                         priv->mask[offset] = 0xff;
756                 }
757
758                 if (priv->value[offset] & BIT(CMOS_BIT(bitnum)))
759                         val |= BIT(i);
760                 log_debug("bit %x %x\n", bitnum, val);
761         }
762
763         /* update the current item */
764         mi = scene_menuitem_find_seq(menu, val);
765         if (!mi)
766                 return log_msg_ret("seq", -ENOENT);
767
768         menu->cur_item_id = mi->id;
769         log_debug("Update menu %d cur_item_id %d\n", menu->obj.id, mi->id);
770
771         return 0;
772 }
773
774 int cedit_read_settings_cmos(struct expo *exp, struct udevice *dev,
775                              bool verbose)
776 {
777         struct cedit_iter_priv priv;
778         int ret, i, count, first, last;
779
780         /* read in the items */
781         priv.mask = calloc(1, CMOS_MAX_BYTES);
782         if (!priv.mask)
783                 return log_msg_ret("mas", -ENOMEM);
784         priv.value = calloc(1, CMOS_MAX_BYTES);
785         if (!priv.value) {
786                 free(priv.mask);
787                 return log_msg_ret("val", -ENOMEM);
788         }
789         priv.dev = dev;
790
791         ret = expo_iter_scene_objs(exp, h_read_settings_cmos, &priv);
792         if (ret) {
793                 log_debug("Failed to read CMOS (err=%d)\n", ret);
794                 ret = log_msg_ret("set", ret);
795                 goto done;
796         }
797
798         /* read the data to the RTC */
799         first = CMOS_MAX_BYTES;
800         last = -1;
801         for (i = 0, count = 0; i < CMOS_MAX_BYTES; i++) {
802                 if (priv.mask[i]) {
803                         log_debug("Read byte %x: %x\n", i, priv.value[i]);
804                         count++;
805                         first = min(first, i);
806                         last = max(last, i);
807                 }
808         }
809         if (verbose) {
810                 printf("Read %d bytes from offset %x to %x\n", count, first,
811                        last);
812         }
813
814 done:
815         free(priv.mask);
816         free(priv.value);
817         return ret;
818 }
This page took 0.074899 seconds and 4 git commands to generate.