blob: a5ddc531710cdafb2916ad72a133a512574be23d [file] [log] [blame]
Uwe Hermann941c1fd2009-07-07 15:10:13 +00001/*
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.
Uwe Hermann941c1fd2009-07-07 15:10:13 +000014 */
15
16#include "coreinfo.h"
Gabe Black0af03d22012-03-19 03:06:46 -070017#include "endian.h"
Uwe Hermann941c1fd2009-07-07 15:10:13 +000018
Stefan Reinauer04fb7a82015-06-29 16:08:39 -070019#if IS_ENABLED(CONFIG_MODULE_CBFS)
Uwe Hermann941c1fd2009-07-07 15:10:13 +000020
Uwe Hermann941c1fd2009-07-07 15:10:13 +000021#define HEADER_MAGIC 0x4F524243
22#define HEADER_ADDR 0xfffffffc
23#define LARCHIVE_MAGIC 0x455649484352414cLL /* "LARCHIVE" */
24
25#define COMPONENT_DELETED 0x00
26#define COMPONENT_STAGE 0x10
27#define COMPONENT_PAYLOAD 0x20
28#define COMPONENT_OPTIONROM 0x30
29#define COMPONENT_NULL 0xffffffff
30
31struct cbheader {
32 u32 magic;
33 u32 version;
34 u32 romsize;
35 u32 bootblocksize;
36 u32 align;
37 u32 offset;
David Hendricks90ca3b62012-11-16 14:48:22 -080038 u32 architecture;
39 u32 pad[1];
Uwe Hermann941c1fd2009-07-07 15:10:13 +000040} __attribute__ ((packed));
41
42struct cbfile {
43 u64 magic;
44 u32 len;
45 u32 type;
46 u32 checksum;
47 u32 offset;
48 char filename[0];
49} __attribute__ ((packed));
50
51static int filecount = 0, selected = 0;
52static char **filenames;
53static struct cbheader *header = NULL;
54
55static struct cbfile *getfile(struct cbfile *f)
56{
57 while (1) {
58 if (f < (struct cbfile *)(0xffffffff - ntohl(header->romsize)))
59 return NULL;
60 if (f->magic == 0)
61 return NULL;
62 if (f->magic == LARCHIVE_MAGIC)
63 return f;
64 f = (void *)f + ntohl(header->align);
65 }
66}
67
68static struct cbfile *firstfile(void)
69{
70 return getfile((void *)(0 - ntohl(header->romsize) +
71 ntohl(header->offset)));
72}
73
74static struct cbfile *nextfile(struct cbfile *f)
75{
76 f = (void *)f + ALIGN(ntohl(f->len) + ntohl(f->offset),
77 ntohl(header->align));
78 return getfile(f);
79}
80
81static struct cbfile *findfile(const char *filename)
82{
83 struct cbfile *f;
84 for (f = firstfile(); f; f = nextfile(f)) {
85 if (strcmp(filename, f->filename) == 0)
86 return f;
87 }
88 return NULL;
89}
90
91static int cbfs_module_init(void)
92{
93 struct cbfile *f;
94 int index = 0;
95
96 header = *(void **)HEADER_ADDR;
97 if (header->magic != ntohl(HEADER_MAGIC)) {
98 header = NULL;
99 return 0;
100 }
101
102 for (f = firstfile(); f; f = nextfile(f))
103 filecount++;
104
105 filenames = malloc(filecount * sizeof(char *));
106 if (filenames == NULL)
107 return 0;
108
109 for (f = firstfile(); f; f = nextfile(f))
110 filenames[index++] = strdup((const char *)f->filename);
111
112 return 0;
113}
114
115static int cbfs_module_redraw(WINDOW * win)
116{
117 struct cbfile *f;
118 int i, row = 2;
119
120 print_module_title(win, "CBFS Listing");
121
122 if (!header) {
123 mvwprintw(win, 11, 61 / 2, "Bad or missing CBFS header");
124 return 0;
125 }
126
127 /* Draw a line down the middle. */
128 for (i = 2; i < 21; i++)
129 mvwaddch(win, i, 30, ACS_VLINE);
130
131 /* Draw the names down the left side. */
132 for (i = 0; i < filecount; i++) {
133 if (i == selected)
134 wattrset(win, COLOR_PAIR(3) | A_BOLD);
135 else
136 wattrset(win, COLOR_PAIR(2));
137 if (i == filecount - 1)
138 mvwprintw(win, 2 + i, 1, "<free space>");
139 else
140 mvwprintw(win, 2 + i, 1, "%.25s", filenames[i]);
141 }
142
143 f = findfile(filenames[selected]);
144 if (!f) {
145 mvwprintw(win, 11, 32, "ERROR: CBFS component not found");
146 return 0;
147 }
148
149 wattrset(win, COLOR_PAIR(2));
150
151 /* mvwprintw(win, row++, 32, "Offset: 0x%x", f->offset); *//* FIXME */
152 mvwprintw(win, row, 32, "Type: ");
153 switch (ntohl(f->type)) {
154 case COMPONENT_STAGE:
155 mvwprintw(win, row++, 38, "stage");
156 break;
157 case COMPONENT_PAYLOAD:
158 mvwprintw(win, row++, 38, "payload");
159 break;
160 case COMPONENT_OPTIONROM:
161 mvwprintw(win, row++, 38, "optionrom");
162 break;
163 case COMPONENT_NULL:
164 mvwprintw(win, row++, 38, "free");
165 break;
166 case COMPONENT_DELETED:
167 mvwprintw(win, row++, 38, "deleted");
168 break;
169 default:
170 mvwprintw(win, row++, 38, "Unknown (0x%x)", ntohl(f->type));
171 break;
172 }
173 mvwprintw(win, row++, 32, "Size: %d", ntohl(f->len));
174 mvwprintw(win, row++, 32, "Checksum: 0x%x", ntohl(f->checksum));
175
176 return 0;
177}
178
179static int cbfs_module_handle(int key)
180{
181 int ret = 0;
182
183 if (filecount == 0)
184 return 0;
185
186 switch (key) {
187 case KEY_DOWN:
188 if (selected + 1 < filecount) {
189 selected++;
190 ret = 1;
191 }
192 break;
193 case KEY_UP:
194 if (selected > 0) {
195 selected--;
196 ret = 1;
197 }
198 break;
199 }
200
201 return ret;
202}
203
204struct coreinfo_module cbfs_module = {
205 .name = "CBFS",
206 .init = cbfs_module_init,
207 .redraw = cbfs_module_redraw,
208 .handle = cbfs_module_handle
209};
210
211#else
212
213struct coreinfo_module cbfs_module = {
214};
215
216#endif