qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support
@ 2008-12-18 14:51 Laurent Vivier
  2008-12-18 14:51 ` [Qemu-devel] [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Laurent Vivier @ 2008-12-18 14:51 UTC (permalink / raw)
  To: kvm developers; +Cc: bochs developers, qemu 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] 8+ messages in thread

* [Qemu-devel] [PATCH 1/2][v2][BIOS] Add splash image support
  2008-12-18 14:51 [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
@ 2008-12-18 14:51 ` Laurent Vivier
  2008-12-18 14:51   ` [Qemu-devel] [PATCH 2/2][v2][QEMU] Add BIOS splash image Laurent Vivier
  2008-12-18 16:21 ` [Qemu-devel] Re: [PATCH 0/2][v2] Add BIOS splash image support Anthony Liguori
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Laurent Vivier @ 2008-12-18 14:51 UTC (permalink / raw)
  To: kvm developers; +Cc: bochs developers, qemu 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] 8+ messages in thread

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

* [Qemu-devel] Re: [PATCH 0/2][v2] Add BIOS splash image support
  2008-12-18 14:51 [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
  2008-12-18 14:51 ` [Qemu-devel] [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
@ 2008-12-18 16:21 ` Anthony Liguori
  2008-12-18 16:24 ` Anthony Liguori
  2008-12-18 18:23 ` [Qemu-devel] " andrzej zaborowski
  3 siblings, 0 replies; 8+ messages in thread
From: Anthony Liguori @ 2008-12-18 16:21 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: bochs developers, qemu developers, kvm 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] 8+ messages in thread

* [Qemu-devel] Re: [PATCH 0/2][v2] Add BIOS splash image support
  2008-12-18 14:51 [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
  2008-12-18 14:51 ` [Qemu-devel] [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
  2008-12-18 16:21 ` [Qemu-devel] Re: [PATCH 0/2][v2] Add BIOS splash image support Anthony Liguori
@ 2008-12-18 16:24 ` Anthony Liguori
  2008-12-18 18:23 ` [Qemu-devel] " andrzej zaborowski
  3 siblings, 0 replies; 8+ messages in thread
From: Anthony Liguori @ 2008-12-18 16:24 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: bochs developers, qemu developers, kvm 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] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support
  2008-12-18 14:51 [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
                   ` (2 preceding siblings ...)
  2008-12-18 16:24 ` Anthony Liguori
@ 2008-12-18 18:23 ` andrzej zaborowski
  2008-12-18 18:40   ` Laurent Vivier
  2008-12-18 19:14   ` Anthony Liguori
  3 siblings, 2 replies; 8+ messages in thread
From: andrzej zaborowski @ 2008-12-18 18:23 UTC (permalink / raw)
  To: qemu-devel

2008/12/18 Laurent Vivier <Laurent.Vivier@bull.net>:
> 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.

Maybe having a default splash image in the same directory as the BIOS
binary, with hardcoded path, would make sense?  Then instead of adding
-splash you could override with -L.  A linux distribution could
override it too.

Cheers

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

* Re: [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support
  2008-12-18 18:23 ` [Qemu-devel] " andrzej zaborowski
@ 2008-12-18 18:40   ` Laurent Vivier
  2008-12-18 19:14   ` Anthony Liguori
  1 sibling, 0 replies; 8+ messages in thread
From: Laurent Vivier @ 2008-12-18 18:40 UTC (permalink / raw)
  To: qemu-devel


Le 18 déc. 08 à 19:23, andrzej zaborowski a écrit :

> 2008/12/18 Laurent Vivier <Laurent.Vivier@bull.net>:
>> 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.
>
> Maybe having a default splash image in the same directory as the BIOS
> binary, with hardcoded path, would make sense?  Then instead of adding
> -splash you could override with -L.  A linux distribution could
> override it too.


This is what I did primarily, but I don't like hardcoded values... and  
using "-splash" allows to provide more than the file name.

Regards,
Laurent
----------------------- Laurent Vivier ----------------------
"The best way to predict the future is to invent it."
- Alan Kay

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

* Re: [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support
  2008-12-18 18:23 ` [Qemu-devel] " andrzej zaborowski
  2008-12-18 18:40   ` Laurent Vivier
@ 2008-12-18 19:14   ` Anthony Liguori
  1 sibling, 0 replies; 8+ messages in thread
From: Anthony Liguori @ 2008-12-18 19:14 UTC (permalink / raw)
  To: qemu-devel

andrzej zaborowski wrote:
> 2008/12/18 Laurent Vivier <Laurent.Vivier@bull.net>:
>   
>> 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.
>>     
>
> Maybe having a default splash image in the same directory as the BIOS
> binary, with hardcoded path, would make sense?  Then instead of adding
> -splash you could override with -L.  A linux distribution could
> override it too.
>   

I think we should leave -splash to allow people to control it but I also 
like the idea of having a default splash for QEMU.  If someone out there 
is good with gimp, please post splash screens and we can consider a 
default :-)

N.B. If we do this, the prompt=off stuff would disable the splash.  We 
should also prevent the VGA BIOS from writing to the screen during boot 
but we can do this all as follow up.

Regards,

Anthony Liguori

> Cheers
>
>
>   

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

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

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-18 14:51 [Qemu-devel] [PATCH 0/2][v2] Add BIOS splash image support Laurent Vivier
2008-12-18 14:51 ` [Qemu-devel] [PATCH 1/2][v2][BIOS] Add " Laurent Vivier
2008-12-18 14:51   ` [Qemu-devel] [PATCH 2/2][v2][QEMU] Add BIOS splash image Laurent Vivier
2008-12-18 16:21 ` [Qemu-devel] Re: [PATCH 0/2][v2] Add BIOS splash image support Anthony Liguori
2008-12-18 16:24 ` Anthony Liguori
2008-12-18 18:23 ` [Qemu-devel] " andrzej zaborowski
2008-12-18 18:40   ` Laurent Vivier
2008-12-18 19:14   ` 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).