coreboot: Changed cbmemc to support updated console format from coreboot.
[grub.git] / grub-core / term / i386 / coreboot / cbmemc.c
1 /*
2  *  GRUB  --  GRand Unified Bootloader
3  *  Copyright (C) 2013  Free Software Foundation, Inc.
4  *
5  *  GRUB is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  GRUB is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <grub/term.h>
20 #include <grub/types.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/time.h>
24 #include <grub/terminfo.h>
25 #include <grub/dl.h>
26 #include <grub/coreboot/lbio.h>
27 #include <grub/command.h>
28 #include <grub/normal.h>
29
30 GRUB_MOD_LICENSE ("GPLv3+");
31
32 #define CURSOR_MASK ((1 << 28) - 1)
33 #define OVERFLOW (1 << 31)
34
35 struct grub_linuxbios_cbmemc
36 {
37   grub_uint32_t size;
38   grub_uint32_t cursor;
39   char body[0];
40 };
41
42 static struct grub_linuxbios_cbmemc *cbmemc;
43
44 static void
45 put (struct grub_term_output *term __attribute__ ((unused)), const int c)
46 {
47   grub_uint32_t flags, cursor;
48   if (!cbmemc)
49     return;
50   flags = cbmemc->cursor & ~CURSOR_MASK;
51   cursor = cbmemc->cursor & CURSOR_MASK;
52   if (cursor >= cbmemc->size)
53     return;
54   cbmemc->body[cursor++] = c;
55   if (cursor >= cbmemc->size)
56     {
57       cursor = 0;
58       flags |= OVERFLOW;
59     }
60   cbmemc->cursor = flags | cursor;
61 }
62
63 struct grub_terminfo_output_state grub_cbmemc_terminfo_output =
64   {
65     .put = put,
66     .size = { 80, 24 }
67   };
68
69 static struct grub_term_output grub_cbmemc_term_output =
70   {
71     .name = "cbmemc",
72     .init = grub_terminfo_output_init,
73     .fini = 0,
74     .putchar = grub_terminfo_putchar,
75     .getxy = grub_terminfo_getxy,
76     .getwh = grub_terminfo_getwh,
77     .gotoxy = grub_terminfo_gotoxy,
78     .cls = grub_terminfo_cls,
79     .setcolorstate = grub_terminfo_setcolorstate,
80     .setcursor = grub_terminfo_setcursor,
81     .flags = GRUB_TERM_CODE_TYPE_ASCII,
82     .data = &grub_cbmemc_terminfo_output,
83     .progress_update_divisor = GRUB_PROGRESS_NO_UPDATE
84   };
85
86 static int
87 iterate_linuxbios_table (grub_linuxbios_table_item_t table_item,
88                          void *data __attribute__ ((unused)))
89 {
90   if (table_item->tag != GRUB_LINUXBIOS_MEMBER_CBMEMC)
91     return 0;
92   cbmemc = (struct grub_linuxbios_cbmemc *) (grub_addr_t)
93     *(grub_uint64_t *) (table_item + 1);
94   return 1;
95 }
96
97 static grub_err_t
98 grub_cmd_cbmemc (struct grub_command *cmd __attribute__ ((unused)),
99                  int argc __attribute__ ((unused)),
100                  char *argv[] __attribute__ ((unused)))
101 {
102   grub_size_t size, cursor;
103   struct grub_linuxbios_cbmemc *real_cbmemc;
104
105   if (!cbmemc)
106     return grub_error (GRUB_ERR_IO, "no CBMEM console found");
107
108   real_cbmemc = cbmemc;
109   cbmemc = 0;
110   cursor = real_cbmemc->cursor & CURSOR_MASK;
111   if (!(real_cbmemc->cursor & OVERFLOW) && cursor < real_cbmemc->size)
112     size = cursor;
113   else
114     size = real_cbmemc->size;
115   if (real_cbmemc->cursor & OVERFLOW)
116     {
117       if (cursor > size)
118         cursor = 0;
119       grub_xnputs(real_cbmemc->body + cursor, size - cursor);
120       grub_xnputs(real_cbmemc->body, cursor);
121     }
122   else
123     grub_xnputs(real_cbmemc->body, size);
124   cbmemc = real_cbmemc;
125   return 0;
126 }
127
128 static grub_command_t cmd;
129
130 GRUB_MOD_INIT (cbmemc)
131 {
132   grub_linuxbios_table_iterate (iterate_linuxbios_table, 0);
133
134   if (cbmemc)
135     grub_term_register_output ("cbmemc", &grub_cbmemc_term_output);
136
137   cmd =
138     grub_register_command ("cbmemc", grub_cmd_cbmemc,
139                            0, N_("Show CBMEM console content."));
140 }
141
142
143 GRUB_MOD_FINI (cbmemc)
144 {
145   grub_term_unregister_output (&grub_cbmemc_term_output);
146   grub_unregister_command (cmd);
147 }