• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include "coreinfo.h"
4 #include "endian.h"
5 
6 #if CONFIG(MODULE_CBFS)
7 
8 #define FILES_VISIBLE		19
9 
10 #define HEADER_MAGIC		0x4F524243
11 #define HEADER_ADDR		0xfffffffc
12 #define LARCHIVE_MAGIC		0x455649484352414cLL	/* "LARCHIVE" */
13 
14 #define COMPONENT_DELETED	0x00
15 #define COMPONENT_BOOTBLOCK	0x01
16 #define COMPONENT_CBFSHEADER	0x02
17 #define COMPONENT_STAGE		0x10
18 #define COMPONENT_SELF		0x20
19 #define COMPONENT_FIT		0x21
20 #define COMPONENT_OPTIONROM	0x30
21 #define COMPONENT_RAW		0x50
22 #define COMPONENT_MICROCODE	0x53
23 #define COMPONENT_CMOS_LAYOUT	0x1aa
24 #define COMPONENT_NULL		0xffffffff
25 
26 struct cbheader {
27 	u32 magic;
28 	u32 version;
29 	u32 romsize;
30 	u32 bootblocksize;
31 	u32 align;
32 	u32 offset;
33 	u32 architecture;
34 	u32 pad[];
35 } __packed;
36 
37 struct cbfile {
38 	u64 magic;
39 	u32 len;
40 	u32 type;
41 	u32 checksum;
42 	u32 offset;
43 	char filename[];
44 } __packed;
45 
46 static int filecount = 0, selected = 0, start_row = 0;
47 static char **filenames;
48 static struct cbheader *header = NULL;
49 
getfile(struct cbfile * f)50 static struct cbfile *getfile(struct cbfile *f)
51 {
52 	while (1) {
53 		if (f < (struct cbfile *)(0xffffffff - ntohl(header->romsize)))
54 			return NULL;
55 		if (f->magic == 0)
56 			return NULL;
57 		if (f->magic == LARCHIVE_MAGIC)
58 			return f;
59 		f = (struct cbfile *)((u8 *)f + ntohl(header->align));
60 	}
61 }
62 
firstfile(void)63 static struct cbfile *firstfile(void)
64 {
65 	return getfile((void *)(0 - ntohl(header->romsize) +
66 				ntohl(header->offset)));
67 }
68 
nextfile(struct cbfile * f)69 static struct cbfile *nextfile(struct cbfile *f)
70 {
71 	f = (struct cbfile *)((u8 *)f + ALIGN_UP(ntohl(f->len) + ntohl(f->offset),
72 			      ntohl(header->align)));
73 	return getfile(f);
74 }
75 
findfile(const char * filename)76 static struct cbfile *findfile(const char *filename)
77 {
78 	struct cbfile *f;
79 	for (f = firstfile(); f; f = nextfile(f)) {
80 		if (strcmp(filename, f->filename) == 0)
81 			return f;
82 	}
83 	return NULL;
84 }
85 
cbfs_module_init(void)86 static int cbfs_module_init(void)
87 {
88 	struct cbfile *f;
89 	int index = 0;
90 
91 	header = *(void **)HEADER_ADDR;
92 	if (header->magic != ntohl(HEADER_MAGIC)) {
93 		header = NULL;
94 		return 0;
95 	}
96 
97 	for (f = firstfile(); f; f = nextfile(f))
98 		filecount++;
99 
100 	filenames = malloc(filecount * sizeof(char *));
101 	if (filenames == NULL)
102 		return 0;
103 
104 	for (f = firstfile(); f; f = nextfile(f))
105 		filenames[index++] = strdup((const char *)f->filename);
106 
107 	return 0;
108 }
109 
cbfs_module_redraw(WINDOW * win)110 static int cbfs_module_redraw(WINDOW * win)
111 {
112 	struct cbfile *f;
113 	int i, row, frow;
114 
115 	print_module_title(win, "CBFS Listing");
116 
117 	if (!header) {
118 		mvwprintw(win, 11, 61 / 2, "Bad or missing CBFS header");
119 		return 0;
120 	}
121 
122 	/* Draw a line down the middle. */
123 	for (i = 2; i < 21; i++)
124 		mvwaddch(win, i, 30, ACS_VLINE);
125 
126 	/* Draw the names down the left side. */
127 	for (frow = 0; frow < FILES_VISIBLE; frow++) {
128 		row = 2 + frow;
129 		i = start_row + frow;
130 		if (i >= filecount)
131 			break;
132 		if (i == selected)
133 			wattrset(win, COLOR_PAIR(3) | A_BOLD);
134 		else
135 			wattrset(win, COLOR_PAIR(2));
136 
137 		if (strlen(filenames[i]) == 0) {
138 			if (findfile(filenames[i])->type == COMPONENT_NULL)
139 				mvwprintw(win, row, 1, "<free space>");
140 			else
141 				mvwprintw(win, row, 1, "<unnamed>");
142 		} else {
143 			mvwprintw(win, row, 1, "%.25s", filenames[i]);
144 		}
145 		/* show scroll arrows */
146 		if (frow == 0 && start_row > 0) {
147 			wattrset(win, COLOR_PAIR(2));
148 			mvwaddch(win, row, 28, ACS_UARROW);
149 		}
150 		if (frow == FILES_VISIBLE - 1 && i != filecount - 1) {
151 			wattrset(win, COLOR_PAIR(2));
152 			mvwaddch(win, row, 28, ACS_DARROW);
153 		}
154 	}
155 
156 	f = findfile(filenames[selected]);
157 	if (!f) {
158 		mvwprintw(win, 11, 32, "ERROR: CBFS component not found");
159 		return 0;
160 	}
161 
162 	wattrset(win, COLOR_PAIR(2));
163 
164 	/* Draw the file information */
165 	row = 2;
166 	/* mvwprintw(win, row++, 32, "Offset: 0x%x", f->offset); *//* FIXME */
167 	mvwprintw(win, row, 32, "Type: ");
168 	switch (ntohl(f->type)) {
169 	case COMPONENT_BOOTBLOCK:
170 		mvwprintw(win, row++, 38, "bootblock");
171 		break;
172 	case COMPONENT_CBFSHEADER:
173 		mvwprintw(win, row++, 38, "CBFS header");
174 		break;
175 	case COMPONENT_STAGE:
176 		mvwprintw(win, row++, 38, "stage");
177 		break;
178 	case COMPONENT_SELF:
179 		mvwprintw(win, row++, 38, "simple ELF");
180 		break;
181 	case COMPONENT_FIT:
182 		mvwprintw(win, row++, 38, "FIT");
183 		break;
184 	case COMPONENT_OPTIONROM:
185 		mvwprintw(win, row++, 38, "optionrom");
186 		break;
187 	case COMPONENT_RAW:
188 		mvwprintw(win, row++, 38, "raw");
189 		break;
190 	case COMPONENT_MICROCODE:
191 		mvwprintw(win, row++, 38, "microcode");
192 		break;
193 	case COMPONENT_CMOS_LAYOUT:
194 		mvwprintw(win, row++, 38, "cmos layout");
195 		break;
196 	case COMPONENT_NULL:
197 		mvwprintw(win, row++, 38, "free");
198 		break;
199 	case COMPONENT_DELETED:
200 		mvwprintw(win, row++, 38, "deleted");
201 		break;
202 	default:
203 		mvwprintw(win, row++, 38, "Unknown (0x%x)", ntohl(f->type));
204 		break;
205 	}
206 	mvwprintw(win, row++, 32, "Size: %d", ntohl(f->len));
207 	mvwprintw(win, row++, 32, "Checksum: 0x%x", ntohl(f->checksum));
208 
209 	return 0;
210 }
211 
cbfs_module_handle(int key)212 static int cbfs_module_handle(int key)
213 {
214 	int ret = 0;
215 
216 	if (filecount == 0)
217 		return 0;
218 
219 	switch (key) {
220 	case KEY_DOWN:
221 		if (selected + 1 < filecount) {
222 			selected++;
223 			if (selected >= start_row + FILES_VISIBLE - 1)
224 				start_row = selected - (FILES_VISIBLE - 1);
225 			ret = 1;
226 		}
227 		break;
228 	case KEY_UP:
229 		if (selected > 0) {
230 			selected--;
231 			if (selected < start_row)
232 				start_row = selected;
233 			ret = 1;
234 		}
235 		break;
236 	}
237 
238 	return ret;
239 }
240 
241 struct coreinfo_module cbfs_module = {
242 	.name = "CBFS",
243 	.init = cbfs_module_init,
244 	.redraw = cbfs_module_redraw,
245 	.handle = cbfs_module_handle
246 };
247 
248 #else
249 
250 struct coreinfo_module cbfs_module = {
251 };
252 
253 #endif
254