qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/3] [QEMU] Add BIOS splash image


From: Laurent Vivier
Subject: [Qemu-devel] [PATCH 3/3] [QEMU] Add BIOS splash image
Date: Tue, 16 Dec 2008 16:20:10 +0100

This patch adds to qemu the function 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 <address@hidden>
---
 qemu/Makefile.target      |    2 +-
 qemu/configure            |   19 +++
 qemu/hw/bootmenu_pixmap.h |  231 +++++++++++++++++++++++++++++++++++++
 qemu/hw/fw_cfg.h          |    1 +
 qemu/hw/pc.c              |  276 ++++++++++++++++++++++++++++++++++++++++++++-
 qemu/sysemu.h             |    1 +
 qemu/vl.c                 |   19 +++
 7 files changed, 545 insertions(+), 4 deletions(-)
 create mode 100644 qemu/hw/bootmenu_pixmap.h

diff --git a/qemu/Makefile.target b/qemu/Makefile.target
index d6a6479..65f0252 100644
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -894,7 +894,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 1f8b9b4..7f20a4b 100755
--- a/qemu/configure
+++ b/qemu/configure
@@ -833,6 +833,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
@@ -1187,6 +1200,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"
@@ -1477,6 +1491,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/bootmenu_pixmap.h b/qemu/hw/bootmenu_pixmap.h
new file mode 100644
index 0000000..a33ddb4
--- /dev/null
+++ b/qemu/hw/bootmenu_pixmap.h
@@ -0,0 +1,231 @@
+/*  GIMP header image file format (INDEXED): /home/vivierl/Desktop/Press F12 
for boot menu.h  */
+
+#define SPLASH_BOOTMENU_WIDTH 216
+#define SPLASH_BOOTMENU_HEIGHT 16
+
+static char bootmenu_pixmap[] = {
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       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/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 3cf5a73..74ba523 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -36,6 +36,9 @@
 #include "virtio-blk.h"
 #include "virtio-balloon.h"
 #include "device-assignment.h"
+#ifdef CONFIG_PNGLITE
+#include <pnglite.h>
+#endif
 
 #include "qemu-kvm.h"
 
@@ -423,7 +426,256 @@ static void bochs_bios_write(void *opaque, uint32_t addr, 
uint32_t val)
     }
 }
 
-static void bochs_bios_init(void)
+#ifdef CONFIG_PNGLITE
+struct logo_header {
+    uint16_t        signature;
+    uint16_t        duration;
+    uint8_t         fadein;
+    uint8_t         fadeout;
+    uint8_t         bootmenu;
+    uint8_t         pad;
+    uint32_t        size;
+};
+
+#define LOGO_HDR_MAGIC 0x66BB
+
+struct splash_info {
+    uint16_t data;
+    DisplayState *ds;
+    int width;
+    int height;
+    struct logo_header *logo;
+};
+
+#define LOGO_CMD_NOP           0x00
+#define LOGO_CMD_SET_OFFSET    0x01
+#define LOGO_CMD_SHOW_BMP      0x02
+#define        LOGO_SHOW_STEPS 16
+
+#define SPLASH_WIDTH    640
+#define SPLASH_HEIGHT   480
+#define SPLASH_BPP      4
+#define SPLASH_DURATION 2000
+
+#include "bootmenu_pixmap.h"
+
+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) - SPLASH_BOOTMENU_HEIGHT;
+    origin_x = (ds_get_width(info->ds) - SPLASH_BOOTMENU_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 < SPLASH_BOOTMENU_HEIGHT; i++) {
+        for (j = 0; j < SPLASH_BOOTMENU_WIDTH; j++ ) {
+            if (bootmenu_pixmap[i * SPLASH_BOOTMENU_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 / LOGO_SHOW_STEPS;
+                    break;
+                case 24:
+                    d[j * 3] = d[j * 3 + 1] = d[j * 3 + 2] =
+                                    255 * step / LOGO_SHOW_STEPS;
+                    break;
+            }
+        }
+        d += ds_get_linesize(info->ds);
+    }
+
+    dpy_update(info->ds, origin_x, origin_y,
+               SPLASH_BOOTMENU_WIDTH, SPLASH_BOOTMENU_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 logo_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 / LOGO_SHOW_STEPS;
+            g = g * step / LOGO_SHOW_STEPS;
+            b = b * step / LOGO_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 logo_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 logo_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(LOGO_HDR_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 LOGO_CMD_NOP:
+        break;
+
+    case LOGO_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 LOGO_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;
+
+    }
+}
+#endif /* CONFIG_PNGLITE */
+
+static void bochs_bios_init(DisplayState *ds)
 {
     void *fw_cfg;
 
@@ -441,6 +693,24 @@ 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);
+
+#ifdef CONFIG_PNGLITE
+    if (!nographic && splash_image) {
+        struct splash_info *splash;
+
+        splash = qemu_mallocz(sizeof(*splash));
+        if (!splash)
+            return;
+
+        splash->ds = ds;
+        splash->logo = NULL;
+
+        if (!fw_cfg_add_callback(fw_cfg, FW_CFG_SPLASH,
+                                 splash_controller, splash,
+                                 &splash->data, sizeof(splash->data)))
+            qemu_free(splash);
+    }
+#endif /* CONFIG_PNGLITE */
 }
 
 /* Generate an initial boot sector which sets state and jump to
@@ -977,8 +1247,6 @@ 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();
-
     cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
     i8259 = i8259_init(cpu_irq[0]);
     ferr_irq = i8259[13];
@@ -1020,6 +1288,8 @@ static void pc_init1(ram_addr_t ram_size, int 
vga_ram_size,
         }
     }
 
+    bochs_bios_init(ds);
+
     rtc_state = rtc_init(0x70, i8259[8]);
 
     qemu_register_boot_set(pc_boot_set, rtc_state);
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 7b58605..01aea0f 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -228,6 +228,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;
@@ -3986,6 +3989,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)
@@ -4195,6 +4203,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,
@@ -4323,6 +4334,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 },
@@ -5234,6 +5248,11 @@ int main(int argc, char **argv)
                 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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]