This patch adds to qemu the functions needed to display a splash image under BIOS control through the firmware control device.
It adds a "-splash" option allowing to specify the picture file name (a .PNG) to display. You can enable/disable a fade in, fade out and the bootmenu. The time to display the image can be also given (in seconds). Signed-off-by: Laurent Vivier <laurent.viv...@bull.net> --- qemu/Makefile.target | 5 +- qemu/configure | 19 +++ qemu/hw/fw_cfg.h | 1 + qemu/hw/pc.c | 11 ++- qemu/hw/press_f12.h | 231 +++++++++++++++++++++++++++++++++++++++ qemu/hw/splash.c | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++ qemu/hw/splash.h | 38 +++++++ qemu/qemu-doc.texi | 20 ++++ qemu/sysemu.h | 1 + qemu/vl.c | 19 +++ 10 files changed, 639 insertions(+), 3 deletions(-) create mode 100644 qemu/hw/press_f12.h create mode 100644 qemu/hw/splash.c create mode 100644 qemu/hw/splash.h Changelog: v2: make it generic, move splash functions to their own files, add documentation diff --git a/qemu/Makefile.target b/qemu/Makefile.target index 315c3c9..5887bba 100644 --- a/qemu/Makefile.target +++ b/qemu/Makefile.target @@ -613,6 +613,9 @@ ifndef CONFIG_USER_ONLY OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o OBJS+=fw_cfg.o +ifdef CONFIG_PNGLITE +OBJS+=splash.o +endif ifdef CONFIG_KVM OBJS+=kvm.o kvm-all.o endif @@ -865,7 +868,7 @@ firmware.o: firmware.c endif $(QEMU_PROG): $(OBJS) ../libqemu_common.a libqemu.a $(DEPLIBS) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) $(VDE_LIBS) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(PNGLITE_LIBS) $(CURSES_LIBS) $(BRLAPI_LIBS) $(VDE_LIBS) endif # !CONFIG_USER_ONLY diff --git a/qemu/configure b/qemu/configure index 5f5264f..60523fd 100755 --- a/qemu/configure +++ b/qemu/configure @@ -767,6 +767,19 @@ else fi ########################################## +# libpnglite check + +cat > $TMPC << EOF +#include <pnglite.h> +int main(void) { (void)png_init(NULL, NULL); return 0; } +EOF +if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC -lz -lpnglite 2> /dev/null ; then + pnglite=yes +else + pnglite=no +fi + +########################################## # SDL probe sdl_too_old=no @@ -1145,6 +1158,7 @@ echo "SDL support $sdl" if test "$sdl" != "no" ; then echo "SDL static link $sdl_static" fi +echo "pnglite support $pnglite" echo "curses support $curses" echo "mingw32 support $mingw32" echo "Audio drivers $audio_drv_list" @@ -1437,6 +1451,11 @@ if test "$cocoa" = "yes" ; then echo "#define CONFIG_COCOA 1" >> $config_h echo "CONFIG_COCOA=yes" >> $config_mak fi +if test "$pnglite" = "yes" ; then + echo "#define CONFIG_PNGLITE 1" >> $config_h + echo "CONFIG_PNGLITE=yes" >> $config_mak + echo "PNGLITE_LIBS=-lpnglite" >> $config_mak +fi if test "$curses" = "yes" ; then echo "#define CONFIG_CURSES 1" >> $config_h echo "CONFIG_CURSES=yes" >> $config_mak diff --git a/qemu/hw/fw_cfg.h b/qemu/hw/fw_cfg.h index ef8f378..41fdde8 100644 --- a/qemu/hw/fw_cfg.h +++ b/qemu/hw/fw_cfg.h @@ -8,6 +8,7 @@ #define FW_CFG_NOGRAPHIC 0x04 #define FW_CFG_NB_CPUS 0x05 #define FW_CFG_MACHINE_ID 0x06 +#define FW_CFG_SPLASH (FW_CFG_WRITE_CHANNEL | 0x07) #define FW_CFG_MAX_ENTRY 0x10 #define FW_CFG_WRITE_CHANNEL 0x4000 diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c index 2924b2a..f6979fe 100644 --- a/qemu/hw/pc.c +++ b/qemu/hw/pc.c @@ -36,6 +36,8 @@ #include "virtio-blk.h" #include "virtio-balloon.h" #include "device-assignment.h" +#include "splash.h" +#include "press_f12.h" #include "qemu-kvm.h" @@ -423,7 +425,7 @@ static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) } } -static void bochs_bios_init(void) +static void *bochs_bios_init(void) { void *fw_cfg; @@ -441,6 +443,8 @@ static void bochs_bios_init(void) fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + + return fw_cfg; } /* Generate an initial boot sector which sets state and jump to @@ -818,6 +822,7 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, int index; BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BlockDriverState *fd[MAX_FD]; + void *fw_cfg; if (ram_size >= 0xe0000000 ) { above_4g_mem_size = ram_size - 0xe0000000; @@ -977,7 +982,7 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, cpu_register_physical_memory((uint32_t)(-bios_size), bios_size, bios_offset | IO_MEM_ROM); - bochs_bios_init(); + fw_cfg = bochs_bios_init(); cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1); i8259 = i8259_init(cpu_irq[0]); @@ -1020,6 +1025,8 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, } } + splash_init(fw_cfg, ds, &press_f12_pixmap); + rtc_state = rtc_init(0x70, i8259[8]); qemu_register_boot_set(pc_boot_set, rtc_state); diff --git a/qemu/hw/press_f12.h b/qemu/hw/press_f12.h new file mode 100644 index 0000000..0e0fe23 --- /dev/null +++ b/qemu/hw/press_f12.h @@ -0,0 +1,231 @@ +static struct splash_pixmap press_f12_pixmap = { + .width = 216, + .height = 16, + .data = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0, + 0,0,1,1,0,0,0,0,0,1,1,1,1,1,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0, + 0,1,1,1,0,0,0,0,1,1,0,0,0,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0, + 1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,1,1,0,0,1,1,0,0,1,1,0,1,1,1,0, + 0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1, + 1,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0, + 0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0, + 0,0,0,0,1,1,1,1,1,0,0,0,1,1,0,1, + 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0, + 0,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0, + 1,1,0,0,0,1,1,1,1,1,0,0,0,1,1,0, + 1,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,1,1,1,1,1,0,0,0,0,1,1,1,0,1,1, + 0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0, + 1,1,0,0,1,1,0,0,0,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0, + 0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1, + 0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0, + 1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, + 1,1,1,0,1,1,0,0,0,1,1,0,0,0,1,1, + 0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1, + 0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0, + 0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0, + 0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0, + 0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0, + 0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0, + 1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1, + 0,1,1,0,1,1,1,1,1,1,1,0,0,0,1,1, + 0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0, + 0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1, + 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0, + 0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0, + 0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0, + 1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1, + 0,1,1,0,1,1,0,0,0,0,0,0,0,0,1,1, + 0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0, + 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0, + 0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0, + 0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0, + 1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1, + 0,1,1,0,1,1,0,0,0,0,0,0,0,0,1,1, + 0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0, + 0,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0, + 1,1,0,0,1,1,0,0,0,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0, + 0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0, + 0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0, + 1,1,0,0,0,1,1,0,0,0,0,1,1,0,1,1, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1, + 0,1,1,0,1,1,0,0,0,1,1,0,0,0,1,1, + 0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0, + 0,0,1,1,0,0,0,0, + 1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0, + 0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1, + 1,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, + 0,0,0,0,1,1,1,1,1,0,0,0,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,1,1,0,0,0,0,1,1,1,1,1,0,0,0, + 0,1,1,1,1,1,0,0,0,0,0,0,1,1,1,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1, + 0,1,1,0,0,1,1,1,1,1,0,0,0,0,1,1, + 0,0,1,1,0,0,0,1,1,1,0,1,1,0,0,0, + 0,0,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 + } +}; + diff --git a/qemu/hw/splash.c b/qemu/hw/splash.c new file mode 100644 index 0000000..0289fb3 --- /dev/null +++ b/qemu/hw/splash.c @@ -0,0 +1,297 @@ +/* + * QEMU Splash image support + * + * Copyright (c) 2008 Bull S.A.S., Laurent Vivier <laurent.viv...@bull.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <pnglite.h> + +#include "hw.h" +#include "fw_cfg.h" +#include "splash.h" +#include "console.h" +#include "sysemu.h" + +struct splash_header { + uint16_t signature; + uint16_t duration; + uint8_t fadein; + uint8_t fadeout; + uint8_t bootmenu; + uint8_t pad; + uint32_t size; +}; + +#define SPLASH_MAGIC 0x66BB + +struct splash_info { + uint16_t data; + DisplayState *ds; + struct splash_pixmap *pixmap; + int width; + int height; + struct splash_header *logo; +}; + +#define SPLASH_CMD_NOP 0x00 +#define SPLASH_CMD_SET_OFFSET 0x01 +#define SPLASH_CMD_SHOW_BMP 0x02 +#define SPLASH_SHOW_STEPS 16 + +#define SPLASH_WIDTH 640 +#define SPLASH_HEIGHT 480 +#define SPLASH_BPP 4 +#define SPLASH_DURATION 2000 + +static void splash_show_info(struct splash_info *info, int step) +{ + int i, j; + uint8_t *d; + int origin_x, origin_y; + + origin_y = ds_get_height(info->ds) - info->pixmap->height; + origin_x = (ds_get_width(info->ds) - info->pixmap->width) / 2; + + d = ds_get_data(info->ds); + d += origin_y * ds_get_linesize(info->ds); + d += origin_x * ds_get_bits_per_pixel(info->ds) / 8; + + for (i = 0; i < info->pixmap->height; i++) { + for (j = 0; j < info->pixmap->width; j++ ) { + if (info->pixmap->data[i * info->pixmap->width + j]) + switch(ds_get_bits_per_pixel(info->ds)) { + case 32: + d[j * 4] = d[j * 4 + 1] = d[j * 4 + 2] = + 255 * step / SPLASH_SHOW_STEPS; + break; + case 24: + d[j * 3] = d[j * 3 + 1] = d[j * 3 + 2] = + 255 * step / SPLASH_SHOW_STEPS; + break; + } + } + d += ds_get_linesize(info->ds); + } + + dpy_update(info->ds, origin_x, origin_y, + info->pixmap->width, info->pixmap->height); +} + +static void splash_show(struct splash_info *info, int step) +{ + int i, j; + uint8_t *d, *s; + int origin_x, origin_y; + + if (ds_get_width(info->ds) < SPLASH_WIDTH || + ds_get_height(info->ds) < SPLASH_HEIGHT || + ds_get_bits_per_pixel(info->ds) < 24) + return; + + origin_y = (ds_get_height(info->ds) - info->height) / 2; + origin_x = (ds_get_width(info->ds) - info->width) / 2; + d = ds_get_data(info->ds); + d += origin_y * ds_get_linesize(info->ds); + d += origin_x * ds_get_bits_per_pixel(info->ds) / 8; + s = (uint8_t*)info->logo + sizeof(struct splash_header); + for (i = 0; i < info->height; i++) { + for (j = 0; j < info->width; j++ ) { + int r, g, b; + b = s[j * SPLASH_BPP + 0]; + g = s[j * SPLASH_BPP + 1]; + r = s[j * SPLASH_BPP + 2]; + r = r * step / SPLASH_SHOW_STEPS; + g = g * step / SPLASH_SHOW_STEPS; + b = b * step / SPLASH_SHOW_STEPS; + switch(ds_get_bits_per_pixel(info->ds)) { + case 32: + d[j * 4] = r; d[j * 4 + 1] = g; d[j * 4 + 2] = b; + break; + case 24: + d[j * 3] = r; d[j * 3 + 1] = g; d[j * 3] = b; + break; + } + } + s += info->width * 4; + d += ds_get_linesize(info->ds); + } + + if (info->logo->bootmenu) + splash_show_info(info, step); + + dpy_update(info->ds, origin_x, origin_y, info->width, info->height); +} + +static void splash_load(struct splash_info *info) +{ + int len; + png_t png; + char buf[128]; + char file[1024]; + static const char * const params[] = { "file", "fadein", "fadeout", + "duration", "bootmenu", NULL }; + + if (check_params(buf, sizeof(buf), params, splash_image) < 0) { + fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n", + buf, splash_image); + return; + } + + if (!get_param_value(file, sizeof(file), "file", splash_image)) + return; + + /* load splash image */ + + png_init(qemu_malloc, qemu_free); + + if (png_open_file(&png, file) != PNG_NO_ERROR) + return; + + if (png.bpp != SPLASH_BPP || png.width > SPLASH_WIDTH || + png.height > SPLASH_HEIGHT) { + fprintf(stderr, "qemu: splash image %s is greater than %dx%dx%d\n", + file, SPLASH_WIDTH, SPLASH_HEIGHT, SPLASH_BPP * 8); + return; + } + + len = png.width * png.height * png.bpp + sizeof(struct splash_header); + info->logo = qemu_malloc(len); + if (info->logo == NULL) { + png_close_file(&png); + fprintf(stderr, "qemu: cannot allocate memory for %s\n", file); + return; + } + + if (png_get_data(&png, + (uint8_t*)info->logo + + sizeof(struct splash_header)) != PNG_NO_ERROR) { + fprintf(stderr, "Cannot load splash screen %s\n", buf); + free(info->logo); + info->logo = NULL; + png_close_file(&png); + return; + } + png_close_file(&png); + + info->width = png.width; + info->height = png.height; + info->logo->signature = cpu_to_le16(SPLASH_MAGIC); + info->logo->size = cpu_to_le32(len); + + info->logo->fadein = 1; + if (get_param_value(buf, sizeof(buf), "fadein", splash_image)) { + if (!strcmp(buf, "off")) + info->logo->fadein = 0; + else if (strcmp(buf, "on")) + fprintf(stderr, "qemu: '%s' invalid splash option\n", splash_image); + } + + info->logo->fadeout = 1; + if (get_param_value(buf, sizeof(buf), "fadeout", splash_image)) { + if (!strcmp(buf, "off")) + info->logo->fadeout = 0; + else if (strcmp(buf, "on")) + fprintf(stderr, "qemu: '%s' invalid splash option\n", splash_image); + } + + info->logo->bootmenu = 1; + if (get_param_value(buf, sizeof(buf), "bootmenu", splash_image)) { + if (!strcmp(buf, "off")) + info->logo->bootmenu = 0; + else if (strcmp(buf, "on")) + fprintf(stderr, "qemu: '%s' invalid splash option\n", splash_image); + } + + info->logo->duration = SPLASH_DURATION; + if (get_param_value(buf, sizeof(buf), "duration", splash_image)) { + int duration = strtol(buf, NULL, 0); + if (duration != 0 || errno != EINVAL) + info->logo->duration = duration * 1000; + } +} + +/* free splash image */ + +static void splash_unload(struct splash_info *info) +{ + if (info->logo) + free(info->logo); + + info->logo = NULL; +} + +static void splash_controller(void *opaque, uint8_t *data) +{ + struct splash_info *info = (struct splash_info *)opaque; + uint16_t cmd = *(uint16_t*)data; + + switch (cmd & 0x00FF) { + + case SPLASH_CMD_NOP: + break; + + case SPLASH_CMD_SHOW_BMP: + cmd >>= 8; + if (info->logo == NULL) { + splash_load(info); + if (info->logo == NULL) + break; + } + splash_show(info, cmd); + if (cmd == 0) + splash_unload(info); + break; + + case SPLASH_CMD_SET_OFFSET: + if (info->logo == NULL) { + splash_load(info); + if (info->logo == NULL) + break; + } + cmd >>= 8; + if (cmd >= info->logo->size) + break; + memcpy(&info->data, ((char*)info->logo) + cmd, + sizeof(info->data)); + break; + + } +} + +void splash_init(void *fw_cfg, DisplayState *ds, struct splash_pixmap *pixmap) +{ + if (!nographic && splash_image) { + struct splash_info *splash; + + splash = qemu_mallocz(sizeof(*splash)); + if (!splash) + return; + + splash->ds = ds; + splash->pixmap = pixmap; + splash->logo = NULL; + + if (!fw_cfg_add_callback(fw_cfg, FW_CFG_SPLASH, + splash_controller, splash, + &splash->data, sizeof(splash->data))) + qemu_free(splash); + } +} diff --git a/qemu/hw/splash.h b/qemu/hw/splash.h new file mode 100644 index 0000000..54f4fc7 --- /dev/null +++ b/qemu/hw/splash.h @@ -0,0 +1,38 @@ +/* + * QEMU Splash image support + * + * Copyright (c) 2008 Bull S.A.S., Laurent Vivier <laurent.viv...@bull.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +struct splash_pixmap { + int width, height; + char data[]; +}; + +#ifdef CONFIG_PNGLITE +void splash_init(void *fw_cfg, DisplayState *ds, struct splash_pixmap *pixmap); +#else +static inline void splash_init(void *fw_cfg, DisplayState *ds, + struct splash_pixmap *pixmap) +{ + return; +} +#endif diff --git a/qemu/qemu-doc.texi b/qemu/qemu-doc.texi index e004a26..f0adf7c 100644 --- a/qemu/qemu-doc.texi +++ b/qemu/qemu-doc.texi @@ -426,6 +426,26 @@ Use it when installing Windows 2000 to avoid a disk full bug. After Windows 2000 is installed, you no longer need this option (this option slows down the IDE transfers). +...@item -splash @var{option}[,@var{option}[,@var{option}[,...]]] +Display a splash image at BIOS startup. This option is available only if +libpnglite is available on your system and if your BIOS has support for +splash image. +...@table @code +...@item fi...@var{file} +This option defines the image to display at BIOS startup. The file must +be a PNG file, true color. +...@item fade...@var{fadein} +...@var{fadein} is "on" or "off", to enable or disable a fade in when the image +is displayed. +...@item fadeo...@var{fadeout} +...@var{fadeout} is "on" or "off", to enable or disable a fade out when the image +is cleared. +...@item bootme...@var{bootmenu} +...@var{bootmenu} is "on" or "off", to enable or disable the boot menu. +...@item durati...@var{duration} +The splash image is displayed @var{duration} seconds. +...@end table + @item -option-rom @var{file} Load the contents of @var{file} as an option ROM. This option is useful to load things like EtherBoot. diff --git a/qemu/sysemu.h b/qemu/sysemu.h index 5abda5c..ff8669b 100644 --- a/qemu/sysemu.h +++ b/qemu/sysemu.h @@ -99,6 +99,7 @@ extern int win2k_install_hack; extern int alt_grab; extern int usb_enabled; extern int smp_cpus; +extern char *splash_image; extern int cursor_hide; extern int graphic_rotate; extern int no_quit; diff --git a/qemu/vl.c b/qemu/vl.c index 26d767a..56cc1ac 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -229,6 +229,9 @@ int usb_enabled = 0; const char *assigned_devices[MAX_DEV_ASSIGN_CMDLINE]; int assigned_devices_index; int smp_cpus = 1; +#ifdef CONFIG_PNGLITE +char *splash_image = NULL; +#endif const char *vnc_display; int acpi_enabled = 1; int fd_bootchk = 1; @@ -3987,6 +3990,11 @@ static void help(int exitcode) #ifdef TARGET_I386 "-win2k-hack use it when installing Windows 2000 to avoid a disk full bug\n" #endif +#ifdef CONFIG_PNGLITE + "-splash file=name.png[,fadein=on|off][,fadeout=on|off]\n" + " [,bootmenu=on|off][,duration=seconds]\n" + " display a splash image at BIOS startup\n" +#endif "-usb enable the USB driver (will be the default soon)\n" "-usbdevice name add the host or guest USB device 'name'\n" #if defined(TARGET_PPC) || defined(TARGET_SPARC) @@ -4196,6 +4204,9 @@ enum { QEMU_OPTION_kernel_kqemu, QEMU_OPTION_enable_kvm, QEMU_OPTION_win2k_hack, +#ifdef CONFIG_PNGLITE + QEMU_OPTION_splash, +#endif QEMU_OPTION_usb, QEMU_OPTION_usbdevice, QEMU_OPTION_smp, @@ -4324,6 +4335,9 @@ static const QEMUOption qemu_options[] = { #endif { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, +#ifdef CONFIG_PNGLITE + { "splash", HAS_ARG, QEMU_OPTION_splash }, +#endif { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, { "smp", HAS_ARG, QEMU_OPTION_smp }, { "vnc", HAS_ARG, QEMU_OPTION_vnc }, @@ -5237,6 +5251,11 @@ int main(int argc, char **argv, char **envp) win2k_install_hack = 1; break; #endif +#ifdef CONFIG_PNGLITE + case QEMU_OPTION_splash: + splash_image = optarg; + break; +#endif #ifdef USE_KQEMU case QEMU_OPTION_no_kqemu: kqemu_allowed = 0; -- 1.5.6.5 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html