qemu-devel
[Top][All Lists]
Advanced

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

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


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

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

Idea and some parts of code are stollen from VirtualBox.

Signed-off-by: Laurent Vivier <address@hidden>
---
 bios/Makefile  |    4 +-
 bios/logo.c    |  206 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bios/logo.h    |   56 +++++++++++++++
 bios/rombios.c |  125 +++++++++++++++++++++-------------
 4 files changed, 340 insertions(+), 51 deletions(-)
 create mode 100644 bios/logo.c
 create mode 100644 bios/logo.h

diff --git a/bios/Makefile b/bios/Makefile
index a2759a9..d30be7d 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 logo.c logo.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 logo.c logo.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/logo.c b/bios/logo.c
new file mode 100644
index 0000000..d41eb10
--- /dev/null
+++ b/bios/logo.c
@@ -0,0 +1,206 @@
+/**
+ * Stuff for drawing the BIOS logo.
+ */
+
+/*
+ * Copyright (C) 2004-2008 Sun Microsystems, Inc.
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+ * Clara, CA 95054 USA or visit http://www.sun.com if you need
+ * additional information or have any questions.
+ *
+ * QEMU/KVM port by Laurent Vivier <address@hidden>
+ *
+ */
+
+#include "logo.h"
+
+#define BIOS_CFG_IOPORT 0x510
+#define BIOS_CFG_SIGNATURE 0x0000
+#define BIOS_CFG_SPLASH 0x4007
+
+#define WAIT_MS 16
+
+/**
+ * Set video mode (VGA).
+ * @params    New video mode.
+ */
+void set_mode(mode)
+  Bit8u mode;
+  {
+  ASM_START
+    push bp
+    mov  bp, sp
+
+      push ax
+
+      mov  ah, #0
+      mov  al, 4[bp] ; mode
+      int  #0x10
+
+      pop  ax
+
+    pop  bp
+  ASM_END
+  }
+
+Bit8u read_logo_byte(offset)
+  Bit8u offset;
+{
+    outw(BIOS_CFG_IOPORT, BIOS_CFG_SPLASH);
+    outb(BIOS_CFG_IOPORT + 1, LOGO_CMD_SET_OFFSET);
+    outb(BIOS_CFG_IOPORT + 1, offset);
+    return inb(BIOS_CFG_IOPORT + 1);
+}
+
+Bit16u read_logo_word(offset)
+  Bit8u offset;
+{
+    Bit16u word;
+    outw(BIOS_CFG_IOPORT, BIOS_CFG_SPLASH);
+    outb(BIOS_CFG_IOPORT + 1, LOGO_CMD_SET_OFFSET);
+    outb(BIOS_CFG_IOPORT + 1, offset);
+    word = inb(BIOS_CFG_IOPORT + 1);
+    word = (inb(BIOS_CFG_IOPORT + 1) << 8) | word;
+    return word;
+}
+
+void clear_screen()
+{
+// Hide cursor, clear screen and move cursor to starting position
+ASM_START
+    push bx
+    push cx
+    push dx
+
+    mov  ax, #0x100
+    mov  cx, #0x1000
+    int  #0x10
+
+    mov  ax, #0x700
+    mov  bh, #7
+    xor  cx, cx
+    mov  dx, #0x184f
+    int  #0x10
+
+    mov  ax, #0x200
+    xor  bx, bx
+    xor  dx, dx
+    int  #0x10
+
+    pop  dx
+    pop  cx
+    pop  bx
+ASM_END
+}
+
+Bit8u
+logo_enabled()
+{
+    LOGOHDR    *logo_hdr = 0;
+    Bit8u      is_fade_in, is_fade_out, uBootMenu;
+    Bit16u     logo_time;
+
+    /* 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 (read_logo_word(&logo_hdr->u16Signature) != LOGO_HDR_MAGIC)
+        return 0;
+
+    /* Get options */
+
+    is_fade_in = read_logo_byte(&logo_hdr->fu8FadeIn);
+    is_fade_out = read_logo_byte(&logo_hdr->fu8FadeOut);
+    logo_time = read_logo_word(&logo_hdr->u16LogoMillies);
+
+    return (is_fade_in || is_fade_out || logo_time);
+}
+
+void logo_show()
+{
+    LOGOHDR    *logo_hdr = 0;
+    Bit8u is_fade_in;
+    Bit16u i;
+
+    set_mode(0x12); /* 640x480 */
+
+    is_fade_in = read_logo_byte(&logo_hdr->fu8FadeIn);
+
+    outw(BIOS_CFG_IOPORT, BIOS_CFG_SPLASH);
+    if (is_fade_in)
+    {
+        for (i = 0; i < LOGO_SHOW_STEPS; i++)
+        {
+            if (i != 0) { /* 0 means "unload image from memory" */
+              outb(BIOS_CFG_IOPORT + 1, LOGO_CMD_SHOW_BMP);
+              outb(BIOS_CFG_IOPORT + 1, i);
+            }
+            delay_ticks_and_check_for_keystroke(16 / WAIT_MS, 1);
+            if (check_for_keystroke())
+                break;
+        }
+    }
+    outb(BIOS_CFG_IOPORT + 1, LOGO_CMD_SHOW_BMP);
+    outb(BIOS_CFG_IOPORT + 1, LOGO_SHOW_STEPS);
+
+    return;
+}
+
+void logo_hide()
+{
+    LOGOHDR    *logo_hdr = 0;
+    Bit8u is_fade_out;
+    Bit16u i;
+
+    if (check_for_keystroke())
+       goto hide;
+
+    is_fade_out = read_logo_byte(&logo_hdr->fu8FadeOut);
+
+    outw(BIOS_CFG_IOPORT, BIOS_CFG_SPLASH);
+    if (is_fade_out)
+    {
+        for (i = LOGO_SHOW_STEPS; i > 0 ; i--)
+        {
+            outb(BIOS_CFG_IOPORT + 1, LOGO_CMD_SHOW_BMP);
+            outb(BIOS_CFG_IOPORT + 1, i);
+            delay_ticks_and_check_for_keystroke(16 / WAIT_MS, 1);
+            if (check_for_keystroke())
+                break;
+        }
+    }
+hide:
+    outb(BIOS_CFG_IOPORT + 1, LOGO_CMD_SHOW_BMP);
+    outb(BIOS_CFG_IOPORT + 1, 0);
+    set_mode(0x03);
+    clear_screen();
+
+    return;
+}
+
+Bit8u
+logo_display_boot_list()
+{
+    LOGOHDR    *logo_hdr = 0;
+
+    return read_logo_byte(&logo_hdr->fu8ShowBootMenu);
+}
diff --git a/bios/logo.h b/bios/logo.h
new file mode 100644
index 0000000..d7a7b80
--- /dev/null
+++ b/bios/logo.h
@@ -0,0 +1,56 @@
+/**
+ * BiosLogo - The Private BIOS Logo Interface.
+ */
+
+/*
+ * Copyright (C) 2006-2007 Sun Microsystems, Inc.
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+ * Clara, CA 95054 USA or visit http://www.sun.com if you need
+ * additional information or have any questions.
+ *
+ * QEMU/KVM port by Laurent Vivier <address@hidden>
+ *
+ */
+
+#define LOGO_SHOW_STEPS      16
+
+#define LOGO_CMD_NOP         0
+#define LOGO_CMD_SET_OFFSET  0x01
+#define LOGO_CMD_SHOW_BMP    0x02
+
+typedef struct LOGOHDR
+{
+    /** Signature (LOGO_HDR_MAGIC/0x66BB). */
+    Bit16u        u16Signature;
+    /** Logo time (msec). */
+    Bit16u        u16LogoMillies;
+    /** Fade in - boolean. */
+    Bit8u         fu8FadeIn;
+    /** Fade out - boolean. */
+    Bit8u         fu8FadeOut;
+    /** Show setup - boolean. */
+    Bit8u         fu8ShowBootMenu;
+    /** Reserved / padding. */
+    Bit8u         u8Reserved;
+    /** Logo file size. */
+    Bit32u        cbLogo;
+} LOGOHDR;
+#define LOGO_HDR_MAGIC      0x66BB
diff --git a/bios/rombios.c b/bios/rombios.c
index 9a1cdd6..52a1391 100644
--- a/bios/rombios.c
+++ b/bios/rombios.c
@@ -1917,6 +1917,10 @@ shutdown_status_panic(status)
   BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
 }
 
+#ifdef BX_QEMU
+#include "logo.c"
+#endif
+
 //--------------------------------------------------------------------------
 // print_bios_banner
 //   displays a the bios version
@@ -1924,6 +1928,10 @@ shutdown_status_panic(status)
 void
 print_bios_banner()
 {
+#ifdef BX_QEMU
+  if (logo_enabled())
+    return;
+#endif
   printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
     BIOS_BUILD_DATE, bios_cvs_version_string);
   printf(
@@ -2021,65 +2029,78 @@ interactive_bootkey()
   Bit16u ss = get_SS();
   Bit16u valid_choice = 0;
 
+#ifdef BX_QEMU
+  if (logo_enabled()) {
+    LOGOHDR *logo_hdr = 0;
+    Bit16u logo_time;
+
+    logo_show();
+    logo_time = read_logo_word(&logo_hdr->u16LogoMillies);
+    if (!check_for_keystroke())
+      delay_ticks_and_check_for_keystroke(WAIT_MS, logo_time / 1000);
+    logo_hide();
+    if (!logo_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 +2727,9 @@ void ata_detect( )
           break;
         }
 
+#ifdef BX_QEMU
+      if (!logo_enabled()) {
+#endif
       switch (type) {
         case ATA_TYPE_ATA:
           printf("ata%d %s: ",channel,slave?" slave":"master");
@@ -2727,6 +2751,9 @@ void ata_detect( )
           printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master");
           break;
         }
+#ifdef BX_QEMU
+        }
+#endif
       }
     }
 
-- 
1.5.6.5





reply via email to

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