ie++;
}
+ if (CONFIG_COREBOOT_FLASH) {
+ ie->type = IPL_TYPE_CBFS;
+ ie->description = "CBFS";
+ ie++;
+ }
+
IPL.bevcount = ie - IPL.bev;
SET_EBDA(boot_sequence, 0xffff);
if (CONFIG_COREBOOT) {
return ATA.cdcount;
}
+// Show coreboot-fs menu item.
+static int
+menu_show_cbfs(struct ipl_entry_s *ie, int menupos)
+{
+ int count = 0;
+ for (;;) {
+ const char *filename = cbfs_findNprefix("img/", count);
+ if (!filename)
+ break;
+ printf("%d. Payload [%s]\n", menupos + count, &filename[4]);
+ count++;
+ if (count > 8)
+ break;
+ }
+ return count;
+}
+
// Show IPL option menu.
static void
interactive_bootmenu()
case IPL_TYPE_CDROM:
sc = menu_show_cdrom(ie, menupos);
break;
+ case IPL_TYPE_CBFS:
+ sc = menu_show_cbfs(ie, menupos);
+ break;
default:
sc = menu_show_default(ie, menupos);
break;
choice -= subcount[bev];
bev++;
}
-
- switch (IPL.bev[bev].type) {
- case IPL_TYPE_HARDDISK:
- // A harddrive request enables a BCV order.
- IPL.bcv_override = choice-1;
- break;
- case IPL_TYPE_CDROM:
- // Select cdrom to boot from.
- IPL.cdrom_override = choice-1;
- break;
- }
+ IPL.bev[bev].subchoice = choice-1;
// Add user choice to the boot order.
IPL.bootorder = (IPL.bootorder << 4) | (bev+1);
interactive_bootmenu();
// Run BCVs
- int override = IPL.bcv_override;
+ int override = IPL.bev[1].subchoice;
if (override < IPL.bcvcount)
run_bcv(&IPL.bcv[override]);
int i;
// Boot from a CD-ROM
static void
-boot_cdrom()
+boot_cdrom(struct ipl_entry_s *ie)
{
if (! CONFIG_CDROM_BOOT)
return;
- int status = cdrom_boot(IPL.cdrom_override);
+ int status = cdrom_boot(ie->subchoice);
if (status) {
printf("Boot failed: Could not read from CDROM (code %04x)\n", status);
return;
call_boot_entry(bootseg, bootip, bootdrv);
}
+// Boot from a CD-ROM
+static void
+boot_cbfs(struct ipl_entry_s *ie)
+{
+ if (! CONFIG_COREBOOT_FLASH)
+ return;
+ const char *filename = cbfs_findNprefix("img/", ie->subchoice);
+ if (! filename)
+ return;
+ cbfs_run_payload(filename);
+}
+
static void
do_boot(u16 seq_nr)
{
boot_disk(0x80, 1);
break;
case IPL_TYPE_CDROM:
- boot_cdrom();
+ boot_cdrom(ie);
+ break;
+ case IPL_TYPE_CBFS:
+ boot_cbfs(ie);
break;
case IPL_TYPE_BEV:
call_boot_entry(ie->vector >> 16, ie->vector & 0xffff, 0);
u32 type;
u32 checksum;
u32 offset;
+ char filename[0];
} PACKED;
static struct cbfs_file *
-cbfs_find(char *fname)
+cbfs_search(struct cbfs_file *file)
+{
+ for (;;) {
+ if (file < (struct cbfs_file *)(0xFFFFFFFF - ntohl(CBHDR->romsize)))
+ return NULL;
+ if (file->magic == CBFS_FILE_MAGIC)
+ return file;
+ file = (void*)file + ntohl(CBHDR->align);
+ }
+}
+
+static struct cbfs_file *
+cbfs_getfirst()
{
- if (! CONFIG_COREBOOT_FLASH)
- return NULL;
if (! CBHDR)
return NULL;
+ return cbfs_search((void *)(0 - ntohl(CBHDR->romsize) + ntohl(CBHDR->offset)));
+}
- dprintf(3, "Searching CBFS for %s\n", fname);
+static struct cbfs_file *
+cbfs_getnext(struct cbfs_file *file)
+{
+ file = (void*)file + ALIGN(ntohl(file->len) + ntohl(file->offset), ntohl(CBHDR->align));
+ return cbfs_search(file);
+}
- struct cbfs_file *file = (void *)(0 - ntohl(CBHDR->romsize) + ntohl(CBHDR->offset));
- for (;;) {
- if (file < (struct cbfs_file *)(0xFFFFFFFF - ntohl(CBHDR->romsize)))
- return NULL;
- if (file->magic != CBFS_FILE_MAGIC) {
- file = (void*)file + ntohl(CBHDR->align);
- continue;
- }
+static struct cbfs_file *
+cbfs_findfile(const char *fname)
+{
+ if (! CONFIG_COREBOOT_FLASH)
+ return NULL;
- dprintf(3, "Found CBFS file %s\n", (char*)file + sizeof(*file));
- if (streq(fname, (char*)file + sizeof(*file)))
+ dprintf(3, "Searching CBFS for %s\n", fname);
+ struct cbfs_file *file;
+ for (file = cbfs_getfirst(); file; file = cbfs_getnext(file)) {
+ dprintf(3, "Found CBFS file %s\n", file->filename);
+ if (streq(fname, file->filename))
return file;
- file = (void*)file + ALIGN(ntohl(file->len) + ntohl(file->offset), ntohl(CBHDR->align));
}
+ return NULL;
+}
+
+const char *
+cbfs_findNprefix(const char *prefix, int n)
+{
+ if (! CONFIG_COREBOOT_FLASH)
+ return NULL;
+
+ dprintf(3, "Searching CBFS for prefix %s\n", prefix);
+ int len = strlen(prefix);
+ struct cbfs_file *file;
+ for (file = cbfs_getfirst(); file; file = cbfs_getnext(file)) {
+ dprintf(3, "Found CBFS file %s\n", file->filename);
+ if (memeq(prefix, file->filename, len)) {
+ if (n <= 0)
+ return file->filename;
+ n--;
+ }
+ }
+ return NULL;
}
static char
char fname[17];
// Ughh - poor man's sprintf of "pci%04x,%04x.rom"
- *(u32*)fname = 0x20696370; // "pci"
+ *(u32*)fname = 0x20696370; // "pci "
*(u32*)&fname[3] = hexify4(vendev);
fname[7] = ',';
*(u32*)&fname[8] = hexify4(vendev >> 16);
*(u32*)&fname[12] = 0x6d6f722e; // ".rom"
fname[16] = '\0';
- struct cbfs_file *file = cbfs_find(fname);
+ struct cbfs_file *file = cbfs_findfile(fname);
if (!file)
return NULL;
// Found it.
return (void*)file + ntohl(file->offset);
}
+struct cbfs_payload_segment {
+ u32 type;
+ u32 compression;
+ u32 offset;
+ u64 load_addr;
+ u32 len;
+ u32 mem_len;
+} PACKED;
+
+#define PAYLOAD_SEGMENT_BSS 0x20535342
+#define PAYLOAD_SEGMENT_ENTRY 0x52544E45
+
+#define CBFS_COMPRESS_NONE 0
+
+struct cbfs_payload {
+ struct cbfs_payload_segment segments[1];
+};
+
+void
+cbfs_run_payload(const char *filename)
+{
+ dprintf(1, "Run %s\n", filename);
+ struct cbfs_file *file = cbfs_findfile(filename);
+ if (!file)
+ return;
+ struct cbfs_payload *pay = (void*)file + ntohl(file->offset);
+ struct cbfs_payload_segment *seg = pay->segments;
+ for (;;) {
+ if (seg->compression != htonl(CBFS_COMPRESS_NONE)) {
+ dprintf(1, "No support for compressed payloads (%x)\n"
+ , seg->compression);
+ return;
+ }
+ void *src = (void*)pay + ntohl(seg->offset);
+ void *dest = (void*)ntohl((u32)seg->load_addr);
+ u32 src_len = ntohl(seg->len);
+ u32 dest_len = ntohl(seg->mem_len);
+ switch (seg->type) {
+ case PAYLOAD_SEGMENT_BSS:
+ dprintf(3, "BSS segment %d@%p\n", dest_len, dest);
+ memset(dest, 0, dest_len);
+ break;
+ case PAYLOAD_SEGMENT_ENTRY: {
+ dprintf(1, "Calling addr %p\n", dest);
+ void (*func)() = dest;
+ func();
+ return;
+ }
+ default:
+ dprintf(3, "Segment %x %d@%p -> %d@%p\n"
+ , seg->type, src_len, src, dest_len, dest);
+ if (src_len > dest_len)
+ src_len = dest_len;
+ memcpy(dest, src, src_len);
+ if (dest_len > src_len)
+ memset(dest + src_len, 0, dest_len - src_len);
+ break;
+ }
+ seg++;
+ }
+}
+
void
coreboot_setup(void)
{
inline u32 stack_hop(u32 eax, u32 edx, u32 ecx, void *func);
u8 checksum_far(u16 buf_seg, void *buf_far, u32 len);
u8 checksum(void *buf, u32 len);
-int streq(char *s1, char *s2);
+int memeq(const void *s1, const void *s2, size_t n);
+size_t strlen(const char *s);
+int streq(const char *s1, const char *s2);
void *memset(void *s, int c, size_t n);
void *memcpy(void *d1, const void *s1, size_t len);
inline void memcpy_far(u16 d_seg, void *d_far
void smbios_init(void);
// coreboot.c
+const char *cbfs_findNprefix(const char *prefix, int n);
void *cb_find_optionrom(u32 vendev);
+void cbfs_run_payload(const char *filename);
void coreboot_setup();
// vgahooks.c