On 05/14/14 13:27, Jaeyong Yoo wrote:
Hello Seabios!
I started the thread from qemu-list and Laszlo suggested me to post the question here.
In Seabios, the call-path of calling vgarom entry point is the following:
handle_post() [src/post.c] make_bios_writable() [src/fw/shadow.c] make_bios_writable_intel() __make_bios_writable_intel() -- shadows vgabios in C segment too dopost() [src/post.c] maininit() vgarom_setup() [src/optionroms.c] init_pcirom() init_optionrom() callrom() __callrom() _rom_header_entry [vgasrc/vgaentry.S] vga_post() [vgasrc/vgainit.c]
For me, it looks like seabios (bios.bin) calls a function, vga_post, that is supposed be in vgabios.bin. It makes me thinking that vgabios.bin is somehow embedded in bios.bin.
No, vgabios is a separate binary, formatted as a PCI option ("expansion") ROM. It starts with a special structure -- there's an entry point field in it, which happens to contain a jump instruction. Please check the functions and files that I listed in the above call tree.
vgasrc/vgaentry.S:
_rom_header_entry: jmp _optionrom_entry [...] _optionrom_entry: ENTRY_ARG_VGA vga_post [...]
src/optionroms.c:
// Execute a given option rom at the standard entry vector. void callrom(struct rom_header *rom, u16 bdf) { __callrom(rom, OPTION_ROM_INITVECTOR, bdf); }
// Execute a given option rom. static void __callrom(struct rom_header *rom, u16 offset, u16 bdf) { u16 seg = FLATPTR_TO_SEG(rom); dprintf(1, "Running option rom at %04x:%04x\n", seg, offset);
struct bregs br; memset(&br, 0, sizeof(br)); br.flags = F_IF; br.ax = bdf; br.bx = 0xffff; br.dx = 0xffff; br.es = SEG_BIOS; br.di = get_pnp_offset(); br.code = SEGOFF(seg, offset); start_preempt(); farcall16big(&br); finish_preempt(); }
The macro OPTION_ROM_INITVECTOR, passed as "offset" to __callrom, matches the label "_rom_header_entry" in "vgasrc/vgaentry.S". In more concrete terms, it is offset 3.
Basically, if you know where a well-formed option ROM is located in memory, then you post it by simply jumping to its entry point (after setting up some registers etc). The entry point to jump to is simply offset 3 of the ROM. So, in:
callrom() __callrom() _rom_header_entry [vgasrc/vgaentry.S] vga_post() [vgasrc/vgainit.c]
the __callrom()-->_rom_header_entry "call" does not happen by name. It happens "blindly" in a sense, as if through a function pointer in C. I omitted the farcall16big() function from the call chain (which actually implements the jump) because it was not relevant for your purposes.
But, in my case I use both bios.bin and vgabios.bin to booting up my guest OS (I'm using qemu). Apparently, I'm not clearly understanding the difference between vgabios inside bios.bin and vgabios-stdvga.bin. Could you tell me the difference?
vgabios is not "inside" bios.bin. It is not built into it. "bios.bin" is loaded by qemu, placed at a special address, and executed.
"vgabios.bin", which is a separate output file of the SeaBIOS build process, is also loaded by qemu, and presented as the PCI option ROM of the VGA card. SeaBIOS first copies it below 1MB in RAM, and then posts it. The copying ("mapping") happens in init_pcirom().
init_pcirom() lookup_hardcode() || map_pcirom() init_optionrom() callrom() ...
And, I'm trying to debug a vgabios.bin by examining with qemu+gdb. Especially, I'm trying to set the break-point to the entry point of vgabios.bin and I'm not quite sure how to do this since I don't know the address where vgabios.bin is loaded. I would appreciate if you give me some hint about this.
I have no clue if you can debug real mode code and/or set a breakpoint on it, but the vgabios entry point (see "_rom_header_entry") should be at C000:0003.
Laszlo