libpayload: Provide interpretation of CMOS data structures
[coreboot.git] / payloads / coreinfo / cbfs_module.c
1 /*
2  * This file is part of the coreinfo project.
3  *
4  * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program 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 this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #include "coreinfo.h"
21 #include "arch/endian.h"
22
23 #ifdef CONFIG_MODULE_CBFS
24
25 #define ALIGN(_v, _a) (((_v) + ((_a) - 1)) & ~((_a) - 1))
26
27 #define HEADER_MAGIC            0x4F524243
28 #define HEADER_ADDR             0xfffffffc
29 #define LARCHIVE_MAGIC          0x455649484352414cLL    /* "LARCHIVE" */
30
31 #define COMPONENT_DELETED       0x00
32 #define COMPONENT_STAGE         0x10
33 #define COMPONENT_PAYLOAD       0x20
34 #define COMPONENT_OPTIONROM     0x30
35 #define COMPONENT_NULL          0xffffffff
36
37 struct cbheader {
38         u32 magic;
39         u32 version;
40         u32 romsize;
41         u32 bootblocksize;
42         u32 align;
43         u32 offset;
44         u32 pad[2];
45 } __attribute__ ((packed));
46
47 struct cbfile {
48         u64 magic;
49         u32 len;
50         u32 type;
51         u32 checksum;
52         u32 offset;
53         char filename[0];
54 } __attribute__ ((packed));
55
56 static int filecount = 0, selected = 0;
57 static char **filenames;
58 static struct cbheader *header = NULL;
59
60 static struct cbfile *getfile(struct cbfile *f)
61 {
62         while (1) {
63                 if (f < (struct cbfile *)(0xffffffff - ntohl(header->romsize)))
64                         return NULL;
65                 if (f->magic == 0)
66                         return NULL;
67                 if (f->magic == LARCHIVE_MAGIC)
68                         return f;
69                 f = (void *)f + ntohl(header->align);
70         }
71 }
72
73 static struct cbfile *firstfile(void)
74 {
75         return getfile((void *)(0 - ntohl(header->romsize) +
76                                 ntohl(header->offset)));
77 }
78
79 static struct cbfile *nextfile(struct cbfile *f)
80 {
81         f = (void *)f + ALIGN(ntohl(f->len) + ntohl(f->offset),
82                               ntohl(header->align));
83         return getfile(f);
84 }
85
86 static struct cbfile *findfile(const char *filename)
87 {
88         struct cbfile *f;
89         for (f = firstfile(); f; f = nextfile(f)) {
90                 if (strcmp(filename, f->filename) == 0)
91                         return f;
92         }
93         return NULL;
94 }
95
96 static int cbfs_module_init(void)
97 {
98         struct cbfile *f;
99         int index = 0;
100
101         header = *(void **)HEADER_ADDR;
102         if (header->magic != ntohl(HEADER_MAGIC)) {
103                 header = NULL;
104                 return 0;
105         }
106
107         for (f = firstfile(); f; f = nextfile(f))
108                 filecount++;
109
110         filenames = malloc(filecount * sizeof(char *));
111         if (filenames == NULL)
112                 return 0;
113
114         for (f = firstfile(); f; f = nextfile(f))
115                 filenames[index++] = strdup((const char *)f->filename);
116
117         return 0;
118 }
119
120 static int cbfs_module_redraw(WINDOW * win)
121 {
122         struct cbfile *f;
123         int i, row = 2;
124
125         print_module_title(win, "CBFS Listing");
126
127         if (!header) {
128                 mvwprintw(win, 11, 61 / 2, "Bad or missing CBFS header");
129                 return 0;
130         }
131
132         /* Draw a line down the middle. */
133         for (i = 2; i < 21; i++)
134                 mvwaddch(win, i, 30, ACS_VLINE);
135
136         /* Draw the names down the left side. */
137         for (i = 0; i < filecount; i++) {
138                 if (i == selected)
139                         wattrset(win, COLOR_PAIR(3) | A_BOLD);
140                 else
141                         wattrset(win, COLOR_PAIR(2));
142                 if (i == filecount - 1)
143                         mvwprintw(win, 2 + i, 1, "<free space>");
144                 else
145                         mvwprintw(win, 2 + i, 1, "%.25s", filenames[i]);
146         }
147
148         f = findfile(filenames[selected]);
149         if (!f) {
150                 mvwprintw(win, 11, 32, "ERROR: CBFS component not found");
151                 return 0;
152         }
153
154         wattrset(win, COLOR_PAIR(2));
155
156         /* mvwprintw(win, row++, 32, "Offset: 0x%x", f->offset); *//* FIXME */
157         mvwprintw(win, row, 32, "Type: ");
158         switch (ntohl(f->type)) {
159         case COMPONENT_STAGE:
160                 mvwprintw(win, row++, 38, "stage");
161                 break;
162         case COMPONENT_PAYLOAD:
163                 mvwprintw(win, row++, 38, "payload");
164                 break;
165         case COMPONENT_OPTIONROM:
166                 mvwprintw(win, row++, 38, "optionrom");
167                 break;
168         case COMPONENT_NULL:
169                 mvwprintw(win, row++, 38, "free");
170                 break;
171         case COMPONENT_DELETED:
172                 mvwprintw(win, row++, 38, "deleted");
173                 break;
174         default:
175                 mvwprintw(win, row++, 38, "Unknown (0x%x)", ntohl(f->type));
176                 break;
177         }
178         mvwprintw(win, row++, 32, "Size: %d", ntohl(f->len));
179         mvwprintw(win, row++, 32, "Checksum: 0x%x", ntohl(f->checksum));
180
181         return 0;
182 }
183
184 static int cbfs_module_handle(int key)
185 {
186         int ret = 0;
187
188         if (filecount == 0)
189                 return 0;
190
191         switch (key) {
192         case KEY_DOWN:
193                 if (selected + 1 < filecount) {
194                         selected++;
195                         ret = 1;
196                 }
197                 break;
198         case KEY_UP:
199                 if (selected > 0) {
200                         selected--;
201                         ret = 1;
202                 }
203                 break;
204         }
205
206         return ret;
207 }
208
209 struct coreinfo_module cbfs_module = {
210         .name = "CBFS",
211         .init = cbfs_module_init,
212         .redraw = cbfs_module_redraw,
213         .handle = cbfs_module_handle
214 };
215
216 #else
217
218 struct coreinfo_module cbfs_module = {
219 };
220
221 #endif