All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/5] Seabios qemu detect
@ 2009-08-03 13:32 Jes Sorensen
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 1/5] Move QEMU_CFG related code out of smbios.c Jes Sorensen
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Jes Sorensen @ 2009-08-03 13:32 UTC (permalink / raw)
  To: kevin; +Cc: Anthony Liguori, Beth Kon, qemu-devel, avi

Hi,

Argh! Forgot to post this yesterday!

Here is a series of patches for Seabios which introduces support for
QEMU_CFG_EMULATOR and uses it to select the irq0verride flag and for
runtime detection of whether or not Seabios is running on QEMU and
KVM.

This allows us to eliminate CONFIG_KVM completely as well.

I would love to see something similar used to detect Coreboot, making
it possible to have one shared BIOS binary.

Cheers,
Jes

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

* [Qemu-devel] [PATCH 1/5] Move QEMU_CFG related code out of smbios.c
  2009-08-03 13:32 [Qemu-devel] [PATCH 0/5] Seabios qemu detect Jes Sorensen
@ 2009-08-03 13:32 ` Jes Sorensen
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 2/5] Reorder call for qemu-cfg probing Jes Sorensen
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jes Sorensen @ 2009-08-03 13:32 UTC (permalink / raw)
  To: kevin; +Cc: Anthony Liguori, Beth Kon, qemu-devel, avi

[-- Attachment #1: 0002-seperate-qemu-cfg.patch --]
[-- Type: text/plain, Size: 3493 bytes --]

This patch moves QEMU_CFG infrastructure out of smbios.c and puts it
into seperate files.

Signed-off-by: Jes Sorensen <jes@sgi.com>

---
 Makefile       |    4 ++--
 src/qemu-cfg.c |   29 +++++++++++++++++++++++++++++
 src/qemu-cfg.h |   19 +++++++++++++++++++
 src/smbios.c   |   22 +---------------------
 4 files changed, 51 insertions(+), 23 deletions(-)

Index: seabios/Makefile
===================================================================
--- seabios.orig/Makefile
+++ seabios/Makefile
@@ -16,8 +16,8 @@ SRCBOTH=output.c util.c floppy.c ata.c m
         pnpbios.c pirtable.c vgahooks.c pmm.c
 SRC16=$(SRCBOTH) system.c disk.c apm.c pcibios.c font.c
 SRC32=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
-      acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
-      lzmadecode.c
+      acpi.c smm.c mptable.c qemu-cfg.c smbios.c pciinit.c optionroms.c \
+      mtrr.c lzmadecode.c
 
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
               /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;)
Index: seabios/src/qemu-cfg.c
===================================================================
--- /dev/null
+++ seabios/src/qemu-cfg.c
@@ -0,0 +1,29 @@
+// qemu-cfg.c: QEMU_CFG related code
+//
+// Copyright (C) 2009  Jes Sorensen, SGI <jes@sgi.com>
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "types.h"
+#include "ioport.h"
+#include "qemu-cfg.h"
+
+void
+qemu_cfg_read(u8 *buf, u16 f, int len)
+{
+    outw(f, PORT_QEMU_CFG_CTL);
+    while (len--)
+        *(buf++) = inb(PORT_QEMU_CFG_DATA);
+}
+
+int
+qemu_cfg_port_probe()
+{
+    u8 sig[4] = "QEMU";
+    u8 buf[4];
+    qemu_cfg_read(buf, QEMU_CFG_SIGNATURE, 4);
+    return *(u32*)buf == *(u32*)sig;
+}
+
Index: seabios/src/qemu-cfg.h
===================================================================
--- /dev/null
+++ seabios/src/qemu-cfg.h
@@ -0,0 +1,19 @@
+// qemu-cfg.h: QEMU_CFG related definitions
+//
+// Copyright (C) 2009  Jes Sorensen, SGI <jes@sgi.com>
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#ifndef __QEMU_CFG_H
+#define __QEMU_CFG_H
+
+#define QEMU_CFG_SIGNATURE  0x00
+#define QEMU_CFG_ID         0x01
+#define QEMU_CFG_UUID       0x02
+
+void qemu_cfg_read(u8 *buf, u16 f, int len);
+int qemu_cfg_port_probe();
+
+#endif
Index: seabios/src/smbios.c
===================================================================
--- seabios.orig/src/smbios.c
+++ seabios/src/smbios.c
@@ -8,33 +8,13 @@
 #include "util.h" // dprintf
 #include "memmap.h" // malloc_fseg
 #include "biosvar.h" // GET_EBDA
+#include "qemu-cfg.h" // QEMU_CFG_UUID
 
 
 /****************************************************************
  * UUID probe
  ****************************************************************/
 
-#define QEMU_CFG_SIGNATURE  0x00
-#define QEMU_CFG_ID         0x01
-#define QEMU_CFG_UUID       0x02
-
-static void
-qemu_cfg_read(u8 *buf, u16 f, int len)
-{
-    outw(f, PORT_QEMU_CFG_CTL);
-    while (len--)
-        *(buf++) = inb(PORT_QEMU_CFG_DATA);
-}
-
-static int
-qemu_cfg_port_probe()
-{
-    u8 sig[4] = "QEMU";
-    u8 buf[4];
-    qemu_cfg_read(buf, QEMU_CFG_SIGNATURE, 4);
-    return *(u32*)buf == *(u32*)sig;
-}
-
 static void
 uuid_probe(u8 *bios_uuid)
 {

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

* [Qemu-devel] [PATCH 2/5] Reorder call for qemu-cfg probing.
  2009-08-03 13:32 [Qemu-devel] [PATCH 0/5] Seabios qemu detect Jes Sorensen
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 1/5] Move QEMU_CFG related code out of smbios.c Jes Sorensen
@ 2009-08-03 13:32 ` Jes Sorensen
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 3/5] Set emu_ver based on information provided by qemu_cfg Jes Sorensen
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jes Sorensen @ 2009-08-03 13:32 UTC (permalink / raw)
  To: kevin; +Cc: Anthony Liguori, Beth Kon, qemu-devel, avi

[-- Attachment #1: 0003-reorder-cfg-probe.patch --]
[-- Type: text/plain, Size: 2351 bytes --]

This moves the call to probe for qemu-cfg to an earlier point in the
BIOS init. Required in order to use the output for mptable setup etc.

Signed-off-by: Jes Sorensen <jes@sgi.com>

---
 src/post.c     |   10 ++++++++++
 src/qemu-cfg.c |    6 +++++-
 src/smbios.c   |    2 +-
 src/util.h     |    3 +++
 4 files changed, 19 insertions(+), 2 deletions(-)

Index: seabios/src/post.c
===================================================================
--- seabios.orig/src/post.c
+++ seabios/src/post.c
@@ -18,6 +18,7 @@
 #include "bregs.h" // struct bregs
 #include "mptable.h" // mptable_init
 #include "boot.h" // IPL
+#include "qemu-cfg.h"
 
 void
 __set_irq(int vector, void *loc)
@@ -158,6 +159,15 @@ post()
     init_ivt();
     init_bda();
 
+    /*
+     * Test for emulator earlier, to be able to runtime check whether
+     * we are on QEMU/KVM/Coreboot etc.
+     *
+     * Would be ideal to be able to runtime test for coreboot in here,
+     * if someone knows how to do so reliably.
+     */
+    qemu_cfg_port_probe();
+
     pic_setup();
     timer_setup();
     mathcp_setup();
Index: seabios/src/qemu-cfg.c
===================================================================
--- seabios.orig/src/qemu-cfg.c
+++ seabios/src/qemu-cfg.c
@@ -10,6 +10,8 @@
 #include "ioport.h"
 #include "qemu-cfg.h"
 
+int qemu_cfg_port = 0;
+
 void
 qemu_cfg_read(u8 *buf, u16 f, int len)
 {
@@ -24,6 +26,8 @@ qemu_cfg_port_probe()
     u8 sig[4] = "QEMU";
     u8 buf[4];
     qemu_cfg_read(buf, QEMU_CFG_SIGNATURE, 4);
-    return *(u32*)buf == *(u32*)sig;
+    if (*(u32*)buf == *(u32*)sig)
+        qemu_cfg_port = 1;
+    return qemu_cfg_port;
 }
 
Index: seabios/src/smbios.c
===================================================================
--- seabios.orig/src/smbios.c
+++ seabios/src/smbios.c
@@ -24,7 +24,7 @@ uuid_probe(u8 *bios_uuid)
         return;
     if (CONFIG_COREBOOT)
         return;
-    if (! qemu_cfg_port_probe())
+    if (!qemu_cfg_port)
         // Feature not available
         return;
 
Index: seabios/src/util.h
===================================================================
--- seabios.orig/src/util.h
+++ seabios/src/util.h
@@ -264,4 +264,7 @@ extern int irq0override;
 // version (auto generated file out/version.c)
 extern const char VERSION[];
 
+// qemu-cfg.c
+extern int qemu_cfg_port;
+
 #endif // util.h

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

* [Qemu-devel] [PATCH 3/5] Set emu_ver based on information provided by qemu_cfg.
  2009-08-03 13:32 [Qemu-devel] [PATCH 0/5] Seabios qemu detect Jes Sorensen
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 1/5] Move QEMU_CFG related code out of smbios.c Jes Sorensen
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 2/5] Reorder call for qemu-cfg probing Jes Sorensen
@ 2009-08-03 13:32 ` Jes Sorensen
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 4/5] Set irq0override based on emu_ver Jes Sorensen
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jes Sorensen @ 2009-08-03 13:32 UTC (permalink / raw)
  To: kevin; +Cc: Anthony Liguori, Beth Kon, qemu-devel, avi

[-- Attachment #1: 0004-emulator-detect.patch --]
[-- Type: text/plain, Size: 2079 bytes --]

This patch retrieves the value of QEMU_CFG_EMULATOR and sets emu_ver,
allowing the BIOS to runtime verify which emulator it is running on.

Signed-off-by: Jes Sorensen <jes@sgi.com>

---
 src/post.c     |    4 ++++
 src/qemu-cfg.c |    8 ++++++++
 src/qemu-cfg.h |    2 ++
 src/util.h     |    7 +++++++
 4 files changed, 21 insertions(+)

Index: seabios/src/post.c
===================================================================
--- seabios.orig/src/post.c
+++ seabios/src/post.c
@@ -20,6 +20,8 @@
 #include "boot.h" // IPL
 #include "qemu-cfg.h"
 
+u16 emu_ver;
+
 void
 __set_irq(int vector, void *loc)
 {
@@ -167,6 +169,8 @@ post()
      * if someone knows how to do so reliably.
      */
     qemu_cfg_port_probe();
+    if (qemu_cfg_port)
+        emu_ver = qemu_cfg_get_emulator_rev();
 
     pic_setup();
     timer_setup();
Index: seabios/src/qemu-cfg.c
===================================================================
--- seabios.orig/src/qemu-cfg.c
+++ seabios/src/qemu-cfg.c
@@ -31,3 +31,11 @@ qemu_cfg_port_probe()
     return qemu_cfg_port;
 }
 
+u16 qemu_cfg_get_emulator_rev(void)
+{
+    u16 rev;
+
+    qemu_cfg_read((u8*)&rev, QEMU_CFG_EMULATOR, sizeof(rev));
+
+    return rev;
+}
Index: seabios/src/qemu-cfg.h
===================================================================
--- seabios.orig/src/qemu-cfg.h
+++ seabios/src/qemu-cfg.h
@@ -12,8 +12,10 @@
 #define QEMU_CFG_SIGNATURE  0x00
 #define QEMU_CFG_ID         0x01
 #define QEMU_CFG_UUID       0x02
+#define QEMU_CFG_EMULATOR   0x10
 
 void qemu_cfg_read(u8 *buf, u16 f, int len);
 int qemu_cfg_port_probe();
+u16 qemu_cfg_get_emulator_rev(void);
 
 #endif
Index: seabios/src/util.h
===================================================================
--- seabios.orig/src/util.h
+++ seabios/src/util.h
@@ -267,4 +267,11 @@ extern const char VERSION[];
 // qemu-cfg.c
 extern int qemu_cfg_port;
 
+// port.c
+extern u16 emu_ver;
+#define EMU_NONE            0x0000
+#define EMU_QEMU            0x0100
+#define EMU_QEMU_KVM        0x0101
+#define EMU_QEMU_KQEMU      0x0102
+
 #endif // util.h

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

* [Qemu-devel] [PATCH 4/5] Set irq0override based on emu_ver.
  2009-08-03 13:32 [Qemu-devel] [PATCH 0/5] Seabios qemu detect Jes Sorensen
                   ` (2 preceding siblings ...)
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 3/5] Set emu_ver based on information provided by qemu_cfg Jes Sorensen
@ 2009-08-03 13:32 ` Jes Sorensen
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 5/5] Remove CONFIG_KVM and use emu_ver to runtime detect QEMU & KVM Jes Sorensen
  2009-08-05  1:20 ` [Qemu-devel] Re: [PATCH 0/5] Seabios qemu detect Kevin O'Connor
  5 siblings, 0 replies; 7+ messages in thread
From: Jes Sorensen @ 2009-08-03 13:32 UTC (permalink / raw)
  To: kevin; +Cc: Anthony Liguori, Beth Kon, qemu-devel, avi

[-- Attachment #1: 0005-ir0override-qemu.patch --]
[-- Type: text/plain, Size: 1000 bytes --]

Enable irq0override when we are running on QEMU. All recent versionsof
QEMU rely on irq0override, not just for KVM.

Signed-off-by: Jes Sorensen <jes@sgi.com>
---
 src/mptable.c |    4 ----
 src/post.c    |    2 ++
 2 files changed, 2 insertions(+), 4 deletions(-)

Index: seabios/src/mptable.c
===================================================================
--- seabios.orig/src/mptable.c
+++ seabios/src/mptable.c
@@ -9,11 +9,7 @@
 #include "config.h" // CONFIG_*
 #include "mptable.h" // MPTABLE_SIGNATURE
 
-#if CONFIG_KVM
-int irq0override = 1;
-#else
 int irq0override = 0;
-#endif
 
 void
 mptable_init(void)
Index: seabios/src/post.c
===================================================================
--- seabios.orig/src/post.c
+++ seabios/src/post.c
@@ -171,6 +171,8 @@ post()
     qemu_cfg_port_probe();
     if (qemu_cfg_port)
         emu_ver = qemu_cfg_get_emulator_rev();
+    if ((emu_ver & 0xff00) == EMU_QEMU)
+        irq0override = 1;
 
     pic_setup();
     timer_setup();

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

* [Qemu-devel] [PATCH 5/5] Remove CONFIG_KVM and use emu_ver to runtime detect QEMU & KVM.
  2009-08-03 13:32 [Qemu-devel] [PATCH 0/5] Seabios qemu detect Jes Sorensen
                   ` (3 preceding siblings ...)
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 4/5] Set irq0override based on emu_ver Jes Sorensen
@ 2009-08-03 13:32 ` Jes Sorensen
  2009-08-05  1:20 ` [Qemu-devel] Re: [PATCH 0/5] Seabios qemu detect Kevin O'Connor
  5 siblings, 0 replies; 7+ messages in thread
From: Jes Sorensen @ 2009-08-03 13:32 UTC (permalink / raw)
  To: kevin; +Cc: Anthony Liguori, Beth Kon, qemu-devel, avi

[-- Attachment #1: 0006-kvm-runtime-detect.patch --]
[-- Type: text/plain, Size: 3179 bytes --]

This patch makes Seabios use emu_ver to determine QEMU and KVM
specific configuration at runtime.

Signed-off-by: Jes Sorensen <jes@sgi.com>

---
 src/acpi.c    |   14 +++++++-------
 src/config.h  |    2 --
 src/pciinit.c |   18 +++++++++++++-----
 src/post.c    |    2 +-
 4 files changed, 21 insertions(+), 15 deletions(-)

Index: seabios/src/acpi.c
===================================================================
--- seabios.orig/src/acpi.c
+++ seabios/src/acpi.c
@@ -196,12 +196,8 @@ struct madt_io_apic
                                  * lines start */
 } PACKED;
 
-#if CONFIG_KVM
-/* IRQs 5,9,10,11 */
-#define PCI_ISA_IRQ_MASK    0x0e20
-#else
-#define PCI_ISA_IRQ_MASK    0x0000
-#endif
+/* IRQs 5,9,10,11 for QEMU/KQEMU/KVM */
+#define QEMU_PCI_ISA_IRQ_MASK    0x0e20
 
 struct madt_intsrcovr {
     APIC_HEADER_DEF
@@ -339,8 +335,12 @@ build_madt(struct rsdt_descriptor_rev1 *
         intsrcovr->flags  = 0; /* conforms to bus specifications */
         intsrcovr++;
     }
+    int pci_isa_irq_mask = 0;
+    if ((emu_ver & 0xff00) == EMU_QEMU)
+        pci_isa_irq_mask = QEMU_PCI_ISA_IRQ_MASK;
+
     for (i = 1; i < 16; i++) {
-        if (!(PCI_ISA_IRQ_MASK & (1 << i)))
+        if (!(pci_isa_irq_mask & (1 << i)))
             /* No need for a INT source override structure. */
             continue;
         memset(intsrcovr, 0, sizeof(*intsrcovr));
Index: seabios/src/config.h
===================================================================
--- seabios.orig/src/config.h
+++ seabios/src/config.h
@@ -12,8 +12,6 @@
 #define CONFIG_APPNAME6 "BOCHS "
 #define CONFIG_APPNAME4 "BXPC"
 
-// Configure for use with KVM.
-#define CONFIG_KVM 1
 // Configure as a coreboot payload.
 #define CONFIG_COREBOOT 0
 
Index: seabios/src/pciinit.c
===================================================================
--- seabios.orig/src/pciinit.c
+++ seabios/src/pciinit.c
@@ -18,12 +18,15 @@ static u32 pci_bios_io_addr;
 static u32 pci_bios_mem_addr;
 static u32 pci_bios_bigmem_addr;
 /* host irqs corresponding to PCI irqs A-D */
-static u8 pci_irqs[4] = {
-#if CONFIG_KVM
-    10, 10, 11, 11
-#else
+
+static u8 *pci_irqs;
+
+static u8 default_pci_irqs[4] = {
     11, 9, 11, 9
-#endif
+};
+
+static u8 qemu_pci_irqs[4] = {
+    10, 10, 11, 11
 };
 
 static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
@@ -194,6 +197,11 @@ pci_bios_setup(void)
         // Already done by coreboot.
         return;
 
+    if ((emu_ver & 0xff00) == EMU_QEMU)
+        pci_irqs = qemu_pci_irqs;
+    else
+        pci_irqs = default_pci_irqs;
+
     pci_bios_io_addr = 0xc000;
     pci_bios_mem_addr = 0xc0000000;
     pci_bios_bigmem_addr = RamSize;
Index: seabios/src/post.c
===================================================================
--- seabios.orig/src/post.c
+++ seabios/src/post.c
@@ -129,7 +129,7 @@ ram_probe(void)
              , E820_RESERVED);
     add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED);
 
-    if (CONFIG_KVM)
+    if (emu_ver == EMU_QEMU_KVM)
         // 4 pages before the bios, 3 pages for vmx tss pages, the
         // other page for EPT real mode pagetable
         add_e820(0xfffbc000, 4*4096, E820_RESERVED);

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

* [Qemu-devel] Re: [PATCH 0/5] Seabios qemu detect
  2009-08-03 13:32 [Qemu-devel] [PATCH 0/5] Seabios qemu detect Jes Sorensen
                   ` (4 preceding siblings ...)
  2009-08-03 13:32 ` [Qemu-devel] [PATCH 5/5] Remove CONFIG_KVM and use emu_ver to runtime detect QEMU & KVM Jes Sorensen
@ 2009-08-05  1:20 ` Kevin O'Connor
  5 siblings, 0 replies; 7+ messages in thread
From: Kevin O'Connor @ 2009-08-05  1:20 UTC (permalink / raw)
  To: Jes Sorensen; +Cc: Anthony Liguori, Beth Kon, qemu-devel, avi

On Mon, Aug 03, 2009 at 03:32:36PM +0200, Jes Sorensen wrote:
> Hi,
> 
> Argh! Forgot to post this yesterday!
> 
> Here is a series of patches for Seabios which introduces support for
> QEMU_CFG_EMULATOR and uses it to select the irq0verride flag and for
> runtime detection of whether or not Seabios is running on QEMU and
> KVM.

Thanks Jes.

Once the backend work is committed to qemu or kvm, I think we should
check this into SeaBIOS.

A couple of minor notes on style: can you make the global variables
use more prominent names (eg, "EmulatorVersion" instead of "emu_ver"),
can you abstract the test "(emu_ver & 0xff00) == EMU_QEMU" into a
function - as it isn't obvious what it does, and finally, can you move
the code you added to post() into qemu_cfg_port_probe() instead?

You asked about detecting coreboot automatically.  There are several
ways to do this, but probably the easiest is to take advantage of the
fact that coreboot uses a dedicated 32bit entry point.  See the
(poorly named) post32 function in romlayout.S.

Note though, the coreboot case may still need some compile-time
checks, because of the code size increase resulting from doing the
tests at runtime.

Thanks again,
-Kevin

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

end of thread, other threads:[~2009-08-05  1:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-03 13:32 [Qemu-devel] [PATCH 0/5] Seabios qemu detect Jes Sorensen
2009-08-03 13:32 ` [Qemu-devel] [PATCH 1/5] Move QEMU_CFG related code out of smbios.c Jes Sorensen
2009-08-03 13:32 ` [Qemu-devel] [PATCH 2/5] Reorder call for qemu-cfg probing Jes Sorensen
2009-08-03 13:32 ` [Qemu-devel] [PATCH 3/5] Set emu_ver based on information provided by qemu_cfg Jes Sorensen
2009-08-03 13:32 ` [Qemu-devel] [PATCH 4/5] Set irq0override based on emu_ver Jes Sorensen
2009-08-03 13:32 ` [Qemu-devel] [PATCH 5/5] Remove CONFIG_KVM and use emu_ver to runtime detect QEMU & KVM Jes Sorensen
2009-08-05  1:20 ` [Qemu-devel] Re: [PATCH 0/5] Seabios qemu detect Kevin O'Connor

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.