blob: 5d013cfc2483e64bb5709b0413099e94671367a0 [file] [log] [blame]
Kevin O'Connor59a23bb2008-06-08 23:09:42 -04001// Coreboot interface support.
2//
Kevin O'Connor2929c352009-07-25 13:48:27 -04003// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connor59a23bb2008-06-08 23:09:42 -04004//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05005// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connor59a23bb2008-06-08 23:09:42 -04006
7#include "memmap.h" // add_e820
8#include "util.h" // dprintf
Kevin O'Connorb3064592012-08-14 21:20:10 -04009#include "byteorder.h" // be32_to_cpu
Kevin O'Connor592323f2009-04-26 23:17:49 -040010#include "lzmadecode.h" // LzmaDecode
Kevin O'Connor01a85202009-10-18 09:49:59 -040011#include "smbios.h" // smbios_init
Kevin O'Connor72eee3e2010-12-27 19:07:49 -050012#include "boot.h" // boot_add_cbfs
Kevin O'Connord3140832012-05-13 22:46:12 -040013#include "disk.h" // MAXDESCSIZE
14#include "config.h" // CONFIG_*
Kevin O'Connor59a23bb2008-06-08 23:09:42 -040015
16
17/****************************************************************
Kevin O'Connor93479e42008-06-12 22:22:43 -040018 * Memory map
Kevin O'Connor59a23bb2008-06-08 23:09:42 -040019 ****************************************************************/
20
21struct cb_header {
22 u32 signature;
23 u32 header_bytes;
24 u32 header_checksum;
25 u32 table_bytes;
26 u32 table_checksum;
27 u32 table_entries;
28};
29
30#define CB_SIGNATURE 0x4f49424C // "LBIO"
31
32struct cb_memory_range {
33 u64 start;
34 u64 size;
35 u32 type;
36};
37
38#define CB_MEM_TABLE 16
39
40struct cb_memory {
41 u32 tag;
42 u32 size;
43 struct cb_memory_range map[0];
44};
45
46#define CB_TAG_MEMORY 0x01
47
48#define MEM_RANGE_COUNT(_rec) \
49 (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0]))
50
Kevin O'Connor22e1b912009-07-19 18:52:46 -040051struct cb_mainboard {
52 u32 tag;
53 u32 size;
54 u8 vendor_idx;
55 u8 part_idx;
56 char strings[0];
57};
58
59#define CB_TAG_MAINBOARD 0x0003
60
Kevin O'Connor071f1542009-03-21 13:17:21 -040061struct cb_forward {
62 u32 tag;
63 u32 size;
64 u64 forward;
65};
66
67#define CB_TAG_FORWARD 0x11
68
Kevin O'Connor59a23bb2008-06-08 23:09:42 -040069static u16
70ipchksum(char *buf, int count)
71{
72 u16 *p = (u16*)buf;
73 u32 sum = 0;
74 while (count > 1) {
75 sum += *p++;
76 count -= 2;
77 }
78 if (count)
79 sum += *(u8*)p;
80 sum = (sum >> 16) + (sum & 0xffff);
81 sum += (sum >> 16);
82 return ~sum;
83}
84
85// Try to locate the coreboot header in a given address range.
86static struct cb_header *
87find_cb_header(char *addr, int len)
88{
89 char *end = addr + len;
90 for (; addr < end; addr += 16) {
91 struct cb_header *cbh = (struct cb_header *)addr;
92 if (cbh->signature != CB_SIGNATURE)
93 continue;
Kevin O'Connor59a23bb2008-06-08 23:09:42 -040094 if (! cbh->table_bytes)
95 continue;
96 if (ipchksum(addr, sizeof(*cbh)) != 0)
97 continue;
98 if (ipchksum(addr + sizeof(*cbh), cbh->table_bytes)
99 != cbh->table_checksum)
100 continue;
101 return cbh;
102 }
103 return NULL;
104}
105
106// Try to find the coreboot memory table in the given coreboot table.
Kevin O'Connor93479e42008-06-12 22:22:43 -0400107static void *
108find_cb_subtable(struct cb_header *cbh, u32 tag)
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400109{
110 char *tbl = (char *)cbh + sizeof(*cbh);
111 int i;
112 for (i=0; i<cbh->table_entries; i++) {
113 struct cb_memory *cbm = (struct cb_memory *)tbl;
114 tbl += cbm->size;
Kevin O'Connor93479e42008-06-12 22:22:43 -0400115 if (cbm->tag == tag)
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400116 return cbm;
117 }
118 return NULL;
119}
120
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400121static struct cb_memory *CBMemTable;
Julian Pidancet02145152012-02-05 04:51:06 +0000122const char *CBvendor = "", *CBpart = "";
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400123
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400124// Populate max ram and e820 map info by scanning for a coreboot table.
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400125void
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500126coreboot_preinit(void)
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400127{
128 dprintf(3, "Attempting to find coreboot table\n");
Kevin O'Connoref3d8822009-02-05 19:51:12 -0500129
Kevin O'Connoref3d8822009-02-05 19:51:12 -0500130 // Find coreboot table.
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400131 struct cb_header *cbh = find_cb_header(0, 0x1000);
132 if (!cbh)
133 goto fail;
Kevin O'Connor071f1542009-03-21 13:17:21 -0400134 struct cb_forward *cbf = find_cb_subtable(cbh, CB_TAG_FORWARD);
135 if (cbf) {
136 dprintf(3, "Found coreboot table forwarder.\n");
137 cbh = find_cb_header((char *)((u32)cbf->forward), 0x100);
138 if (!cbh)
139 goto fail;
140 }
141 dprintf(3, "Now attempting to find coreboot memory map\n");
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400142 struct cb_memory *cbm = CBMemTable = find_cb_subtable(cbh, CB_TAG_MEMORY);
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400143 if (!cbm)
144 goto fail;
145
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400146 u64 maxram = 0, maxram_over4G = 0;
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400147 int i, count = MEM_RANGE_COUNT(cbm);
148 for (i=0; i<count; i++) {
149 struct cb_memory_range *m = &cbm->map[i];
150 u32 type = m->type;
Kevin O'Connor93479e42008-06-12 22:22:43 -0400151 if (type == CB_MEM_TABLE) {
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400152 type = E820_RESERVED;
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400153 } else if (type == E820_ACPI || type == E820_RAM) {
154 u64 end = m->start + m->size;
155 if (end > 0x100000000ull) {
156 end -= 0x100000000ull;
157 if (end > maxram_over4G)
158 maxram_over4G = end;
159 } else if (end > maxram)
160 maxram = end;
Kevin O'Connor93479e42008-06-12 22:22:43 -0400161 }
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400162 add_e820(m->start, m->size, type);
163 }
164
Kevin O'Connore7916362008-12-28 22:03:17 -0500165 RamSize = maxram;
166 RamSizeOver4G = maxram_over4G;
Kevin O'Connor59c35f22008-10-25 23:05:42 -0400167
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400168 // Ughh - coreboot likes to set a map at 0x0000-0x1000, but this
169 // confuses grub. So, override it.
170 add_e820(0, 16*1024, E820_RAM);
171
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400172 struct cb_mainboard *cbmb = find_cb_subtable(cbh, CB_TAG_MAINBOARD);
173 if (cbmb) {
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400174 CBvendor = &cbmb->strings[cbmb->vendor_idx];
175 CBpart = &cbmb->strings[cbmb->part_idx];
176 dprintf(1, "Found mainboard %s %s\n", CBvendor, CBpart);
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400177 }
178
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400179 return;
180
181fail:
182 // No table found.. Use 16Megs as a dummy value.
183 dprintf(1, "Unable to find coreboot table!\n");
Kevin O'Connore7916362008-12-28 22:03:17 -0500184 RamSize = 16*1024*1024;
185 RamSizeOver4G = 0;
Kevin O'Connor59a23bb2008-06-08 23:09:42 -0400186 add_e820(0, 16*1024*1024, E820_RAM);
187 return;
188}
Kevin O'Connor4c0c85a2009-04-11 23:31:29 -0400189
190
191/****************************************************************
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400192 * BIOS table copying
193 ****************************************************************/
194
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400195// Attempt to find (and relocate) any standard bios tables found in a
196// given address range.
197static void
198scan_tables(u32 start, u32 size)
199{
200 void *p = (void*)ALIGN(start, 16);
201 void *end = (void*)start + size;
Kevin O'Connor4d053eb2012-06-09 13:08:02 -0400202 for (; p<end; p += 16)
203 copy_table(p);
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400204}
205
206void
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500207coreboot_biostable_setup(void)
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400208{
209 struct cb_memory *cbm = CBMemTable;
210 if (! CONFIG_COREBOOT || !cbm)
211 return;
212
213 dprintf(3, "Relocating coreboot bios tables\n");
214
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400215 // Scan CB_MEM_TABLE areas for bios tables.
216 int i, count = MEM_RANGE_COUNT(cbm);
217 for (i=0; i<count; i++) {
218 struct cb_memory_range *m = &cbm->map[i];
219 if (m->type == CB_MEM_TABLE)
220 scan_tables(m->start, m->size);
221 }
Kevin O'Connordf5a5fd2009-07-28 20:46:03 -0400222}
223
224
225/****************************************************************
Kevin O'Connor592323f2009-04-26 23:17:49 -0400226 * ulzma
227 ****************************************************************/
228
Kevin O'Connor1f836252009-08-16 20:17:35 -0400229// Uncompress data in flash to an area of memory.
Kevin O'Connor592323f2009-04-26 23:17:49 -0400230static int
Kevin O'Connorcbd6ca02009-04-27 21:51:13 -0400231ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen)
Kevin O'Connor592323f2009-04-26 23:17:49 -0400232{
Kevin O'Connor1edc89d2009-04-30 21:50:35 -0400233 dprintf(3, "Uncompressing data %d@%p to %d@%p\n", srclen, src, maxlen, dst);
Kevin O'Connor592323f2009-04-26 23:17:49 -0400234 CLzmaDecoderState state;
235 int ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);
236 if (ret != LZMA_RESULT_OK) {
237 dprintf(1, "LzmaDecodeProperties error - %d\n", ret);
238 return -1;
239 }
240 u8 scratch[15980];
241 int need = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
242 if (need > sizeof(scratch)) {
Kevin O'Connor311f8872010-12-26 14:16:22 -0500243 dprintf(1, "LzmaDecode need %d have %d\n", need, (unsigned int)sizeof(scratch));
Kevin O'Connor592323f2009-04-26 23:17:49 -0400244 return -1;
245 }
246 state.Probs = (CProb *)scratch;
247
248 u32 dstlen = *(u32*)(src + LZMA_PROPERTIES_SIZE);
Kevin O'Connorcbd6ca02009-04-27 21:51:13 -0400249 if (dstlen > maxlen) {
250 dprintf(1, "LzmaDecode too large (max %d need %d)\n", maxlen, dstlen);
251 return -1;
252 }
Kevin O'Connor592323f2009-04-26 23:17:49 -0400253 u32 inProcessed, outProcessed;
Kevin O'Connorcbd6ca02009-04-27 21:51:13 -0400254 ret = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, srclen
Kevin O'Connor592323f2009-04-26 23:17:49 -0400255 , &inProcessed, dst, dstlen, &outProcessed);
256 if (ret) {
257 dprintf(1, "LzmaDecode returned %d\n", ret);
258 return -1;
259 }
260 return dstlen;
261}
262
263
264/****************************************************************
Kevin O'Connor4c0c85a2009-04-11 23:31:29 -0400265 * Coreboot flash format
266 ****************************************************************/
267
Kevin O'Connor4c0c85a2009-04-11 23:31:29 -0400268#define CBFS_HEADER_MAGIC 0x4F524243
269#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
270#define CBFS_VERSION1 0x31313131
271
272struct cbfs_header {
273 u32 magic;
274 u32 version;
275 u32 romsize;
276 u32 bootblocksize;
277 u32 align;
278 u32 offset;
279 u32 pad[2];
280} PACKED;
281
Kevin O'Connor4c0c85a2009-04-11 23:31:29 -0400282#define CBFS_FILE_MAGIC 0x455649484352414cLL // LARCHIVE
283
284struct cbfs_file {
285 u64 magic;
286 u32 len;
287 u32 type;
288 u32 checksum;
289 u32 offset;
Kevin O'Connor67823442009-04-13 14:14:51 -0400290 char filename[0];
Kevin O'Connor4c0c85a2009-04-11 23:31:29 -0400291} PACKED;
292
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400293// Copy a file to memory (uncompressing if necessary)
294static int
295cbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen)
Kevin O'Connor67823442009-04-13 14:14:51 -0400296{
Kevin O'Connord9c93612010-03-20 11:00:45 -0400297 if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH)
Kevin O'Connor1f836252009-08-16 20:17:35 -0400298 return -1;
299
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400300 u32 size = file->rawsize;
301 void *src = file->data;
302 if (file->flags) {
Kevin O'Connor34036962009-12-05 18:51:53 -0500303 // Compressed - copy to temp ram and uncompress it.
Kevin O'Connorb4525a02010-07-27 01:14:11 -0400304 void *temp = malloc_tmphigh(size);
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400305 if (!temp) {
306 warn_noalloc();
Kevin O'Connor34036962009-12-05 18:51:53 -0500307 return -1;
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400308 }
Kevin O'Connorb4525a02010-07-27 01:14:11 -0400309 iomemcpy(temp, src, size);
Kevin O'Connor34036962009-12-05 18:51:53 -0500310 int ret = ulzma(dst, maxlen, temp, size);
311 yield();
312 free(temp);
313 return ret;
314 }
Kevin O'Connor1f836252009-08-16 20:17:35 -0400315
316 // Not compressed.
317 dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
318 if (size > maxlen) {
Kevin O'Connorcfdc13f2010-02-14 13:07:54 -0500319 warn_noalloc();
Kevin O'Connor1f836252009-08-16 20:17:35 -0400320 return -1;
321 }
Kevin O'Connor34036962009-12-05 18:51:53 -0500322 iomemcpy(dst, src, size);
Kevin O'Connor1f836252009-08-16 20:17:35 -0400323 return size;
Kevin O'Connor67823442009-04-13 14:14:51 -0400324}
325
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400326void
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500327coreboot_cbfs_init(void)
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400328{
329 if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH)
330 return;
331
332 struct cbfs_header *hdr = *(void **)CBFS_HEADPTR_ADDR;
Kevin O'Connorb3064592012-08-14 21:20:10 -0400333 if (hdr->magic != cpu_to_be32(CBFS_HEADER_MAGIC)) {
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400334 dprintf(1, "Unable to find CBFS (ptr=%p; got %x not %x)\n"
Kevin O'Connorb3064592012-08-14 21:20:10 -0400335 , hdr, hdr->magic, cpu_to_be32(CBFS_HEADER_MAGIC));
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400336 return;
337 }
338 dprintf(1, "Found CBFS header at %p\n", hdr);
339
Kevin O'Connorb3064592012-08-14 21:20:10 -0400340 struct cbfs_file *cfile = (void *)(0 - be32_to_cpu(hdr->romsize)
341 + be32_to_cpu(hdr->offset));
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400342 for (;;) {
Kevin O'Connorb3064592012-08-14 21:20:10 -0400343 if (cfile < (struct cbfs_file *)(0xFFFFFFFF - be32_to_cpu(hdr->romsize)))
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400344 break;
345 u64 magic = cfile->magic;
346 if (magic != CBFS_FILE_MAGIC)
347 break;
348 struct romfile_s *file = malloc_tmp(sizeof(*file));
349 if (!file) {
350 warn_noalloc();
351 break;
352 }
353 memset(file, 0, sizeof(*file));
354 strtcpy(file->name, cfile->filename, sizeof(file->name));
355 dprintf(3, "Found CBFS file: %s\n", file->name);
Kevin O'Connorb3064592012-08-14 21:20:10 -0400356 file->size = file->rawsize = be32_to_cpu(cfile->len);
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400357 file->id = (u32)cfile;
358 file->copy = cbfs_copyfile;
Kevin O'Connorb3064592012-08-14 21:20:10 -0400359 file->data = (void*)cfile + be32_to_cpu(cfile->offset);
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400360 int len = strlen(file->name);
361 if (len > 5 && strcmp(&file->name[len-5], ".lzma") == 0) {
362 // Using compression.
363 file->flags = 1;
364 file->name[len-5] = '\0';
365 file->size = *(u32*)(file->data + LZMA_PROPERTIES_SIZE);
366 }
367 romfile_add(file);
368
Kevin O'Connorb3064592012-08-14 21:20:10 -0400369 cfile = (void*)ALIGN((u32)file->data + file->size, be32_to_cpu(hdr->align));
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400370 }
371}
372
Kevin O'Connor67823442009-04-13 14:14:51 -0400373struct cbfs_payload_segment {
374 u32 type;
375 u32 compression;
376 u32 offset;
377 u64 load_addr;
378 u32 len;
379 u32 mem_len;
380} PACKED;
381
382#define PAYLOAD_SEGMENT_BSS 0x20535342
383#define PAYLOAD_SEGMENT_ENTRY 0x52544E45
384
385#define CBFS_COMPRESS_NONE 0
Kevin O'Connor592323f2009-04-26 23:17:49 -0400386#define CBFS_COMPRESS_LZMA 1
Kevin O'Connor67823442009-04-13 14:14:51 -0400387
388struct cbfs_payload {
389 struct cbfs_payload_segment segments[1];
390};
391
392void
Kevin O'Connor1f836252009-08-16 20:17:35 -0400393cbfs_run_payload(struct cbfs_file *file)
Kevin O'Connor67823442009-04-13 14:14:51 -0400394{
Kevin O'Connord9c93612010-03-20 11:00:45 -0400395 if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH || !file)
Kevin O'Connorcbd6ca02009-04-27 21:51:13 -0400396 return;
Kevin O'Connor1f836252009-08-16 20:17:35 -0400397 dprintf(1, "Run %s\n", file->filename);
Kevin O'Connorb3064592012-08-14 21:20:10 -0400398 struct cbfs_payload *pay = (void*)file + be32_to_cpu(file->offset);
Kevin O'Connor67823442009-04-13 14:14:51 -0400399 struct cbfs_payload_segment *seg = pay->segments;
400 for (;;) {
Kevin O'Connorb3064592012-08-14 21:20:10 -0400401 void *src = (void*)pay + be32_to_cpu(seg->offset);
402 void *dest = (void*)(u32)be64_to_cpu(seg->load_addr);
403 u32 src_len = be32_to_cpu(seg->len);
404 u32 dest_len = be32_to_cpu(seg->mem_len);
Kevin O'Connor67823442009-04-13 14:14:51 -0400405 switch (seg->type) {
406 case PAYLOAD_SEGMENT_BSS:
407 dprintf(3, "BSS segment %d@%p\n", dest_len, dest);
408 memset(dest, 0, dest_len);
409 break;
410 case PAYLOAD_SEGMENT_ENTRY: {
411 dprintf(1, "Calling addr %p\n", dest);
412 void (*func)() = dest;
413 func();
414 return;
415 }
416 default:
417 dprintf(3, "Segment %x %d@%p -> %d@%p\n"
418 , seg->type, src_len, src, dest_len, dest);
Kevin O'Connorb3064592012-08-14 21:20:10 -0400419 if (seg->compression == cpu_to_be32(CBFS_COMPRESS_NONE)) {
Kevin O'Connorcbd6ca02009-04-27 21:51:13 -0400420 if (src_len > dest_len)
421 src_len = dest_len;
Kevin O'Connor592323f2009-04-26 23:17:49 -0400422 memcpy(dest, src, src_len);
423 } else if (CONFIG_LZMA
Kevin O'Connorb3064592012-08-14 21:20:10 -0400424 && seg->compression == cpu_to_be32(CBFS_COMPRESS_LZMA)) {
Kevin O'Connorcbd6ca02009-04-27 21:51:13 -0400425 int ret = ulzma(dest, dest_len, src, src_len);
Kevin O'Connor592323f2009-04-26 23:17:49 -0400426 if (ret < 0)
427 return;
428 src_len = ret;
429 } else {
430 dprintf(1, "No support for compression type %x\n"
431 , seg->compression);
432 return;
433 }
Kevin O'Connor67823442009-04-13 14:14:51 -0400434 if (dest_len > src_len)
435 memset(dest + src_len, 0, dest_len - src_len);
436 break;
437 }
438 seg++;
439 }
440}
441
Kevin O'Connor72eee3e2010-12-27 19:07:49 -0500442// Register payloads in "img/" directory with boot system.
Kevin O'Connor89a1efd2011-01-08 12:24:39 -0500443void
444cbfs_payload_setup(void)
Kevin O'Connor72eee3e2010-12-27 19:07:49 -0500445{
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400446 if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH)
447 return;
448 struct romfile_s *file = NULL;
Kevin O'Connor72eee3e2010-12-27 19:07:49 -0500449 for (;;) {
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400450 file = romfile_findprefix("img/", file);
Kevin O'Connor72eee3e2010-12-27 19:07:49 -0500451 if (!file)
452 break;
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400453 const char *filename = file->name;
Kevin O'Connorca2bc1c2010-12-29 21:41:19 -0500454 char *desc = znprintf(MAXDESCSIZE, "Payload [%s]", &filename[4]);
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400455 boot_add_cbfs((void*)file->id, desc
456 , bootprio_find_named_rom(filename, 0));
Kevin O'Connor72eee3e2010-12-27 19:07:49 -0500457 }
458}