qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 1/2][v2][BIOS] Add splash image support


From: Laurent Vivier
Subject: [Qemu-devel] [PATCH 1/2][v2][BIOS] Add splash image support
Date: Thu, 18 Dec 2008 15:51:36 +0100

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 <address@hidden>
---
 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





reply via email to

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