summaryrefslogtreecommitdiff
path: root/pc-bios
diff options
context:
space:
mode:
authorJunfeng Dong <junfeng.dong@intel.com>2013-11-19 17:45:23 +0800
committerJunfeng Dong <junfeng.dong@intel.com>2013-11-19 17:45:23 +0800
commit340f06c9eaee097e626c251bf7a013350649c091 (patch)
tree107e5705050a12da68fc80a56ae37afd50a2cc94 /pc-bios
parent42bf3037d458a330856a0be584200c1e41c3f417 (diff)
downloadqemu-340f06c9eaee097e626c251bf7a013350649c091.tar.gz
qemu-340f06c9eaee097e626c251bf7a013350649c091.tar.bz2
qemu-340f06c9eaee097e626c251bf7a013350649c091.zip
Import upstream 1.6.0.upstream/1.6.0
Change-Id: Icf52b556470cac8677297f2ef14ded16684f7887 Signed-off-by: Junfeng Dong <junfeng.dong@intel.com>
Diffstat (limited to 'pc-bios')
-rw-r--r--pc-bios/README8
-rw-r--r--pc-bios/acpi-dsdt.amlbin4540 -> 4407 bytes
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/efi-e1000.rombin0 -> 173568 bytes
-rw-r--r--pc-bios/efi-eepro100.rombin0 -> 174592 bytes
-rw-r--r--pc-bios/efi-ne2k_pci.rombin0 -> 173056 bytes
-rw-r--r--pc-bios/efi-pcnet.rombin0 -> 173056 bytes
-rw-r--r--pc-bios/efi-rtl8139.rombin0 -> 176640 bytes
-rw-r--r--pc-bios/efi-virtio.rombin0 -> 171008 bytes
-rwxr-xr-x[-rw-r--r--]pc-bios/multiboot.binbin1024 -> 1024 bytes
-rw-r--r--pc-bios/openbios-ppcbin729908 -> 733976 bytes
-rw-r--r--pc-bios/openbios-sparc32bin381764 -> 381484 bytes
-rw-r--r--pc-bios/openbios-sparc64bin1598648 -> 1598328 bytes
-rw-r--r--pc-bios/optionrom/multiboot.S75
-rw-r--r--pc-bios/optionrom/optionrom.h2
-rwxr-xr-xpc-bios/palcode-clipperbin185703 -> 133550 bytes
-rw-r--r--pc-bios/q35-acpi-dsdt.amlbin0 -> 7344 bytes
-rw-r--r--pc-bios/qemu-nsis.bmpbin0 -> 154542 bytes
-rw-r--r--pc-bios/qemu-nsis.icobin0 -> 4846 bytes
-rw-r--r--pc-bios/qemu_logo_no_text.svg976
-rw-r--r--pc-bios/s390-ccw.imgbin0 -> 9432 bytes
-rw-r--r--pc-bios/s390-ccw/Makefile26
-rw-r--r--pc-bios/s390-ccw/bootmap.c235
-rw-r--r--pc-bios/s390-ccw/cio.h342
-rw-r--r--pc-bios/s390-ccw/main.c80
-rw-r--r--pc-bios/s390-ccw/s390-ccw.h135
-rw-r--r--pc-bios/s390-ccw/sclp-ascii.c81
-rw-r--r--pc-bios/s390-ccw/sclp.h107
-rw-r--r--pc-bios/s390-ccw/start.S33
-rw-r--r--pc-bios/s390-ccw/virtio.c321
-rw-r--r--pc-bios/s390-ccw/virtio.h163
-rw-r--r--pc-bios/slof.binbin878640 -> 909720 bytes
32 files changed, 2561 insertions, 23 deletions
diff --git a/pc-bios/README b/pc-bios/README
index 303713099..e404a228a 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -12,12 +12,12 @@
1275-1994 (referred to as Open Firmware) compliant firmware.
The included images for PowerPC (for 32 and 64 bit PPC CPUs),
Sparc32 and Sparc64 are built from OpenBIOS SVN revision
- 1063.
+ 1198.
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at
- https://github.com/dgibson/SLOF, and the image currently in qemu is
- built from git tag qemu-slof-20120731.
+ https://github.com/aik/SLOF, and the image currently in qemu is
+ built from git tag qemu-slof-20130430.
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
legacy x86 software to communicate with an attached serial console as
@@ -40,4 +40,4 @@
git://repo.or.cz/s390-tools.git
- The sources for the Alpha palcode image is available from:
- git://repo.or.cz/qemu-palcode.git
+ git://github.com/rth7680/qemu-palcode.git
diff --git a/pc-bios/acpi-dsdt.aml b/pc-bios/acpi-dsdt.aml
index bb3dd83a5..48dbe3242 100644
--- a/pc-bios/acpi-dsdt.aml
+++ b/pc-bios/acpi-dsdt.aml
Binary files differ
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index dc9b57ddc..cccc48781 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/pc-bios/efi-e1000.rom b/pc-bios/efi-e1000.rom
new file mode 100644
index 000000000..21b880afc
--- /dev/null
+++ b/pc-bios/efi-e1000.rom
Binary files differ
diff --git a/pc-bios/efi-eepro100.rom b/pc-bios/efi-eepro100.rom
new file mode 100644
index 000000000..1799c38a8
--- /dev/null
+++ b/pc-bios/efi-eepro100.rom
Binary files differ
diff --git a/pc-bios/efi-ne2k_pci.rom b/pc-bios/efi-ne2k_pci.rom
new file mode 100644
index 000000000..5d1b38b9a
--- /dev/null
+++ b/pc-bios/efi-ne2k_pci.rom
Binary files differ
diff --git a/pc-bios/efi-pcnet.rom b/pc-bios/efi-pcnet.rom
new file mode 100644
index 000000000..79fa7a9b1
--- /dev/null
+++ b/pc-bios/efi-pcnet.rom
Binary files differ
diff --git a/pc-bios/efi-rtl8139.rom b/pc-bios/efi-rtl8139.rom
new file mode 100644
index 000000000..0b78f1a38
--- /dev/null
+++ b/pc-bios/efi-rtl8139.rom
Binary files differ
diff --git a/pc-bios/efi-virtio.rom b/pc-bios/efi-virtio.rom
new file mode 100644
index 000000000..e6b2bf724
--- /dev/null
+++ b/pc-bios/efi-virtio.rom
Binary files differ
diff --git a/pc-bios/multiboot.bin b/pc-bios/multiboot.bin
index 7b3c1745a..e772713c9 100644..100755
--- a/pc-bios/multiboot.bin
+++ b/pc-bios/multiboot.bin
Binary files differ
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 5311eca69..c6b3319fa 100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 6bd8e45d8..2aa400cfd 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 7c06fcc5a..f6ee28603 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
diff --git a/pc-bios/optionrom/multiboot.S b/pc-bios/optionrom/multiboot.S
index 003bcfb49..b7efe4de3 100644
--- a/pc-bios/optionrom/multiboot.S
+++ b/pc-bios/optionrom/multiboot.S
@@ -89,17 +89,14 @@ run_multiboot:
/* Initialize multiboot mmap structs using int 0x15(e820) */
xor %ebx, %ebx
- /* mmap start after first size */
- movl $4, %edi
+ /* Start storing mmap data at %es:0 */
+ xor %edi, %edi
mmap_loop:
+ /* The multiboot entry size has offset -4, so leave some space */
+ add $4, %di
/* entry size (mmap struct) & max buffer size (int15) */
movl $20, %ecx
- /* store entry size */
- /* old as(1) doesn't like this insn so emit the bytes instead:
- movl %ecx, %es:-4(%edi)
- */
- .dc.b 0x26,0x67,0x66,0x89,0x4f,0xfc
/* e820 */
movl $0x0000e820, %eax
/* 'SMAP' magic */
@@ -107,23 +104,65 @@ mmap_loop:
int $0x15
mmap_check_entry:
- /* last entry? then we're done */
+ /* Error or last entry already done? */
jb mmap_done
- and %bx, %bx
- jz mmap_done
- /* valid entry, so let's loop on */
mmap_store_entry:
- /* %ax = entry_number * 24 */
- mov $24, %ax
- mul %bx
- mov %ax, %di
+ /* store entry size */
+ /* old as(1) doesn't like this insn so emit the bytes instead:
+ movl %ecx, %es:-4(%edi)
+ */
+ .dc.b 0x26,0x67,0x66,0x89,0x4f,0xfc
+
+ /* %edi += entry_size, store as mbs_mmap_length */
+ add %ecx, %edi
movw %di, %fs:0x2c
- /* %di = 4 + (entry_number * 24) */
- add $4, %di
- jmp mmap_loop
+
+ /* Continuation value 0 means last entry */
+ test %ebx, %ebx
+ jnz mmap_loop
mmap_done:
+ /* Calculate upper_mem field: The amount of memory between 1 MB and
+ the first upper memory hole. Get it from the mmap. */
+ xor %di, %di
+ mov $0x100000, %edx
+upper_mem_entry:
+ cmp %fs:0x2c, %di
+ je upper_mem_done
+ add $4, %di
+
+ /* Skip if type != 1 */
+ cmpl $1, %es:16(%di)
+ jne upper_mem_next
+
+ /* Skip if > 4 GB */
+ movl %es:4(%di), %eax
+ test %eax, %eax
+ jnz upper_mem_next
+
+ /* Check for contiguous extension (base <= %edx < base + length) */
+ movl %es:(%di), %eax
+ cmp %eax, %edx
+ jb upper_mem_next
+ addl %es:8(%di), %eax
+ cmp %eax, %edx
+ jae upper_mem_next
+
+ /* If so, update %edx, and restart the search (mmap isn't ordered) */
+ mov %eax, %edx
+ xor %di, %di
+ jmp upper_mem_entry
+
+upper_mem_next:
+ addl %es:-4(%di), %edi
+ jmp upper_mem_entry
+
+upper_mem_done:
+ sub $0x100000, %edx
+ shr $10, %edx
+ mov %edx, %fs:0x8
+
real_to_prot:
/* Load the GDT before going into protected mode */
lgdt:
diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
index 3daf7da49..ce436085d 100644
--- a/pc-bios/optionrom/optionrom.h
+++ b/pc-bios/optionrom/optionrom.h
@@ -20,7 +20,7 @@
#define NO_QEMU_PROTOS
-#include "../../hw/fw_cfg.h"
+#include "../../include/hw/nvram/fw_cfg.h"
#define BIOS_CFG_IOPORT_CFG 0x510
#define BIOS_CFG_IOPORT_DATA 0x511
diff --git a/pc-bios/palcode-clipper b/pc-bios/palcode-clipper
index a92372c10..9956340cd 100755
--- a/pc-bios/palcode-clipper
+++ b/pc-bios/palcode-clipper
Binary files differ
diff --git a/pc-bios/q35-acpi-dsdt.aml b/pc-bios/q35-acpi-dsdt.aml
new file mode 100644
index 000000000..91ab67cad
--- /dev/null
+++ b/pc-bios/q35-acpi-dsdt.aml
Binary files differ
diff --git a/pc-bios/qemu-nsis.bmp b/pc-bios/qemu-nsis.bmp
new file mode 100644
index 000000000..ae82cd269
--- /dev/null
+++ b/pc-bios/qemu-nsis.bmp
Binary files differ
diff --git a/pc-bios/qemu-nsis.ico b/pc-bios/qemu-nsis.ico
new file mode 100644
index 000000000..1d0128cd4
--- /dev/null
+++ b/pc-bios/qemu-nsis.ico
Binary files differ
diff --git a/pc-bios/qemu_logo_no_text.svg b/pc-bios/qemu_logo_no_text.svg
new file mode 100644
index 000000000..24ca23a1e
--- /dev/null
+++ b/pc-bios/qemu_logo_no_text.svg
@@ -0,0 +1,976 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="111.71874"
+ height="111.12498"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:docname="qemu_logo_no_text.svg">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient4686">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4688" />
+ <stop
+ id="stop3956"
+ offset="0.75"
+ style="stop-color:#000000;stop-opacity:0.87843138;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.43921569;"
+ offset="0.75"
+ id="stop3958" />
+ <stop
+ id="stop3960"
+ offset="0.88"
+ style="stop-color:#181818;stop-opacity:1;" />
+ <stop
+ style="stop-color:#242424;stop-opacity:1;"
+ offset="0.88"
+ id="stop3962" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="1"
+ id="stop4690" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4467">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4469" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.8974359;"
+ offset="1"
+ id="stop4471" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4431">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4433" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4435" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4466">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4468" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4470" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4321">
+ <stop
+ style="stop-color:#ff6702;stop-opacity:1;"
+ offset="0"
+ id="stop4323" />
+ <stop
+ style="stop-color:#ff9a55;stop-opacity:1;"
+ offset="1"
+ id="stop4325" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4283">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4285" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop4287" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4251">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4253" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop4255" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4007">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop4009" />
+ <stop
+ style="stop-color:#ff9148;stop-opacity:1;"
+ offset="1"
+ id="stop4011" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999">
+ <stop
+ style="stop-color:#fff7f2;stop-opacity:1;"
+ offset="0"
+ id="stop4001" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4003" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3890">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3892" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3894" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3880">
+ <stop
+ style="stop-color:#eb7400;stop-opacity:1;"
+ offset="0"
+ id="stop3882" />
+ <stop
+ style="stop-color:#f7b06a;stop-opacity:1;"
+ offset="1"
+ id="stop3884" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4011">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3879">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90598291;"
+ offset="0"
+ id="stop3881" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3869">
+ <stop
+ style="stop-color:#c95000;stop-opacity:1;"
+ offset="0"
+ id="stop3871" />
+ <stop
+ style="stop-color:#ff9e5e;stop-opacity:1;"
+ offset="1"
+ id="stop3873" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3861">
+ <stop
+ style="stop-color:#f06000;stop-opacity:1;"
+ offset="0"
+ id="stop3863" />
+ <stop
+ style="stop-color:#ffccaa;stop-opacity:1;"
+ offset="1"
+ id="stop3865" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3826">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop3828" />
+ <stop
+ style="stop-color:#ff893b;stop-opacity:1;"
+ offset="1"
+ id="stop3830" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3879-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90598291;"
+ offset="0"
+ id="stop3881-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3869-5">
+ <stop
+ style="stop-color:#c95000;stop-opacity:1;"
+ offset="0"
+ id="stop3871-9" />
+ <stop
+ style="stop-color:#ff9e5e;stop-opacity:1;"
+ offset="1"
+ id="stop3873-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4"
+ id="linearGradient3885-6"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3869-2">
+ <stop
+ style="stop-color:#c95000;stop-opacity:1;"
+ offset="0"
+ id="stop3871-99" />
+ <stop
+ style="stop-color:#ff9e5e;stop-opacity:1;"
+ offset="1"
+ id="stop3873-6" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011"
+ id="radialGradient4017"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.23244854,1.600893,-1.0124495,0.14700695,145.40424,-26.300303)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-7"
+ id="linearGradient3885-6-2"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-5"
+ id="radialGradient4017-7"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.99779178,6.8718773,-4.3459674,0.6310314,452.75975,-225.98471)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-5">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-75"
+ id="linearGradient3885-6-8"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-75">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-4" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-0"
+ id="radialGradient4017-5"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.23244854,1.600893,-1.0124495,0.14700695,146.34996,53.681728)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-0">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-4" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-0"
+ id="linearGradient4117"
+ x1="107.03001"
+ y1="189.72537"
+ x2="107.18476"
+ y2="173.47537"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-7-2"
+ id="linearGradient3885-6-2-8"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-7-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-5-1"
+ id="radialGradient4017-7-9"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.99779178,6.8718773,-4.3459674,0.6310314,448.94742,-406.99277)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-5-1">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-7-2-7"
+ id="linearGradient3885-6-2-8-0"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-7-2-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9-6" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-5-1-5"
+ id="radialGradient4017-7-9-5"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.55965334,3.8543806,-2.4376181,0.3539404,454.75182,-145.44353)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-5-1-5">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9-6" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3879-4-7-2-4"
+ id="linearGradient3885-6-2-8-4"
+ x1="76.025352"
+ y1="124.8497"
+ x2="75.874107"
+ y2="143.03978"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3879-4-7-2-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9-3" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4011-5-1-7"
+ id="radialGradient4017-7-9-7"
+ cx="66.639"
+ cy="93.096375"
+ fx="66.639"
+ fy="93.096375"
+ r="11.515625"
+ gradientTransform="matrix(0.26837158,1.8482981,-1.1689154,0.16972569,466.57614,26.180822)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4011-5-1-7">
+ <stop
+ style="stop-color:#042dc8;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9-1" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3879-4-7-2-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4011-5-1-55">
+ <stop
+ style="stop-color:#000a30;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9-8" />
+ <stop
+ style="stop-color:#4260d5;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3890-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3892-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3894-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3880-4">
+ <stop
+ style="stop-color:#eb7400;stop-opacity:1;"
+ offset="0"
+ id="stop3882-5" />
+ <stop
+ style="stop-color:#f7b06a;stop-opacity:1;"
+ offset="1"
+ id="stop3884-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999-7">
+ <stop
+ style="stop-color:#fff7f2;stop-opacity:1;"
+ offset="0"
+ id="stop4001-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4003-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4007-9">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop4009-1" />
+ <stop
+ style="stop-color:#ff9148;stop-opacity:1;"
+ offset="1"
+ id="stop4011-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4007-9-5">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop4009-1-9" />
+ <stop
+ style="stop-color:#ff9148;stop-opacity:1;"
+ offset="1"
+ id="stop4011-9-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999-7-1">
+ <stop
+ style="stop-color:#fff7f2;stop-opacity:1;"
+ offset="0"
+ id="stop4001-9-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4003-4-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4007-9-5-3">
+ <stop
+ style="stop-color:#ff6600;stop-opacity:1;"
+ offset="0"
+ id="stop4009-1-9-3" />
+ <stop
+ style="stop-color:#ff9148;stop-opacity:1;"
+ offset="1"
+ id="stop4011-9-5-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3999-7-1-4">
+ <stop
+ style="stop-color:#fff7f2;stop-opacity:1;"
+ offset="0"
+ id="stop4001-9-1-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4003-4-4-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3879-4-7-2-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.93162394;"
+ offset="0"
+ id="stop3881-6-7-9-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3883-74-6-9-87" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4011-5-1-1">
+ <stop
+ style="stop-color:#fde8a1;stop-opacity:1;"
+ offset="0"
+ id="stop4013-1-9-63" />
+ <stop
+ style="stop-color:#2947b9;stop-opacity:1;"
+ offset="1"
+ id="stop4015-3-8-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4466"
+ id="linearGradient4472"
+ x1="161.7561"
+ y1="540.72662"
+ x2="161.7561"
+ y2="579.80206"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4321"
+ id="radialGradient4474"
+ cx="130.8242"
+ cy="575.27838"
+ fx="130.8242"
+ fy="575.27838"
+ r="49.498173"
+ gradientTransform="matrix(0.95670828,0.96684666,-0.72623533,0.71862001,423.45109,35.05138)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4466-5"
+ id="linearGradient4472-9"
+ x1="161.7561"
+ y1="540.72662"
+ x2="161.7561"
+ y2="579.80206"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4466-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4468-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4470-3" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4321-0"
+ id="radialGradient4474-6"
+ cx="130.8242"
+ cy="575.27838"
+ fx="130.8242"
+ fy="575.27838"
+ r="49.498173"
+ gradientTransform="matrix(0.95670828,0.96684666,-0.72623533,0.71862001,442.64399,170.9169)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4321-0">
+ <stop
+ style="stop-color:#ff6702;stop-opacity:1;"
+ offset="0"
+ id="stop4323-3" />
+ <stop
+ style="stop-color:#ff9a55;stop-opacity:1;"
+ offset="1"
+ id="stop4325-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4466-5-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4468-2-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4470-3-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4321-0-0">
+ <stop
+ style="stop-color:#ff6702;stop-opacity:1;"
+ offset="0"
+ id="stop4323-3-9" />
+ <stop
+ style="stop-color:#ff9a55;stop-opacity:1;"
+ offset="1"
+ id="stop4325-1-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4466-5-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4468-2-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4470-3-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4321-0-7">
+ <stop
+ style="stop-color:#ff6702;stop-opacity:1;"
+ offset="0"
+ id="stop4323-3-3" />
+ <stop
+ style="stop-color:#ff9a55;stop-opacity:1;"
+ offset="1"
+ id="stop4325-1-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4431"
+ id="linearGradient4437"
+ x1="142.81854"
+ y1="831.52283"
+ x2="142.81854"
+ y2="878.90735"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4467"
+ id="radialGradient4475"
+ cx="116.51958"
+ cy="98.282051"
+ fx="116.51958"
+ fy="98.282051"
+ r="55.859375"
+ gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,79.641615,-130.28522)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4431-3"
+ id="linearGradient4437-6"
+ x1="142.81854"
+ y1="831.52283"
+ x2="142.81854"
+ y2="878.90735"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4431-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4433-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4435-2" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4467-7"
+ id="radialGradient4475-0"
+ cx="116.51958"
+ cy="98.282051"
+ fx="116.51958"
+ fy="98.282051"
+ r="55.859375"
+ gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,225.10358,63.664066)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient4467-7">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4469-4" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.8974359;"
+ offset="1"
+ id="stop4471-7" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4467"
+ id="radialGradient3262"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.97442557,1.5088911,-0.83559154,0.53961599,59.641615,-150.28522)"
+ cx="116.51958"
+ cy="98.282051"
+ fx="116.51958"
+ fy="98.282051"
+ r="55.859375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4431"
+ id="linearGradient3264"
+ gradientUnits="userSpaceOnUse"
+ x1="142.81854"
+ y1="831.52283"
+ x2="142.81854"
+ y2="878.90735" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="5.6"
+ inkscape:cx="31.144191"
+ inkscape:cy="38.335716"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ showguides="false"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1056"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ fit-margin-left="0">
+ <sodipodi:guide
+ orientation="0,1"
+ position="72.563745,37.346999"
+ id="guide2989" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="74.584055,7.2949693"
+ id="guide2991" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="71.048515,20.426949"
+ id="guide2993" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="97.817565,20.174409"
+ id="guide2995" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="71.048515,20.426949"
+ id="guide3017" />
+ <inkscape:grid
+ type="xygrid"
+ id="grid3019"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="105.6589,-12.377861"
+ id="guide3021" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="126.6589,-16.377861"
+ id="guide3023" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="110.6589,-3.3778607"
+ id="guide3025" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="110.6589,-27.377861"
+ id="guide3027" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="19.658895,-35.37786"
+ id="guide3810" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="21.658895,-70.377861"
+ id="guide3814" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="2.301752,-9.4850007"
+ id="guide3856" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="26.601806,-9.4850007"
+ id="guide3887" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="44.658283,37.346999"
+ id="guide4019" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="126.6589,-27.377861"
+ id="guide4481" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="159.08747,-213.94929"
+ id="guide4483" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-42.341105,-35.859333)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient3262);fill-opacity:1;stroke:none"
+ d="m 98.2161,35.859333 c -30.850815,0 -55.874995,24.87043 -55.874995,55.562497 0,30.69207 25.02418,55.56249 55.874995,55.56249 10.09496,0 19.54625,-2.6525 27.71875,-7.3125 l 2.90625,7.3125 2.40625,0 20,0 0.125,0 -8.8125,-21.78124 c 7.21537,-9.3622 11.5,-21.07236 11.5,-33.78125 0,-30.692067 -24.99293,-55.562497 -55.84375,-55.562497 z"
+ id="path3834-7-7-2-5-5-0-5-4" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient3264);fill-opacity:1;stroke:none"
+ id="path3661"
+ sodipodi:cx="142.5"
+ sodipodi:cy="856.29077"
+ sodipodi:rx="35.357143"
+ sodipodi:ry="24.642857"
+ d="m 177.85714,856.29077 c 0,13.60988 -15.82993,24.64286 -35.35714,24.64286 -19.52721,0 -35.35714,-11.03298 -35.35714,-24.64286 0,-13.60987 15.82993,-24.64286 35.35714,-24.64286 19.52721,0 35.35714,11.03299 35.35714,24.64286 z"
+ transform="matrix(1.0465082,0,0,1.2920463,-51.641235,-1036.8612)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;stroke:none"
+ id="path4442"
+ sodipodi:cx="115.66247"
+ sodipodi:cy="856.39258"
+ sodipodi:rx="6.5659914"
+ sodipodi:ry="6.5659914"
+ d="m 122.22846,856.39258 c 0,3.6263 -2.9397,6.56599 -6.56599,6.56599 -3.6263,0 -6.56599,-2.93969 -6.56599,-6.56599 0,-3.6263 2.93969,-6.56599 6.56599,-6.56599 3.62629,0 6.56599,2.93969 6.56599,6.56599 z"
+ transform="translate(-12.329975,-797.60351)" />
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:none"
+ id="rect4444"
+ width="37.643608"
+ height="5.5005069"
+ x="101.55376"
+ y="48.297417"
+ transform="matrix(0.98974903,0.14281759,-0.18972639,0.981837,0,0)" />
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:none"
+ id="rect4446"
+ width="6.5659914"
+ height="2.9041886"
+ x="124.92451"
+ y="69.016899" />
+ <path
+ style="fill:#ff6600;fill-opacity:1"
+ d="m 83.38797,45.010543 c -0.057,2.18531 -3.865755,0.28296 -4.031245,2.78125 -4.22387,-1.88052 0.32884,2.87188 -0.0937,3.3125 l -0.0312,0 -0.3125,-0.0312 c -0.20386,-0.0728 -0.49977,-0.19904 -0.9375,-0.46875 -2.9499,2.35025 -3.02157,7.23369 -6.0625,9.9375 -1.99467,4.30504 -2.47977,8.98337 -3.9375,13.46875 -0.71796,4.30292 -1.34881,8.597857 -0.28125,12.906247 0.32053,3.50159 -0.68919,8.25865 2.5,10.71875 4.72728,3.88304 8.65575,8.79543 12.624995,13.46875 6.21914,7.65333 11.72948,15.86251 16.59375,24.4375 0.32431,-2.11756 1.10954,4.26459 2.53125,4.6875 -0.49161,-3.19231 -1.13213,-8.26328 -1.4375,-12.1875 -1.5814,-10.2909 -6.65305,-19.64903 -8.5625,-29.84375 -0.0587,-0.43037 -0.12809,-0.87203 -0.1875,-1.3125 l 0,-1.28125 -0.15625,0 c -0.62551,-5.04297 -0.8504,-10.46546 2.8125,-14.40625 3.73968,-3.772097 9.30633,-4.722447 13.8125,-7.343747 1.00194,-0.59119 2.04921,-1.07174 3.125,-1.40625 0.009,-0.003 0.0228,0.003 0.0312,0 3.11701,-0.96341 6.44862,-0.93323 9.6875,-0.40625 0.0479,0.008 0.10841,0.0233 0.15625,0.0312 0.29455,0.0493 0.61389,0.099 0.90625,0.15625 2.37136,0.21133 7.14463,1.13687 8,-0.5 -3.27225,-2.78631 -7.98526,-2.59211 -11.96875,-3.6875 -0.63059,-0.11469 -1.41182,-0.24041 -2.1875,-0.3125 l -3.90625,-0.875 -0.96875,-0.25 0,0.0312 -13.96875,-2.71875 c -0.22212,-0.20226 -0.46434,-0.40933 -0.6875,-0.5625 l 13.625,1.6875 0,-0.0625 c 0.48011,0.10699 0.95576,0.19361 1.4375,0.25 l 0,0.0312 9.625,1.78125 c 1.66103,0.61952 3.4322,1.08374 5.09375,1.1875 2.74263,0.39907 6.22526,4.49092 7.125,4.6875 -0.44096,-4.307 -4.7422,-6.23586 -8.3125,-7.5 -4.1712,-2.02803 -10.4023,-1.95417 -11.0625,-7.5625 -0.1756,-0.39076 -0.34902,-0.78118 -0.5625,-1.15625 l -1.625,-2.15625 0.0625,-0.0312 c -2.21724,-2.61691 -5.34011,-4.52196 -8.65625,-5.25 -3.2914,-1.13611 -6.98773,-2.2671 -10.46875,-2.71875 -1.18132,3.47826 -2.5031,-2.75561 -5.34375,-0.90625 -2.48996,0.29488 -2.14614,0.95256 -4,-0.625 z m 17.90625,10.15625 c 0.90187,-0.0238 1.93277,0.14208 2.96875,0.5 2.76259,0.95447 4.56151,2.96523 4.03125,4.5 -0.53026,1.53477 -3.20616,1.98572 -5.96875,1.03125 -2.76259,-0.95447 -4.5615,-2.93398 -4.03125,-4.46875 0.33141,-0.95923 1.49689,-1.52281 3,-1.5625 z"
+ id="path3499-9-7"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
new file mode 100644
index 000000000..05fc7c2fa
--- /dev/null
+++ b/pc-bios/s390-ccw.img
Binary files differ
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
new file mode 100644
index 000000000..ad55a14a1
--- /dev/null
+++ b/pc-bios/s390-ccw/Makefile
@@ -0,0 +1,26 @@
+all: build-all
+# Dummy command so that make thinks it has done something
+ @true
+
+include ../../config-host.mak
+include $(SRC_PATH)/rules.mak
+
+$(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
+
+.PHONY : all clean build-all
+
+OBJECTS=main.o bootmap.o sclp-ascii.o virtio.o start.o
+CFLAGS += -fno-stack-protector
+# XXX find a more clever to locate the bootloader
+LDFLAGS += -Wl,-Ttext,0x7e00000,-Tbss,0x7f00000 -nostdlib
+
+build-all: s390-ccw.img
+
+s390-ccw.elf: $(OBJECTS)
+ $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS)," Building $(TARGET_DIR)$@")
+
+s390-ccw.img: s390-ccw.elf
+ $(call quiet-command,strip $< -o $@," Stripping $(TARGET_DIR)$@")
+
+clean:
+ rm -f *.o *.d *.img *.elf *~
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
new file mode 100644
index 000000000..53a460df8
--- /dev/null
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -0,0 +1,235 @@
+/*
+ * QEMU S390 bootmap interpreter
+ *
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+
+// #define DEBUG_FALLBACK
+
+#ifdef DEBUG_FALLBACK
+#define dputs(txt) \
+ do { sclp_print("zipl: " txt); } while (0)
+#else
+#define dputs(fmt, ...) \
+ do { } while (0)
+#endif
+
+struct scsi_blockptr {
+ uint64_t blockno;
+ uint16_t size;
+ uint16_t blockct;
+ uint8_t reserved[4];
+} __attribute__ ((packed));
+
+struct component_entry {
+ struct scsi_blockptr data;
+ uint8_t pad[7];
+ uint8_t component_type;
+ uint64_t load_address;
+} __attribute((packed));
+
+struct component_header {
+ uint8_t magic[4];
+ uint8_t type;
+ uint8_t reserved[27];
+} __attribute((packed));
+
+struct mbr {
+ uint8_t magic[4];
+ uint32_t version_id;
+ uint8_t reserved[8];
+ struct scsi_blockptr blockptr;
+} __attribute__ ((packed));
+
+#define ZIPL_MAGIC "zIPL"
+
+#define ZIPL_COMP_HEADER_IPL 0x00
+#define ZIPL_COMP_HEADER_DUMP 0x01
+
+#define ZIPL_COMP_ENTRY_LOAD 0x02
+#define ZIPL_COMP_ENTRY_EXEC 0x01
+
+/* Scratch space */
+static uint8_t sec[SECTOR_SIZE] __attribute__((__aligned__(SECTOR_SIZE)));
+
+/* Check for ZIPL magic. Returns 0 if not matched. */
+static int zipl_magic(uint8_t *ptr)
+{
+ uint32_t *p = (void*)ptr;
+ uint32_t *z = (void*)ZIPL_MAGIC;
+
+ if (*p != *z) {
+ debug_print_int("invalid magic", *p);
+ virtio_panic("invalid magic");
+ }
+
+ return 1;
+}
+
+static int zipl_load_segment(struct component_entry *entry)
+{
+ const int max_entries = (SECTOR_SIZE / sizeof(struct scsi_blockptr));
+ struct scsi_blockptr *bprs = (void*)sec;
+ uint64_t blockno;
+ long address;
+ int i;
+
+ blockno = entry->data.blockno;
+ address = entry->load_address;
+
+ debug_print_int("loading segment at block", blockno);
+ debug_print_int("addr", address);
+
+ do {
+ if (virtio_read(blockno, (uint8_t *)bprs)) {
+ debug_print_int("failed reading bprs at", blockno);
+ goto fail;
+ }
+
+ for (i = 0;; i++) {
+ u64 *cur_desc = (void*)&bprs[i];
+
+ blockno = bprs[i].blockno;
+ if (!blockno)
+ break;
+
+ /* we need the updated blockno for the next indirect entry in the
+ chain, but don't want to advance address */
+ if (i == (max_entries - 1))
+ break;
+
+ address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
+ (void*)address);
+ if (address == -1)
+ goto fail;
+ }
+ } while (blockno);
+
+ return 0;
+
+fail:
+ sclp_print("failed loading segment\n");
+ return -1;
+}
+
+/* Run a zipl program */
+static int zipl_run(struct scsi_blockptr *pte)
+{
+ struct component_header *header;
+ struct component_entry *entry;
+ void (*ipl)(void);
+ uint8_t tmp_sec[SECTOR_SIZE];
+
+ virtio_read(pte->blockno, tmp_sec);
+ header = (struct component_header *)tmp_sec;
+
+ if (!zipl_magic(tmp_sec)) {
+ goto fail;
+ }
+
+ if (header->type != ZIPL_COMP_HEADER_IPL) {
+ goto fail;
+ }
+
+ dputs("start loading images\n");
+
+ /* Load image(s) into RAM */
+ entry = (struct component_entry *)(&header[1]);
+ while (entry->component_type == ZIPL_COMP_ENTRY_LOAD) {
+ if (zipl_load_segment(entry) < 0) {
+ goto fail;
+ }
+
+ entry++;
+
+ if ((uint8_t*)(&entry[1]) > (tmp_sec + SECTOR_SIZE)) {
+ goto fail;
+ }
+ }
+
+ if (entry->component_type != ZIPL_COMP_ENTRY_EXEC) {
+ goto fail;
+ }
+
+ /* Ensure the guest output starts fresh */
+ sclp_print("\n");
+
+ /* And run the OS! */
+ ipl = (void*)(entry->load_address & 0x7fffffff);
+ debug_print_addr("set IPL addr to", ipl);
+ /* should not return */
+ ipl();
+
+ return 0;
+
+fail:
+ sclp_print("failed running zipl\n");
+ return -1;
+}
+
+int zipl_load(void)
+{
+ struct mbr *mbr = (void*)sec;
+ uint8_t *ns, *ns_end;
+ int program_table_entries = 0;
+ int pte_len = sizeof(struct scsi_blockptr);
+ struct scsi_blockptr *prog_table_entry;
+ const char *error = "";
+
+ /* Grab the MBR */
+ virtio_read(0, (void*)mbr);
+
+ dputs("checking magic\n");
+
+ if (!zipl_magic(mbr->magic)) {
+ error = "zipl_magic 1";
+ goto fail;
+ }
+
+ debug_print_int("program table", mbr->blockptr.blockno);
+
+ /* Parse the program table */
+ if (virtio_read(mbr->blockptr.blockno, sec)) {
+ error = "virtio_read";
+ goto fail;
+ }
+
+ if (!zipl_magic(sec)) {
+ error = "zipl_magic 2";
+ goto fail;
+ }
+
+ ns_end = sec + SECTOR_SIZE;
+ for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns++) {
+ prog_table_entry = (struct scsi_blockptr *)ns;
+ if (!prog_table_entry->blockno) {
+ break;
+ }
+
+ program_table_entries++;
+ }
+
+ debug_print_int("program table entries", program_table_entries);
+
+ if (!program_table_entries) {
+ goto fail;
+ }
+
+ /* Run the default entry */
+
+ prog_table_entry = (struct scsi_blockptr *)(sec + pte_len);
+
+ return zipl_run(prog_table_entry);
+
+fail:
+ sclp_print("failed loading zipl: ");
+ sclp_print(error);
+ sclp_print("\n");
+ return -1;
+}
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
new file mode 100644
index 000000000..f5b4549ea
--- /dev/null
+++ b/pc-bios/s390-ccw/cio.h
@@ -0,0 +1,342 @@
+/*
+ * Channel IO definitions
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * Inspired by various s390 headers in Linux 3.9.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef CIO_H
+#define CIO_H
+
+/*
+ * path management control word
+ */
+struct pmcw {
+ __u32 intparm; /* interruption parameter */
+ __u32 qf : 1; /* qdio facility */
+ __u32 w : 1;
+ __u32 isc : 3; /* interruption sublass */
+ __u32 res5 : 3; /* reserved zeros */
+ __u32 ena : 1; /* enabled */
+ __u32 lm : 2; /* limit mode */
+ __u32 mme : 2; /* measurement-mode enable */
+ __u32 mp : 1; /* multipath mode */
+ __u32 tf : 1; /* timing facility */
+ __u32 dnv : 1; /* device number valid */
+ __u32 dev : 16; /* device number */
+ __u8 lpm; /* logical path mask */
+ __u8 pnom; /* path not operational mask */
+ __u8 lpum; /* last path used mask */
+ __u8 pim; /* path installed mask */
+ __u16 mbi; /* measurement-block index */
+ __u8 pom; /* path operational mask */
+ __u8 pam; /* path available mask */
+ __u8 chpid[8]; /* CHPID 0-7 (if available) */
+ __u32 unused1 : 8; /* reserved zeros */
+ __u32 st : 3; /* subchannel type */
+ __u32 unused2 : 18; /* reserved zeros */
+ __u32 mbfc : 1; /* measurement block format control */
+ __u32 xmwme : 1; /* extended measurement word mode enable */
+ __u32 csense : 1; /* concurrent sense; can be enabled ...*/
+ /* ... per MSCH, however, if facility */
+ /* ... is not installed, this results */
+ /* ... in an operand exception. */
+} __attribute__ ((packed));
+
+/* Target SCHIB configuration. */
+struct schib_config {
+ __u64 mba;
+ __u32 intparm;
+ __u16 mbi;
+ __u32 isc:3;
+ __u32 ena:1;
+ __u32 mme:2;
+ __u32 mp:1;
+ __u32 csense:1;
+ __u32 mbfc:1;
+} __attribute__ ((packed));
+
+struct scsw {
+ __u16 flags;
+ __u16 ctrl;
+ __u32 cpa;
+ __u8 dstat;
+ __u8 cstat;
+ __u16 count;
+} __attribute__ ((packed));
+
+#define SCSW_FCTL_CLEAR_FUNC 0x1000
+#define SCSW_FCTL_HALT_FUNC 0x2000
+#define SCSW_FCTL_START_FUNC 0x4000
+
+/*
+ * subchannel information block
+ */
+struct schib {
+ struct pmcw pmcw; /* path management control word */
+ struct scsw scsw; /* subchannel status word */
+ __u64 mba; /* measurement block address */
+ __u8 mda[4]; /* model dependent area */
+} __attribute__ ((packed,aligned(4)));
+
+struct subchannel_id {
+ __u32 cssid : 8;
+ __u32 : 4;
+ __u32 m : 1;
+ __u32 ssid : 2;
+ __u32 one : 1;
+ __u32 sch_no : 16;
+} __attribute__ ((packed, aligned(4)));
+
+struct chsc_header {
+ __u16 length;
+ __u16 code;
+} __attribute__((packed));
+
+struct chsc_area_sda {
+ struct chsc_header request;
+ __u8 reserved1:4;
+ __u8 format:4;
+ __u8 reserved2;
+ __u16 operation_code;
+ __u32 reserved3;
+ __u32 reserved4;
+ __u32 operation_data_area[252];
+ struct chsc_header response;
+ __u32 reserved5:4;
+ __u32 format2:4;
+ __u32 reserved6:24;
+} __attribute__((packed));
+
+/*
+ * TPI info structure
+ */
+struct tpi_info {
+ struct subchannel_id schid;
+ __u32 intparm; /* interruption parameter */
+ __u32 adapter_IO : 1;
+ __u32 reserved2 : 1;
+ __u32 isc : 3;
+ __u32 reserved3 : 12;
+ __u32 int_type : 3;
+ __u32 reserved4 : 12;
+} __attribute__ ((packed));
+
+/* channel command word (type 1) */
+struct ccw1 {
+ __u8 cmd_code;
+ __u8 flags;
+ __u16 count;
+ __u32 cda;
+} __attribute__ ((packed));
+
+#define CCW_FLAG_DC 0x80
+#define CCW_FLAG_CC 0x40
+#define CCW_FLAG_SLI 0x20
+#define CCW_FLAG_SKIP 0x10
+#define CCW_FLAG_PCI 0x08
+#define CCW_FLAG_IDA 0x04
+#define CCW_FLAG_SUSPEND 0x02
+
+#define CCW_CMD_NOOP 0x03
+#define CCW_CMD_BASIC_SENSE 0x04
+#define CCW_CMD_TIC 0x08
+#define CCW_CMD_SENSE_ID 0xe4
+
+#define CCW_CMD_SET_VQ 0x13
+#define CCW_CMD_VDEV_RESET 0x33
+#define CCW_CMD_READ_FEAT 0x12
+#define CCW_CMD_WRITE_FEAT 0x11
+#define CCW_CMD_READ_CONF 0x22
+#define CCW_CMD_WRITE_CONF 0x21
+#define CCW_CMD_WRITE_STATUS 0x31
+#define CCW_CMD_SET_IND 0x43
+#define CCW_CMD_SET_CONF_IND 0x53
+#define CCW_CMD_READ_VQ_CONF 0x32
+
+/*
+ * Command-mode operation request block
+ */
+struct cmd_orb {
+ __u32 intparm; /* interruption parameter */
+ __u32 key:4; /* flags, like key, suspend control, etc. */
+ __u32 spnd:1; /* suspend control */
+ __u32 res1:1; /* reserved */
+ __u32 mod:1; /* modification control */
+ __u32 sync:1; /* synchronize control */
+ __u32 fmt:1; /* format control */
+ __u32 pfch:1; /* prefetch control */
+ __u32 isic:1; /* initial-status-interruption control */
+ __u32 alcc:1; /* address-limit-checking control */
+ __u32 ssic:1; /* suppress-suspended-interr. control */
+ __u32 res2:1; /* reserved */
+ __u32 c64:1; /* IDAW/QDIO 64 bit control */
+ __u32 i2k:1; /* IDAW 2/4kB block size control */
+ __u32 lpm:8; /* logical path mask */
+ __u32 ils:1; /* incorrect length */
+ __u32 zero:6; /* reserved zeros */
+ __u32 orbx:1; /* ORB extension control */
+ __u32 cpa; /* channel program address */
+} __attribute__ ((packed, aligned(4)));
+
+struct ciw {
+ __u8 type;
+ __u8 command;
+ __u16 count;
+};
+
+/*
+ * sense-id response buffer layout
+ */
+struct senseid {
+ /* common part */
+ __u8 reserved; /* always 0x'FF' */
+ __u16 cu_type; /* control unit type */
+ __u8 cu_model; /* control unit model */
+ __u16 dev_type; /* device type */
+ __u8 dev_model; /* device model */
+ __u8 unused; /* padding byte */
+ /* extended part */
+ struct ciw ciw[62];
+} __attribute__ ((packed, aligned(4)));
+
+/* interruption response block */
+struct irb {
+ struct scsw scsw;
+ __u32 esw[5];
+ __u32 ecw[8];
+ __u32 emw[8];
+} __attribute__ ((packed, aligned(4)));
+
+/*
+ * Some S390 specific IO instructions as inline
+ */
+
+static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
+{
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode = -EIO;
+
+ asm volatile(
+ " stsch 0(%3)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ : "+d" (ccode), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int msch(struct subchannel_id schid, struct schib *addr)
+{
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode;
+
+ asm volatile(
+ " msch 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int msch_err(struct subchannel_id schid, struct schib *addr)
+{
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode = -EIO;
+
+ asm volatile(
+ " msch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ : "+d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int tsch(struct subchannel_id schid, struct irb *addr)
+{
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode;
+
+ asm volatile(
+ " tsch 0(%3)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
+{
+ register struct subchannel_id reg1 asm("1") = schid;
+ int ccode = -EIO;
+
+ asm volatile(
+ " ssch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ : "+d" (ccode)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc", "memory");
+ return ccode;
+}
+
+static inline int csch(struct subchannel_id schid)
+{
+ register struct subchannel_id reg1 asm("1") = schid;
+ int ccode;
+
+ asm volatile(
+ " csch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode)
+ : "d" (reg1)
+ : "cc");
+ return ccode;
+}
+
+static inline int tpi(struct tpi_info *addr)
+{
+ int ccode;
+
+ asm volatile(
+ " tpi 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode), "=m" (*addr)
+ : "a" (addr)
+ : "cc");
+ return ccode;
+}
+
+static inline int chsc(void *chsc_area)
+{
+ typedef struct { char _[4096]; } addr_type;
+ int cc;
+
+ asm volatile(
+ " .insn rre,0xb25f0000,%2,0\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (cc), "=m" (*(addr_type *) chsc_area)
+ : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
+ : "cc");
+ return cc;
+}
+
+#endif /* CIO_H */
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
new file mode 100644
index 000000000..c5d533231
--- /dev/null
+++ b/pc-bios/s390-ccw/main.c
@@ -0,0 +1,80 @@
+/*
+ * S390 virtio-ccw loading program
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+
+struct subchannel_id blk_schid;
+char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
+uint64_t boot_value;
+
+void virtio_panic(const char *string)
+{
+ sclp_print(string);
+ disabled_wait();
+ while (1) { }
+}
+
+static void virtio_setup(uint64_t dev_info)
+{
+ struct schib schib;
+ int i;
+ int r;
+ bool found = false;
+ bool check_devno = false;
+ uint16_t dev_no = -1;
+ blk_schid.one = 1;
+
+ if (dev_info != -1) {
+ check_devno = true;
+ dev_no = dev_info & 0xffff;
+ debug_print_int("device no. ", dev_no);
+ blk_schid.ssid = (dev_info >> 16) & 0x3;
+ if (blk_schid.ssid != 0) {
+ debug_print_int("ssid ", blk_schid.ssid);
+ if (enable_mss_facility() != 0) {
+ virtio_panic("Failed to enable mss facility\n");
+ }
+ }
+ }
+
+ for (i = 0; i < 0x10000; i++) {
+ blk_schid.sch_no = i;
+ r = stsch_err(blk_schid, &schib);
+ if (r == 3) {
+ break;
+ }
+ if (schib.pmcw.dnv) {
+ if (!check_devno || (schib.pmcw.dev == dev_no)) {
+ if (virtio_is_blk(blk_schid)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!found) {
+ virtio_panic("No virtio-blk device found!\n");
+ }
+
+ virtio_setup_block(blk_schid);
+}
+
+int main(void)
+{
+ sclp_setup();
+ debug_print_int("boot reg[7] ", boot_value);
+ virtio_setup(boot_value);
+
+ if (zipl_load() < 0)
+ sclp_print("Failed to load OS from hard disk\n");
+ disabled_wait();
+ while (1) { }
+}
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
new file mode 100644
index 000000000..5e871ac84
--- /dev/null
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -0,0 +1,135 @@
+/*
+ * S390 CCW boot loader
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef S390_CCW_H
+#define S390_CCW_H
+
+/* #define DEBUG */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+typedef unsigned long ulong;
+typedef long size_t;
+typedef int bool;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+typedef unsigned long long __u64;
+
+#define true 1
+#define false 0
+#define PAGE_SIZE 4096
+
+#ifndef EIO
+#define EIO 1
+#endif
+#ifndef EBUSY
+#define EBUSY 2
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include "cio.h"
+
+/* start.s */
+void disabled_wait(void);
+
+/* main.c */
+void virtio_panic(const char *string);
+
+/* sclp-ascii.c */
+void sclp_print(const char *string);
+void sclp_setup(void);
+
+/* virtio.c */
+unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
+ ulong subchan_id, void *load_addr);
+bool virtio_is_blk(struct subchannel_id schid);
+void virtio_setup_block(struct subchannel_id schid);
+int virtio_read(ulong sector, void *load_addr);
+int enable_mss_facility(void);
+
+/* bootmap.c */
+int zipl_load(void);
+
+static inline void *memset(void *s, int c, size_t n)
+{
+ int i;
+ unsigned char *p = s;
+
+ for (i = 0; i < n; i++) {
+ p[i] = c;
+ }
+
+ return s;
+}
+
+static inline void fill_hex(char *out, unsigned char val)
+{
+ const char hex[] = "0123456789abcdef";
+
+ out[0] = hex[(val >> 4) & 0xf];
+ out[1] = hex[val & 0xf];
+}
+
+static inline void print_int(const char *desc, u64 addr)
+{
+ unsigned char *addr_c = (unsigned char*)&addr;
+ char out[] = ": 0xffffffffffffffff\n";
+ unsigned int i;
+
+ for (i = 0; i < sizeof(addr); i++) {
+ fill_hex(&out[4 + (i*2)], addr_c[i]);
+ }
+
+ sclp_print(desc);
+ sclp_print(out);
+}
+
+static inline void debug_print_int(const char *desc, u64 addr)
+{
+#ifdef DEBUG
+ print_int(desc, addr);
+#endif
+}
+
+static inline void debug_print_addr(const char *desc, void *p)
+{
+#ifdef DEBUG
+ debug_print_int(desc, (unsigned int)(unsigned long)p);
+#endif
+}
+
+/***********************************************
+ * Hypercall functions *
+ ***********************************************/
+
+#define KVM_S390_VIRTIO_NOTIFY 0
+#define KVM_S390_VIRTIO_RESET 1
+#define KVM_S390_VIRTIO_SET_STATUS 2
+#define KVM_S390_VIRTIO_CCW_NOTIFY 3
+
+static inline void yield(void)
+{
+ asm volatile ("diag 0,0,0x44"
+ : :
+ : "memory", "cc");
+}
+
+#define SECTOR_SIZE 512
+
+#endif /* S390_CCW_H */
diff --git a/pc-bios/s390-ccw/sclp-ascii.c b/pc-bios/s390-ccw/sclp-ascii.c
new file mode 100644
index 000000000..1c9393710
--- /dev/null
+++ b/pc-bios/s390-ccw/sclp-ascii.c
@@ -0,0 +1,81 @@
+/*
+ * SCLP ASCII access driver
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+#include "sclp.h"
+
+static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
+
+/* Perform service call. Return 0 on success, non-zero otherwise. */
+static int sclp_service_call(unsigned int command, void *sccb)
+{
+ int cc;
+
+ asm volatile(
+ " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */
+ " ipm %0\n"
+ " srl %0,28"
+ : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
+ : "cc", "memory");
+ if (cc == 3)
+ return -EIO;
+ if (cc == 2)
+ return -EBUSY;
+ return 0;
+}
+
+static void sclp_set_write_mask(void)
+{
+ WriteEventMask *sccb = (void*)_sccb;
+
+ sccb->h.length = sizeof(WriteEventMask);
+ sccb->mask_length = sizeof(unsigned int);
+ sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
+ sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
+ sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+ sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
+
+ sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
+}
+
+void sclp_setup(void)
+{
+ sclp_set_write_mask();
+}
+
+static int _strlen(const char *str)
+{
+ int i;
+ for (i = 0; *str; i++)
+ str++;
+ return i;
+}
+
+static void _memcpy(char *dest, const char *src, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ dest[i] = src[i];
+}
+
+void sclp_print(const char *str)
+{
+ int len = _strlen(str);
+ WriteEventData *sccb = (void*)_sccb;
+
+ sccb->h.length = sizeof(WriteEventData) + len;
+ sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
+ sccb->ebh.length = sizeof(EventBufferHeader) + len;
+ sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
+ sccb->ebh.flags = 0;
+ _memcpy(sccb->data, str, len);
+
+ sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
+}
diff --git a/pc-bios/s390-ccw/sclp.h b/pc-bios/s390-ccw/sclp.h
new file mode 100644
index 000000000..3cbfb7893
--- /dev/null
+++ b/pc-bios/s390-ccw/sclp.h
@@ -0,0 +1,107 @@
+/*
+ * SCLP ASCII access driver
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef SCLP_H
+#define SCLP_H
+
+/* SCLP command codes */
+#define SCLP_CMDW_READ_SCP_INFO 0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
+#define SCLP_CMD_READ_EVENT_DATA 0x00770005
+#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005
+#define SCLP_CMD_READ_EVENT_DATA 0x00770005
+#define SCLP_CMD_WRITE_EVENT_DATA 0x00760005
+#define SCLP_CMD_WRITE_EVENT_MASK 0x00780005
+
+/* SCLP response codes */
+#define SCLP_RC_NORMAL_READ_COMPLETION 0x0010
+#define SCLP_RC_NORMAL_COMPLETION 0x0020
+#define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0
+#define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340
+#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300
+#define SCLP_RC_INVALID_FUNCTION 0x40f0
+#define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0
+#define SCLP_RC_INVALID_SELECTION_MASK 0x70f0
+#define SCLP_RC_INCONSISTENT_LENGTHS 0x72f0
+#define SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR 0x73f0
+#define SCLP_RC_INVALID_MASK_LENGTH 0x74f0
+
+/* Service Call Control Block (SCCB) and its elements */
+
+#define SCCB_SIZE 4096
+
+#define SCLP_VARIABLE_LENGTH_RESPONSE 0x80
+#define SCLP_EVENT_BUFFER_ACCEPTED 0x80
+
+#define SCLP_FC_NORMAL_WRITE 0
+
+typedef struct SCCBHeader {
+ uint16_t length;
+ uint8_t function_code;
+ uint8_t control_mask[3];
+ uint16_t response_code;
+} __attribute__((packed)) SCCBHeader;
+
+#define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader))
+
+typedef struct ReadInfo {
+ SCCBHeader h;
+ uint16_t rnmax;
+ uint8_t rnsize;
+} __attribute__((packed)) ReadInfo;
+
+typedef struct SCCB {
+ SCCBHeader h;
+ char data[SCCB_DATA_LEN];
+ } __attribute__((packed)) SCCB;
+
+/* SCLP event types */
+#define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a
+#define SCLP_EVENT_SIGNAL_QUIESCE 0x1d
+
+/* SCLP event masks */
+#define SCLP_EVENT_MASK_SIGNAL_QUIESCE 0x00000008
+#define SCLP_EVENT_MASK_MSG_ASCII 0x00000040
+
+#define SCLP_UNCONDITIONAL_READ 0x00
+#define SCLP_SELECTIVE_READ 0x01
+
+typedef struct WriteEventMask {
+ SCCBHeader h;
+ uint16_t _reserved;
+ uint16_t mask_length;
+ uint32_t cp_receive_mask;
+ uint32_t cp_send_mask;
+ uint32_t send_mask;
+ uint32_t receive_mask;
+} __attribute__((packed)) WriteEventMask;
+
+typedef struct EventBufferHeader {
+ uint16_t length;
+ uint8_t type;
+ uint8_t flags;
+ uint16_t _reserved;
+} __attribute__((packed)) EventBufferHeader;
+
+typedef struct WriteEventData {
+ SCCBHeader h;
+ EventBufferHeader ebh;
+ char data[0];
+} __attribute__((packed)) WriteEventData;
+
+typedef struct ReadEventData {
+ SCCBHeader h;
+ EventBufferHeader ebh;
+ uint32_t mask;
+} __attribute__((packed)) ReadEventData;
+
+#define __pa(x) (x)
+
+#endif /* SCLP_H */
diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
new file mode 100644
index 000000000..5d5df0d61
--- /dev/null
+++ b/pc-bios/s390-ccw/start.S
@@ -0,0 +1,33 @@
+/*
+ * First stage boot loader for virtio devices. The compiled output goes
+ * into the pc-bios directory of qemu.
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ * Copyright 2013 IBM Corp.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+ .globl _start
+_start:
+
+larl %r15, stack + 0x8000 /* Set up stack */
+larl %r6, boot_value
+stg %r7, 0(%r6) /* save the boot_value before any function calls */
+j main /* And call C */
+
+/*
+ * void disabled_wait(void)
+ *
+ * stops the current guest cpu.
+ */
+ .globl disabled_wait
+disabled_wait:
+ larl %r1,disabled_wait_psw
+ lpswe 0(%r1)
+
+ .align 8
+disabled_wait_psw:
+ .quad 0x0002000180000000,0x0000000000000000
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
new file mode 100644
index 000000000..49f2d291f
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio.c
@@ -0,0 +1,321 @@
+/*
+ * Virtio driver bits
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "s390-ccw.h"
+#include "virtio.h"
+
+struct vring block;
+
+static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+
+static long kvm_hypercall(unsigned long nr, unsigned long param1,
+ unsigned long param2)
+{
+ register ulong r_nr asm("1") = nr;
+ register ulong r_param1 asm("2") = param1;
+ register ulong r_param2 asm("3") = param2;
+ register long retval asm("2");
+
+ asm volatile ("diag 2,4,0x500"
+ : "=d" (retval)
+ : "d" (r_nr), "0" (r_param1), "r"(r_param2)
+ : "memory", "cc");
+
+ return retval;
+}
+
+static void virtio_notify(struct subchannel_id schid)
+{
+ kvm_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, *(u32*)&schid, 0);
+}
+
+/***********************************************
+ * Virtio functions *
+ ***********************************************/
+
+static int drain_irqs(struct subchannel_id schid)
+{
+ struct irb irb = {};
+ int r = 0;
+
+ while (1) {
+ /* FIXME: make use of TPI, for that enable subchannel and isc */
+ if (tsch(schid, &irb)) {
+ /* Might want to differentiate error codes later on. */
+ if (irb.scsw.cstat) {
+ r = -EIO;
+ } else if (irb.scsw.dstat != 0xc) {
+ r = -EIO;
+ }
+ return r;
+ }
+ }
+}
+
+static int run_ccw(struct subchannel_id schid, int cmd, void *ptr, int len)
+{
+ struct ccw1 ccw = {};
+ struct cmd_orb orb = {};
+ struct schib schib;
+ int r;
+
+ /* start command processing */
+ stsch_err(schid, &schib);
+ schib.scsw.ctrl = SCSW_FCTL_START_FUNC;
+ msch(schid, &schib);
+
+ /* start subchannel command */
+ orb.fmt = 1;
+ orb.cpa = (u32)(long)&ccw;
+ orb.lpm = 0x80;
+
+ ccw.cmd_code = cmd;
+ ccw.cda = (long)ptr;
+ ccw.count = len;
+
+ r = ssch(schid, &orb);
+ /*
+ * XXX Wait until device is done processing the CCW. For now we can
+ * assume that a simple tsch will have finished the CCW processing,
+ * but the architecture allows for asynchronous operation
+ */
+ if (!r) {
+ r = drain_irqs(schid);
+ }
+ return r;
+}
+
+static void virtio_set_status(struct subchannel_id schid,
+ unsigned long dev_addr)
+{
+ unsigned char status = dev_addr;
+ if (run_ccw(schid, CCW_CMD_WRITE_STATUS, &status, sizeof(status))) {
+ virtio_panic("Could not write status to host!\n");
+ }
+}
+
+static void virtio_reset(struct subchannel_id schid)
+{
+ run_ccw(schid, CCW_CMD_VDEV_RESET, NULL, 0);
+}
+
+static void vring_init(struct vring *vr, unsigned int num, void *p,
+ unsigned long align)
+{
+ debug_print_addr("init p", p);
+ vr->num = num;
+ vr->desc = p;
+ vr->avail = p + num*sizeof(struct vring_desc);
+ vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1)
+ & ~(align - 1));
+
+ /* Zero out all relevant field */
+ vr->avail->flags = 0;
+ vr->avail->idx = 0;
+
+ /* We're running with interrupts off anyways, so don't bother */
+ vr->used->flags = VRING_USED_F_NO_NOTIFY;
+ vr->used->idx = 0;
+
+ debug_print_addr("init vr", vr);
+}
+
+static void vring_notify(struct subchannel_id schid)
+{
+ virtio_notify(schid);
+}
+
+static void vring_send_buf(struct vring *vr, void *p, int len, int flags)
+{
+ /* For follow-up chains we need to keep the first entry point */
+ if (!(flags & VRING_HIDDEN_IS_CHAIN)) {
+ vr->avail->ring[vr->avail->idx % vr->num] = vr->next_idx;
+ }
+
+ vr->desc[vr->next_idx].addr = (ulong)p;
+ vr->desc[vr->next_idx].len = len;
+ vr->desc[vr->next_idx].flags = flags & ~VRING_HIDDEN_IS_CHAIN;
+ vr->desc[vr->next_idx].next = vr->next_idx;
+ vr->desc[vr->next_idx].next++;
+ vr->next_idx++;
+
+ /* Chains only have a single ID */
+ if (!(flags & VRING_DESC_F_NEXT)) {
+ vr->avail->idx++;
+ }
+
+ vr->used->idx = vr->next_idx;
+}
+
+static u64 get_clock(void)
+{
+ u64 r;
+
+ asm volatile("stck %0" : "=Q" (r) : : "cc");
+ return r;
+}
+
+static ulong get_second(void)
+{
+ return (get_clock() >> 12) / 1000000;
+}
+
+/*
+ * Wait for the host to reply.
+ *
+ * timeout is in seconds if > 0.
+ *
+ * Returns 0 on success, 1 on timeout.
+ */
+static int vring_wait_reply(struct vring *vr, int timeout)
+{
+ ulong target_second = get_second() + timeout;
+ struct subchannel_id schid = vr->schid;
+ int r = 0;
+
+ while (vr->used->idx == vr->next_idx) {
+ vring_notify(schid);
+ if (timeout && (get_second() >= target_second)) {
+ r = 1;
+ break;
+ }
+ yield();
+ }
+
+ vr->next_idx = 0;
+ vr->desc[0].len = 0;
+ vr->desc[0].flags = 0;
+
+ return r;
+}
+
+/***********************************************
+ * Virtio block *
+ ***********************************************/
+
+static int virtio_read_many(ulong sector, void *load_addr, int sec_num)
+{
+ struct virtio_blk_outhdr out_hdr;
+ u8 status;
+ int r;
+
+ /* Tell the host we want to read */
+ out_hdr.type = VIRTIO_BLK_T_IN;
+ out_hdr.ioprio = 99;
+ out_hdr.sector = sector;
+
+ vring_send_buf(&block, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT);
+
+ /* This is where we want to receive data */
+ vring_send_buf(&block, load_addr, SECTOR_SIZE * sec_num,
+ VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN |
+ VRING_DESC_F_NEXT);
+
+ /* status field */
+ vring_send_buf(&block, &status, sizeof(u8), VRING_DESC_F_WRITE |
+ VRING_HIDDEN_IS_CHAIN);
+
+ /* Now we can tell the host to read */
+ vring_wait_reply(&block, 0);
+
+ r = drain_irqs(block.schid);
+ if (r) {
+ /* Well, whatever status is supposed to contain... */
+ status = 1;
+ }
+ return status;
+}
+
+unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
+ ulong subchan_id, void *load_addr)
+{
+ u8 status;
+ int sec = rec_list1;
+ int sec_num = (((rec_list2 >> 32)+ 1) & 0xffff);
+ int sec_len = rec_list2 >> 48;
+ ulong addr = (ulong)load_addr;
+
+ if (sec_len != SECTOR_SIZE) {
+ return -1;
+ }
+
+ sclp_print(".");
+ status = virtio_read_many(sec, (void*)addr, sec_num);
+ if (status) {
+ virtio_panic("I/O Error");
+ }
+ addr += sec_num * SECTOR_SIZE;
+
+ return addr;
+}
+
+int virtio_read(ulong sector, void *load_addr)
+{
+ return virtio_read_many(sector, load_addr, 1);
+}
+
+void virtio_setup_block(struct subchannel_id schid)
+{
+ struct vq_info_block info;
+ struct vq_config_block config = {};
+
+ virtio_reset(schid);
+
+ config.index = 0;
+ if (run_ccw(schid, CCW_CMD_READ_VQ_CONF, &config, sizeof(config))) {
+ virtio_panic("Could not get block device configuration\n");
+ }
+ vring_init(&block, config.num, (void*)(100 * 1024 * 1024),
+ KVM_S390_VIRTIO_RING_ALIGN);
+
+ info.queue = (100ULL * 1024ULL* 1024ULL);
+ info.align = KVM_S390_VIRTIO_RING_ALIGN;
+ info.index = 0;
+ info.num = config.num;
+ block.schid = schid;
+
+ if (!run_ccw(schid, CCW_CMD_SET_VQ, &info, sizeof(info))) {
+ virtio_set_status(schid, VIRTIO_CONFIG_S_DRIVER_OK);
+ }
+}
+
+bool virtio_is_blk(struct subchannel_id schid)
+{
+ int r;
+ struct senseid senseid = {};
+
+ /* run sense id command */
+ r = run_ccw(schid, CCW_CMD_SENSE_ID, &senseid, sizeof(senseid));
+ if (r) {
+ return false;
+ }
+ if ((senseid.cu_type != 0x3832) || (senseid.cu_model != VIRTIO_ID_BLOCK)) {
+ return false;
+ }
+
+ return true;
+}
+
+int enable_mss_facility(void)
+{
+ int ret;
+ struct chsc_area_sda *sda_area = (struct chsc_area_sda *) chsc_page;
+
+ memset(sda_area, 0, PAGE_SIZE);
+ sda_area->request.length = 0x0400;
+ sda_area->request.code = 0x0031;
+ sda_area->operation_code = 0x2;
+
+ ret = chsc(sda_area);
+ if ((ret == 0) && (sda_area->response.code == 0x0001)) {
+ return 0;
+ }
+ return -EIO;
+}
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
new file mode 100644
index 000000000..86fdd579b
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio.h
@@ -0,0 +1,163 @@
+/*
+ * Virtio driver bits
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef VIRTIO_H
+#define VIRTIO_H
+
+#include "s390-ccw.h"
+
+/* Status byte for guest to report progress, and synchronize features. */
+/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
+/* We have found a driver for the device. */
+#define VIRTIO_CONFIG_S_DRIVER 2
+/* Driver has used its parts of the config, and is happy */
+#define VIRTIO_CONFIG_S_DRIVER_OK 4
+/* We've given up on this device. */
+#define VIRTIO_CONFIG_S_FAILED 0x80
+
+enum virtio_dev_type {
+ VIRTIO_ID_NET = 1,
+ VIRTIO_ID_BLOCK = 2,
+ VIRTIO_ID_CONSOLE = 3,
+ VIRTIO_ID_BALLOON = 5,
+};
+
+struct virtio_dev_header {
+ enum virtio_dev_type type : 8;
+ u8 num_vq;
+ u8 feature_len;
+ u8 config_len;
+ u8 status;
+ u8 vqconfig[];
+} __attribute__((packed));
+
+struct virtio_vqconfig {
+ u64 token;
+ u64 address;
+ u16 num;
+ u8 pad[6];
+} __attribute__((packed));
+
+struct vq_info_block {
+ u64 queue;
+ u32 align;
+ u16 index;
+ u16 num;
+} __attribute__((packed));
+
+struct vq_config_block {
+ u16 index;
+ u16 num;
+} __attribute__((packed));
+
+struct virtio_dev {
+ struct virtio_dev_header *header;
+ struct virtio_vqconfig *vqconfig;
+ char *host_features;
+ char *guest_features;
+ char *config;
+};
+
+#define KVM_S390_VIRTIO_RING_ALIGN 4096
+
+#define VRING_USED_F_NO_NOTIFY 1
+
+/* This marks a buffer as continuing via the next field. */
+#define VRING_DESC_F_NEXT 1
+/* This marks a buffer as write-only (otherwise read-only). */
+#define VRING_DESC_F_WRITE 2
+/* This means the buffer contains a list of buffer descriptors. */
+#define VRING_DESC_F_INDIRECT 4
+
+/* Internal flag to mark follow-up segments as such */
+#define VRING_HIDDEN_IS_CHAIN 256
+
+/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
+struct vring_desc {
+ /* Address (guest-physical). */
+ u64 addr;
+ /* Length. */
+ u32 len;
+ /* The flags as indicated above. */
+ u16 flags;
+ /* We chain unused descriptors via this, too */
+ u16 next;
+} __attribute__((packed));
+
+struct vring_avail {
+ u16 flags;
+ u16 idx;
+ u16 ring[];
+} __attribute__((packed));
+
+/* u32 is used here for ids for padding reasons. */
+struct vring_used_elem {
+ /* Index of start of used descriptor chain. */
+ u32 id;
+ /* Total length of the descriptor chain which was used (written to) */
+ u32 len;
+} __attribute__((packed));
+
+struct vring_used {
+ u16 flags;
+ u16 idx;
+ struct vring_used_elem ring[];
+} __attribute__((packed));
+
+struct vring {
+ unsigned int num;
+ int next_idx;
+ struct vring_desc *desc;
+ struct vring_avail *avail;
+ struct vring_used *used;
+ struct subchannel_id schid;
+};
+
+
+/***********************************************
+ * Virtio block *
+ ***********************************************/
+
+/*
+ * Command types
+ *
+ * Usage is a bit tricky as some bits are used as flags and some are not.
+ *
+ * Rules:
+ * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
+ * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own
+ * and may not be combined with any of the other flags.
+ */
+
+/* These two define direction. */
+#define VIRTIO_BLK_T_IN 0
+#define VIRTIO_BLK_T_OUT 1
+
+/* This bit says it's a scsi command, not an actual read or write. */
+#define VIRTIO_BLK_T_SCSI_CMD 2
+
+/* Cache flush command */
+#define VIRTIO_BLK_T_FLUSH 4
+
+/* Barrier before this op. */
+#define VIRTIO_BLK_T_BARRIER 0x80000000
+
+/* This is the first element of the read scatter-gather list. */
+struct virtio_blk_outhdr {
+ /* VIRTIO_BLK_T* */
+ u32 type;
+ /* io priority. */
+ u32 ioprio;
+ /* Sector (ie. 512 byte offset) */
+ u64 sector;
+};
+
+#endif /* VIRTIO_H */
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 84ba6b83f..092e58a46 100644
--- a/pc-bios/slof.bin
+++ b/pc-bios/slof.bin
Binary files differ