1 // Option rom scanning code.
3 // Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002 MandrakeSoft S.A.
6 // This file may be distributed under the terms of the GNU GPLv3 license.
8 #include "bregs.h" // struct bregs
9 #include "biosvar.h" // struct ipl_entry_s
10 #include "util.h" // dprintf
12 // $PnP string with special alignment in romlayout.S
13 extern char pnp_string[];
60 // Execute a given option rom.
62 callrom(u16 seg, u16 offset)
64 dprintf(1, "Running option rom at %x:%x\n", seg, offset);
67 memset(&br, 0, sizeof(br));
68 // XXX - should set br.ax to PCI Bus/DevFn
72 br.di = (u32)pnp_string - BUILD_BIOS_ADDR;
79 if (GET_BDA(ebda_seg) != SEG_EBDA)
80 BX_PANIC("Option rom at %x:%x attempted to move ebda from %x to %x\n"
81 , seg, offset, SEG_EBDA, GET_BDA(ebda_seg));
84 #define ebda ((struct extended_bios_data_area_s *)MAKE_FARPTR(SEG_EBDA, 0))
86 // Find and run any "option roms" found in the given address range.
88 rom_scan(u32 start, u32 end)
90 if (! CONFIG_OPTIONROMS)
94 for (; p < (u8*)end; p += 2048) {
95 struct rom_header *rom = (struct rom_header *)p;
96 if (rom->signature != 0xaa55)
98 u32 len = rom->size * 512;
99 u8 sum = checksum(p, len);
101 dprintf(1, "Found option rom with bad checksum:"
102 " loc=%p len=%d sum=%x\n"
106 p = (u8*)(((u32)p + len) / 2048 * 2048);
107 callrom(FARPTR_TO_SEG(rom), FARPTR_TO_OFFSET(rom->initVector));
109 // Look at the ROM's PnP Expansion header. Properly, we're supposed
110 // to init all the ROMs and then go back and build an IPL table of
111 // all the bootable devices, but we can get away with one pass.
112 struct pnp_data *pnp = (struct pnp_data *)((u8*)rom + rom->pnpoffset);
113 if (pnp->signature != *(u32*)pnp_string)
115 u16 entry = pnp->bev;
118 // Found a device that thinks it can boot the system. Record
119 // its BEV and product name string.
124 if (ebda->ipl.count >= ARRAY_SIZE(ebda->ipl.table))
127 struct ipl_entry_s *ip = &ebda->ipl.table[ebda->ipl.count];
128 ip->type = IPL_TYPE_BEV;
129 ip->vector = (FARPTR_TO_SEG(rom) << 16) | entry;
131 u16 desc = pnp->productname;
133 ip->description = (u32)MAKE_FARPTR(FARPTR_TO_SEG(rom), desc);
139 // Call into vga code to turn on console.
143 dprintf(1, "Scan for VGA option rom\n");
144 rom_scan(0xc0000, 0xc8000);
146 dprintf(1, "Turning on vga console\n");
148 memset(&br, 0, sizeof(br));
150 call16_int(0x10, &br);
153 printf("Starting SeaBIOS\n\n");
159 dprintf(1, "Scan for option roms\n");
160 rom_scan(0xc8000, 0xf0000);