/ payloads / coreinfo / cbfs_module.c
cbfs_module.c
  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  
 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  
 63  static struct cbfile *firstfile(void)
 64  {
 65  	return getfile((void *)(0 - ntohl(header->romsize) +
 66  				ntohl(header->offset)));
 67  }
 68  
 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  
 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  
 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  
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  
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