kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2][v2] Add BIOS splash image support
@ 2008-12-18 14:51 Laurent Vivier
  2008-12-18 14:51 ` [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Laurent Vivier @ 2008-12-18 14:51 UTC (permalink / raw)
  To: kvm developers; +Cc: qemu developers, bochs developers

This series of patches adds a nice BIOS startup splash screen.

It adds a "-splash" option allowing to specify the picture file name (a 640x480 (or less) and true color 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).

Idea stollen from VirtualBox.

[PATCH 1/2] [BIOS] Add splash image support
[PATCH 2/2] [QEMU] Add BIOS splash image


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2][v2][BIOS] Add splash image support
  2008-12-18 14:51 [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
@ 2008-12-18 14:51 ` Laurent Vivier
  2008-12-18 14:51   ` [PATCH 2/2][v2][QEMU] Add BIOS splash image Laurent Vivier
  2008-12-18 16:21 ` [PATCH 0/2][v2] Add BIOS splash image support Anthony Liguori
  2008-12-18 16:24 ` Anthony Liguori
  2 siblings, 1 reply; 5+ messages in thread
From: Laurent Vivier @ 2008-12-18 14:51 UTC (permalink / raw)
  To: kvm developers; +Cc: qemu developers, bochs developers, Laurent Vivier

This patch adds Qemu firmware configuration device interface to display
a splash image at BIOS startup.

Idea stollen from VirtualBox.

Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
---
 bios/Makefile  |    4 +-
 bios/rombios.c |  142 ++++++++++++++++++++++++++++++++++++-------------------
 bios/splash.c  |  144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bios/splash.h  |   32 ++++++++++++
 4 files changed, 271 insertions(+), 51 deletions(-)
 create mode 100644 bios/splash.c
 create mode 100644 bios/splash.h

Changelog:
v2: totally remove code from VirtualBox to not bring GPLv2 to bios.

diff --git a/bios/Makefile b/bios/Makefile
index a2759a9..605d31f 100644
--- a/bios/Makefile
+++ b/bios/Makefile
@@ -79,7 +79,7 @@ dist-clean: clean
 bios-clean:
 	rm -f  BIOS-bochs-*
 
-BIOS-bochs-legacy: rombios.c apmbios.S biossums rombios.h
+BIOS-bochs-legacy: rombios.c apmbios.S biossums rombios.h splash.c splash.h
 	$(GCC) $(BIOS_BUILD_DATE) -DLEGACY -E -P $< > _rombiosl_.c
 	$(BCC) -o rombiosl.s -C-c -D__i86__ -0 -S _rombiosl_.c
 	sed -e 's/^\.text//' -e 's/^\.data//' rombiosl.s > _rombiosl_.s
@@ -90,7 +90,7 @@ BIOS-bochs-legacy: rombios.c apmbios.S biossums rombios.h
 	rm -f  _rombiosl_.s
 
 
-rombios16.bin: rombios.c apmbios.S biossums rombios.h
+rombios16.bin: rombios.c apmbios.S biossums rombios.h splash.c splash.h
 	$(GCC) $(BIOS_BUILD_DATE) -E -P $< > _rombios_.c
 	$(BCC) -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c
 	sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s
diff --git a/bios/rombios.c b/bios/rombios.c
index 9a1cdd6..a02b50f 100644
--- a/bios/rombios.c
+++ b/bios/rombios.c
@@ -1433,6 +1433,22 @@ void uart_tx_byte(base_port, data)
 #endif
 
   void
+set_video(mode)
+  Bit8u  mode;
+{
+  ASM_START
+  push bp
+  mov  bp, sp
+
+  mov  ah, #0x00
+  mov  al, 4[bp]
+  int  #0x10
+
+  pop  bp
+  ASM_END
+}
+
+  void
 wrch(c)
   Bit8u  c;
 {
@@ -1533,6 +1549,8 @@ void put_str(action, segment, offset)
   }
 }
 
+#define TICKS_PER_SECONDS  18
+
   void
 delay_ticks(ticks)
   Bit16u ticks;
@@ -1917,6 +1935,10 @@ shutdown_status_panic(status)
   BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
 }
 
+#ifdef BX_QEMU
+#include "splash.c"
+#endif
+
 //--------------------------------------------------------------------------
 // print_bios_banner
 //   displays a the bios version
@@ -1924,6 +1946,10 @@ shutdown_status_panic(status)
 void
 print_bios_banner()
 {
+#ifdef BX_QEMU
+  if (splash_enabled())
+    return;
+#endif
   printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
     BIOS_BUILD_DATE, bios_cvs_version_string);
   printf(
@@ -2021,65 +2047,77 @@ interactive_bootkey()
   Bit16u ss = get_SS();
   Bit16u valid_choice = 0;
 
+#ifdef BX_QEMU
+  if (splash_enabled()) {
+    Bit16u duration;
+
+    splash_show();
+    duration = splash_duration();
+    if (!check_for_keystroke())
+      delay_ticks_and_check_for_keystroke(TICKS_PER_SECONDS, duration / 1000);
+    splash_hide();
+    if (!splash_display_boot_list())
+      return;
+  } else
+#endif // BX_QEMU
+  {
+    while (check_for_keystroke())
+      get_keystroke();
+    printf("Press F12 for boot menu.\n\n");
+    delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */
+  }
+  if (!check_for_keystroke())
+    return;
+  scan_code = get_keystroke();
+  if (scan_code != 0x58) /* F12 */
+        return;
+
   while (check_for_keystroke())
     get_keystroke();
 
-  printf("Press F12 for boot menu.\n\n");
+  printf("Select boot device:\n\n");
 
-  delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */
-  if (check_for_keystroke())
+  count = read_word(IPL_SEG, IPL_COUNT_OFFSET);
+  for (i = 0; i < count; i++)
   {
-    scan_code = get_keystroke();
-    if (scan_code == 0x58) /* F12 */
+    memcpyb(ss, &e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e));
+    printf("%d. ", i+1);
+    switch(e.type)
     {
-      while (check_for_keystroke())
-        get_keystroke();
-
-      printf("Select boot device:\n\n");
-
-      count = read_word(IPL_SEG, IPL_COUNT_OFFSET);
-      for (i = 0; i < count; i++)
-      {
-        memcpyb(ss, &e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e));
-        printf("%d. ", i+1);
-        switch(e.type)
+      case IPL_TYPE_FLOPPY:
+      case IPL_TYPE_HARDDISK:
+      case IPL_TYPE_CDROM:
+        printf("%s\n", drivetypes[e.type]);
+        break;
+      case IPL_TYPE_BEV:
+        printf("%s", drivetypes[4]);
+        if (e.description != 0)
         {
-          case IPL_TYPE_FLOPPY:
-          case IPL_TYPE_HARDDISK:
-          case IPL_TYPE_CDROM:
-            printf("%s\n", drivetypes[e.type]);
-            break;
-          case IPL_TYPE_BEV:
-            printf("%s", drivetypes[4]);
-            if (e.description != 0)
-            {
-              memcpyb(ss, &description, (Bit16u)(e.description >> 16), (Bit16u)(e.description & 0xffff), 32);
-              description[32] = 0;
-              printf(" [%S]", ss, description);
-           }
-           printf("\n");
-           break;
-        }
-      }
+          memcpyb(ss, &description, (Bit16u)(e.description >> 16), (Bit16u)(e.description & 0xffff), 32);
+          description[32] = 0;
+          printf(" [%S]", ss, description);
+       }
+       printf("\n");
+       break;
+    }
+  }
 
-      count++;
-      while (!valid_choice) {
-        scan_code = get_keystroke();
-        if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */
-        {
-          valid_choice = 1;
-        }
-        else if (scan_code <= count)
-        {
-          valid_choice = 1;
-          scan_code -= 1;
-          /* Set user selected device */
-          write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, scan_code);
-        }
-      }
-    printf("\n");
+  count++;
+  while (!valid_choice) {
+    scan_code = get_keystroke();
+    if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */
+    {
+      valid_choice = 1;
+    }
+    else if (scan_code <= count)
+    {
+      valid_choice = 1;
+      scan_code -= 1;
+      /* Set user selected device */
+      write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, scan_code);
     }
   }
+  printf("\n");
 }
 #endif // BX_ELTORITO_BOOT
 
@@ -2706,6 +2744,9 @@ void ata_detect( )
           break;
         }
 
+#ifdef BX_QEMU
+      if (!splash_enabled()) {
+#endif
       switch (type) {
         case ATA_TYPE_ATA:
           printf("ata%d %s: ",channel,slave?" slave":"master");
@@ -2727,6 +2768,9 @@ void ata_detect( )
           printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master");
           break;
         }
+#ifdef BX_QEMU
+        }
+#endif
       }
     }
 
diff --git a/bios/splash.c b/bios/splash.c
new file mode 100644
index 0000000..07921b3
--- /dev/null
+++ b/bios/splash.c
@@ -0,0 +1,144 @@
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+
+#include "splash.h"
+
+#define BIOS_CFG_IOPORT    0x0510
+#define BIOS_CFG_SIGNATURE 0x0000
+#define BIOS_CFG_SPLASH    0x4007
+
+#define SPLASH_VALUE(_field)	splash_offset( splash_offsetof(_field), \
+                                               splash_sizeof(_field) )
+Bit16u
+splash_offset(offset, size)
+  Bit8u offset;
+  Bit8u size;
+{
+  Bit16u word;
+
+  outw(BIOS_CFG_IOPORT, BIOS_CFG_SPLASH);
+  outb(BIOS_CFG_IOPORT + 1, SPLASH_CMD_SET_OFFSET);
+  outb(BIOS_CFG_IOPORT + 1, offset);
+
+  word = inb(BIOS_CFG_IOPORT + 1);
+  if (size == 2)
+    word = (inb(BIOS_CFG_IOPORT + 1) << 8) | word;
+
+  return word;
+}
+
+void
+splash_show_bmp(step)
+  Bit16u step;
+{
+  outw(BIOS_CFG_IOPORT, BIOS_CFG_SPLASH);
+  outb(BIOS_CFG_IOPORT + 1, SPLASH_CMD_SHOW_BMP);
+  outb(BIOS_CFG_IOPORT + 1, step);
+
+  return;
+}
+
+Bit8u
+splash_enabled()
+{
+  Bit8u	fadein, fadeout, bootmenu;
+  Bit16u duration;
+
+  /* check QEMU signature */
+
+  outw(BIOS_CFG_IOPORT, BIOS_CFG_SIGNATURE);
+  if (inb(BIOS_CFG_IOPORT + 1) != 'Q')
+      return 0;
+  if (inb(BIOS_CFG_IOPORT + 1) != 'E')
+      return 0;
+  if (inb(BIOS_CFG_IOPORT + 1) != 'M')
+      return 0;
+  if (inb(BIOS_CFG_IOPORT + 1) != 'U')
+      return 0;
+
+  /* check splash signature */
+
+  if (SPLASH_VALUE(signature) != SPLASH_MAGIC)
+      return 0;
+
+  /* Get options */
+
+  fadein = SPLASH_VALUE(fadein);
+  fadeout = SPLASH_VALUE(fadeout);
+  duration = SPLASH_VALUE(duration);
+
+  return (fadein || fadeout || duration);
+}
+
+void
+splash_show()
+{
+  Bit8u fadein;
+  Bit16u i;
+
+  set_video(0x12); /* 640x480 */
+
+  fadein = SPLASH_VALUE(fadein);
+
+  if (fadein)
+  {
+    delay_ticks_and_check_for_keystroke(TICKS_PER_SECONDS / 18, 1);
+    /* "0" means unload image from memory, used in splash_hide() */
+    for (i = 1; !check_for_keystroke() && i < SPLASH_SHOW_STEPS; i++)
+    {
+      splash_show_bmp(i);
+      delay_ticks_and_check_for_keystroke(TICKS_PER_SECONDS / 18, 1);
+    }
+  }
+
+  if (!check_for_keystroke())
+    splash_show_bmp(SPLASH_SHOW_STEPS);
+
+  return;
+}
+
+void
+splash_hide()
+{
+  Bit8u fadeout;
+  Bit16u i;
+
+  fadeout = SPLASH_VALUE(fadeout);
+
+  if (fadeout)
+  {
+    for (i = SPLASH_SHOW_STEPS; !check_for_keystroke() && i > 0 ; i--)
+    {
+      splash_show_bmp(i);
+      delay_ticks_and_check_for_keystroke(TICKS_PER_SECONDS / 18, 1);
+    }
+  }
+  splash_show_bmp(0);
+
+  set_video(0x03);	/* text mode */
+
+  return;
+}
+
+Bit8u
+splash_display_boot_list()
+{
+ return SPLASH_VALUE(bootmenu);
+}
+
+Bit16u
+splash_duration()
+{
+  return SPLASH_VALUE(duration);
+}
diff --git a/bios/splash.h b/bios/splash.h
new file mode 100644
index 0000000..1b34978
--- /dev/null
+++ b/bios/splash.h
@@ -0,0 +1,32 @@
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+
+struct splash_header {
+    Bit16u        signature;
+    Bit16u        duration;
+    Bit8u         fadein;
+    Bit8u         fadeout;
+    Bit8u         bootmenu;
+    Bit8u         pad;
+    Bit32u        size;
+};
+
+#define SPLASH_MAGIC    0x66BB
+#define SPLASH_CMD_NOP            0x00
+#define SPLASH_CMD_SET_OFFSET     0x01
+#define SPLASH_CMD_SHOW_BMP       0x02
+#define         SPLASH_SHOW_STEPS 16
+
+#define splash_offsetof(_field) (&((struct splash_header *)0)->_field)
+#define splash_sizeof(_field) (sizeof(((struct splash_header *)0)->_field))
-- 
1.5.6.5


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2][v2][QEMU] Add BIOS splash image
  2008-12-18 14:51 ` [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
@ 2008-12-18 14:51   ` Laurent Vivier
  0 siblings, 0 replies; 5+ messages in thread
From: Laurent Vivier @ 2008-12-18 14:51 UTC (permalink / raw)
  To: kvm developers; +Cc: qemu developers, bochs developers, Laurent Vivier

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.Vivier@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.Vivier@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.Vivier@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 file=@var{file}
+This option defines the image to display at BIOS startup. The file must
+be a PNG file, true color.
+@item fadein=@var{fadein}
+@var{fadein} is "on" or "off", to enable or disable a fade in when the image
+is displayed.
+@item fadeout=@var{fadeout}
+@var{fadeout} is "on" or "off", to enable or disable a fade out when the image
+is cleared.
+@item bootmenu=@var{bootmenu}
+@var{bootmenu} is "on" or "off", to enable or disable the boot menu.
+@item duration=@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


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/2][v2] Add BIOS splash image support
  2008-12-18 14:51 [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
  2008-12-18 14:51 ` [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
@ 2008-12-18 16:21 ` Anthony Liguori
  2008-12-18 16:24 ` Anthony Liguori
  2 siblings, 0 replies; 5+ messages in thread
From: Anthony Liguori @ 2008-12-18 16:21 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm developers, qemu developers, bochs developers

Laurent Vivier wrote:
> This series of patches adds a nice BIOS startup splash screen.
>
> It adds a "-splash" option allowing to specify the picture file name (a 640x480 (or less) and true color 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).
>
> Idea stollen from VirtualBox.
>
> [PATCH 1/2] [BIOS] Add splash image support
> [PATCH 2/2] [QEMU] Add BIOS splash image
>   

Can you resubmit against QEMU and upstream bochs?  I've done the port 
myself, it's pretty easy.

Regards,

Anthony Liguori

> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>   


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/2][v2] Add BIOS splash image support
  2008-12-18 14:51 [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
  2008-12-18 14:51 ` [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
  2008-12-18 16:21 ` [PATCH 0/2][v2] Add BIOS splash image support Anthony Liguori
@ 2008-12-18 16:24 ` Anthony Liguori
  2 siblings, 0 replies; 5+ messages in thread
From: Anthony Liguori @ 2008-12-18 16:24 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm developers, qemu developers, bochs developers

Laurent Vivier wrote:
> This series of patches adds a nice BIOS startup splash screen.
>
> It adds a "-splash" option allowing to specify the picture file name (a 640x480 (or less) and true color 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).
>
> Idea stollen from VirtualBox.
>
> [PATCH 1/2] [BIOS] Add splash image support
> [PATCH 2/2] [QEMU] Add BIOS splash image
>   

So my general feeling here is that this code is well isolated and 
provides a feature that some people will find interesting.  I know I 
personally am interested in this feature.  I also think that a good 
number of vendors will want to use this mechanism to brand their 
virtualization offerings.

So I'm inclined to take this patch set unless there is objection.  I 
don't necessarily disagree with some of the feedback about making the 
BIOS not delay at all but I think that's an orthogonal discussion to 
this one.  The Press F12 thing also annoys me and I'd be happy to look 
at patches to make it optional.

Regards,

Anthony Liguori

> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>   


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-12-18 16:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-18 14:51 [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
2008-12-18 14:51 ` [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
2008-12-18 14:51   ` [PATCH 2/2][v2][QEMU] Add BIOS splash image Laurent Vivier
2008-12-18 16:21 ` [PATCH 0/2][v2] Add BIOS splash image support Anthony Liguori
2008-12-18 16:24 ` Anthony Liguori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).