summaryrefslogtreecommitdiff
path: root/pc-bios
diff options
context:
space:
mode:
Diffstat (limited to 'pc-bios')
-rw-r--r--pc-bios/QEMU,tcx.binbin1410 -> 1402 bytes
-rw-r--r--pc-bios/bios-256k.binbin262144 -> 262144 bytes
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/linuxboot.binbin1024 -> 1024 bytes
-rw-r--r--pc-bios/openbios-ppcbin734012 -> 746588 bytes
-rw-r--r--pc-bios/openbios-sparc32bin381512 -> 381512 bytes
-rw-r--r--pc-bios/openbios-sparc64bin1616768 -> 1616768 bytes
-rw-r--r--pc-bios/optionrom/linuxboot.S47
-rw-r--r--pc-bios/optionrom/optionrom.h21
-rw-r--r--pc-bios/petalogix-s3adsp1800.dtbbin8259 -> 8259 bytes
-rw-r--r--pc-bios/s390-ccw.imgbin17752 -> 17752 bytes
-rw-r--r--pc-bios/s390-ccw/bootmap.c107
-rw-r--r--pc-bios/s390-ccw/bootmap.h2
-rw-r--r--pc-bios/s390-ccw/virtio.c48
-rw-r--r--pc-bios/s390-ccw/virtio.h2
-rw-r--r--pc-bios/vgabios-cirrus.binbin37376 -> 37376 bytes
-rw-r--r--pc-bios/vgabios-qxl.binbin37376 -> 37376 bytes
-rw-r--r--pc-bios/vgabios-stdvga.binbin37376 -> 37376 bytes
-rw-r--r--pc-bios/vgabios-vmware.binbin37376 -> 37376 bytes
-rw-r--r--pc-bios/vgabios.binbin37376 -> 37376 bytes
20 files changed, 164 insertions, 63 deletions
diff --git a/pc-bios/QEMU,tcx.bin b/pc-bios/QEMU,tcx.bin
index eed108f3f..d79cc1fea 100644
--- a/pc-bios/QEMU,tcx.bin
+++ b/pc-bios/QEMU,tcx.bin
Binary files differ
diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin
index 09686a381..fab9da2b3 100644
--- a/pc-bios/bios-256k.bin
+++ b/pc-bios/bios-256k.bin
Binary files differ
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 2314027c3..8c718e1b9 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/pc-bios/linuxboot.bin b/pc-bios/linuxboot.bin
index e7c36694f..130103fb7 100644
--- a/pc-bios/linuxboot.bin
+++ b/pc-bios/linuxboot.bin
Binary files differ
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 0f2fc3a0a..994052f14 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 8917b558e..6d5a381a7 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 cf72a59ee..61bd46bf4 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
diff --git a/pc-bios/optionrom/linuxboot.S b/pc-bios/optionrom/linuxboot.S
index 748c83116..5bc0af08e 100644
--- a/pc-bios/optionrom/linuxboot.S
+++ b/pc-bios/optionrom/linuxboot.S
@@ -76,14 +76,45 @@ boot_kernel:
copy_kernel:
+ /* Compute initrd address */
+ mov $0xe801, %ax
+ xor %cx, %cx
+ xor %dx, %dx
+ int $0x15
+
+ /* Output could be in AX/BX or CX/DX */
+ or %cx, %cx
+ jnz 1f
+ or %dx, %dx
+ jnz 1f
+ mov %ax, %cx
+ mov %bx, %dx
+1:
+
+ or %dx, %dx
+ jnz 2f
+ addw $1024, %cx /* add 1 MB */
+ movzwl %cx, %edi
+ shll $10, %edi /* convert to bytes */
+ jmp 3f
+
+2:
+ addw $16777216 >> 16, %dx /* add 16 MB */
+ movzwl %dx, %edi
+ shll $16, %edi /* convert to bytes */
+
+3:
+ read_fw FW_CFG_INITRD_SIZE
+ subl %eax, %edi
+ andl $-4096, %edi /* EDI = start of initrd */
/* We need to load the kernel into memory we can't access in 16 bit
mode, so let's get into 32 bit mode, write the kernel and jump
back again. */
/* Reserve space on the stack for our GDT descriptor. */
- mov %esp, %ebp
- sub $16, %esp
+ mov %esp, %ebp
+ sub $16, %esp
/* Now create the GDT descriptor */
movw $((3 * 8) - 1), -16(%bp)
@@ -108,10 +139,18 @@ copy_kernel:
/* We're now running in 16-bit CS, but 32-bit ES! */
/* Load kernel and initrd */
+ pushl %edi
+ read_fw_blob_addr32_edi(FW_CFG_INITRD)
read_fw_blob_addr32(FW_CFG_KERNEL)
- read_fw_blob_addr32(FW_CFG_INITRD)
read_fw_blob_addr32(FW_CFG_CMDLINE)
- read_fw_blob_addr32(FW_CFG_SETUP)
+
+ read_fw FW_CFG_SETUP_ADDR
+ mov %eax, %edi
+ mov %eax, %ebx
+ read_fw_blob_addr32_edi(FW_CFG_SETUP)
+
+ /* Update the header with the initrd address we chose above */
+ popl %es:0x218(%ebx)
/* And now jump into Linux! */
mov $0, %eax
diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
index ce436085d..f1a9021ec 100644
--- a/pc-bios/optionrom/optionrom.h
+++ b/pc-bios/optionrom/optionrom.h
@@ -51,8 +51,6 @@
.endm
#define read_fw_blob_pre(var) \
- read_fw var ## _ADDR; \
- mov %eax, %edi; \
read_fw var ## _SIZE; \
mov %eax, %ecx; \
mov $var ## _DATA, %ax; \
@@ -68,6 +66,8 @@
* Clobbers: %eax, %edx, %es, %ecx, %edi
*/
#define read_fw_blob(var) \
+ read_fw var ## _ADDR; \
+ mov %eax, %edi; \
read_fw_blob_pre(var); \
/* old as(1) doesn't like this insn so emit the bytes instead: \
rep insb (%dx), %es:(%edi); \
@@ -80,7 +80,22 @@
*
* Clobbers: %eax, %edx, %es, %ecx, %edi
*/
-#define read_fw_blob_addr32(var) \
+#define read_fw_blob_addr32(var) \
+ read_fw var ## _ADDR; \
+ mov %eax, %edi; \
+ read_fw_blob_pre(var); \
+ /* old as(1) doesn't like this insn so emit the bytes instead: \
+ addr32 rep insb (%dx), %es:(%edi); \
+ */ \
+ .dc.b 0x67,0xf3,0x6c
+
+/*
+ * Read a blob from the fw_cfg device in forced addr32 mode, address is in %edi.
+ * Requires _SIZE and _DATA values for the parameter.
+ *
+ * Clobbers: %eax, %edx, %edi, %es, %ecx
+ */
+#define read_fw_blob_addr32_edi(var) \
read_fw_blob_pre(var); \
/* old as(1) doesn't like this insn so emit the bytes instead: \
addr32 rep insb (%dx), %es:(%edi); \
diff --git a/pc-bios/petalogix-s3adsp1800.dtb b/pc-bios/petalogix-s3adsp1800.dtb
index 93c5973fd..8ac80f2f2 100644
--- a/pc-bios/petalogix-s3adsp1800.dtb
+++ b/pc-bios/petalogix-s3adsp1800.dtb
Binary files differ
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index e3ea0d566..44873ad18 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differ
diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index f1756796d..115d8bbac 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -40,11 +40,6 @@ static void jump_to_IPL_2(void)
ResetInfo *current = 0;
void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
- debug_print_addr("set IPL addr to", ipl);
-
- /* Ensure the guest output starts fresh */
- sclp_print("\n");
-
*current = save;
ipl(); /* should not return */
}
@@ -64,6 +59,11 @@ static void jump_to_IPL_code(uint64_t address)
current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
current->ipl_continue = address & 0x7fffffff;
+ debug_print_int("set IPL addr to", current->ipl_continue);
+
+ /* Ensure the guest output starts fresh */
+ sclp_print("\n");
+
/*
* HACK ALERT.
* We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
@@ -93,11 +93,23 @@ static inline void verify_boot_info(BootInfo *bip)
"Bad block size in zIPL section of the 1st record.");
}
-static bool eckd_valid_address(BootMapPointer *p)
+static block_number_t eckd_block_num(BootMapPointer *p)
{
+ const uint64_t sectors = virtio_get_sectors();
+ const uint64_t heads = virtio_get_heads();
const uint64_t cylinder = p->eckd.cylinder
+ ((p->eckd.head & 0xfff0) << 12);
const uint64_t head = p->eckd.head & 0x000f;
+ const block_number_t block = sectors * heads * cylinder
+ + sectors * head
+ + p->eckd.sector
+ - 1; /* block nr starts with zero */
+ return block;
+}
+
+static bool eckd_valid_address(BootMapPointer *p)
+{
+ const uint64_t head = p->eckd.head & 0x000f;
if (head >= virtio_get_heads()
|| p->eckd.sector > virtio_get_sectors()
@@ -105,27 +117,14 @@ static bool eckd_valid_address(BootMapPointer *p)
return false;
}
- if (!virtio_guessed_disk_nature() && cylinder >= virtio_get_cylinders()) {
+ if (!virtio_guessed_disk_nature() &&
+ eckd_block_num(p) >= virtio_get_blocks()) {
return false;
}
return true;
}
-static block_number_t eckd_block_num(BootMapPointer *p)
-{
- const uint64_t sectors = virtio_get_sectors();
- const uint64_t heads = virtio_get_heads();
- const uint64_t cylinder = p->eckd.cylinder
- + ((p->eckd.head & 0xfff0) << 12);
- const uint64_t head = p->eckd.head & 0x000f;
- const block_number_t block = sectors * heads * cylinder
- + sectors * head
- + p->eckd.sector
- - 1; /* block nr starts with zero */
- return block;
-}
-
static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address)
{
block_number_t block_nr;
@@ -223,7 +222,6 @@ static void ipl_eckd_cdl(void)
memset(sec, FREE_SPACE_FILLER, sizeof(sec));
read_block(1, ipl2, "Cannot read IPL2 record at block 1");
- IPL_assert(magic_match(ipl2, IPL2_MAGIC), "No IPL2 record");
mbr = &ipl2->u.x.mbr;
IPL_assert(magic_match(mbr, ZIPL_MAGIC), "No zIPL section in IPL2 record.");
@@ -247,12 +245,10 @@ static void ipl_eckd_cdl(void)
/* no return */
}
-static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
+static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode)
{
LDL_VTOC *vlbl = (void *)sec; /* already read, 3rd block */
char msg[4] = { '?', '.', '\n', '\0' };
- block_number_t block_nr;
- BootInfo *bip;
sclp_print((mode == ECKD_CMS) ? "CMS" : "LDL");
sclp_print(" version ");
@@ -272,12 +268,27 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
}
sclp_print(msg);
print_volser(vlbl->volser);
+}
+
+static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
+{
+ block_number_t block_nr;
+ BootInfo *bip = (void *)(sec + 0x70); /* BootInfo is MBR for LDL */
+
+ if (mode != ECKD_LDL_UNLABELED) {
+ print_eckd_ldl_msg(mode);
+ }
/* DO NOT read BootMap pointer (only one, xECKD) at block #2 */
memset(sec, FREE_SPACE_FILLER, sizeof(sec));
- read_block(0, sec, "Cannot read block 0");
- bip = (void *)(sec + 0x70); /* "boot info" is "eckd mbr" for LDL */
+ read_block(0, sec, "Cannot read block 0 to grab boot info.");
+ if (mode == ECKD_LDL_UNLABELED) {
+ if (!magic_match(bip->magic, ZIPL_MAGIC)) {
+ return; /* not applicable layout */
+ }
+ sclp_print("unlabeled LDL.\n");
+ }
verify_boot_info(bip);
block_nr = eckd_block_num((void *)&(bip->bp.ipl.bm_ptr.eckd.bptr));
@@ -285,17 +296,23 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
/* no return */
}
-static void ipl_eckd(ECKD_IPL_mode_t mode)
+static void print_eckd_msg(void)
{
- switch (mode) {
- case ECKD_CDL:
- ipl_eckd_cdl(); /* no return */
- case ECKD_CMS:
- case ECKD_LDL:
- ipl_eckd_ldl(mode); /* no return */
- default:
- virtio_panic("\n! Unknown ECKD IPL mode !\n");
+ char msg[] = "Using ECKD scheme (block size *****), ";
+ char *p = &msg[34], *q = &msg[30];
+ int n = virtio_get_block_size();
+
+ /* Fill in the block size and show up the message */
+ if (n > 0 && n <= 99999) {
+ while (n) {
+ *p-- = '0' + (n % 10);
+ n /= 10;
+ }
+ while (p >= q) {
+ *p-- = ' ';
+ }
}
+ sclp_print(msg);
}
/***********************************************************************
@@ -447,14 +464,13 @@ void zipl_load(void)
}
/* We have failed to follow the SCSI scheme, so */
- sclp_print("Using ECKD scheme.\n");
if (virtio_guessed_disk_nature()) {
sclp_print("Using guessed DASD geometry.\n");
virtio_assume_eckd();
}
-
+ print_eckd_msg();
if (magic_match(mbr->magic, IPL1_MAGIC)) {
- ipl_eckd(ECKD_CDL); /* no return */
+ ipl_eckd_cdl(); /* no return */
}
/* LDL/CMS? */
@@ -462,11 +478,18 @@ void zipl_load(void)
read_block(2, vlbl, "Cannot read block 2");
if (magic_match(vlbl->magic, CMS1_MAGIC)) {
- ipl_eckd(ECKD_CMS); /* no return */
+ ipl_eckd_ldl(ECKD_CMS); /* no return */
}
if (magic_match(vlbl->magic, LNX1_MAGIC)) {
- ipl_eckd(ECKD_LDL); /* no return */
+ ipl_eckd_ldl(ECKD_LDL); /* no return */
}
- virtio_panic("\n* invalid MBR magic *\n");
+ ipl_eckd_ldl(ECKD_LDL_UNLABELED); /* it still may return */
+ /*
+ * Ok, it is not a LDL by any means.
+ * It still might be a CDL with zero record keys for IPL1 and IPL2
+ */
+ ipl_eckd_cdl();
+
+ virtio_panic("\n* this can never happen *\n");
}
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index 30ef22fe6..6a4823d54 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -257,9 +257,9 @@ typedef struct IplVolumeLabel {
typedef enum {
ECKD_NO_IPL,
- ECKD_CDL,
ECKD_CMS,
ECKD_LDL,
+ ECKD_LDL_UNLABELED,
} ECKD_IPL_mode_t;
/* utility code below */
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 31b23b086..c0540d1cd 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -275,12 +275,14 @@ void virtio_assume_scsi(void)
{
guessed_disk_nature = true;
blk_cfg.blk_size = 512;
+ blk_cfg.physical_block_exp = 0;
}
void virtio_assume_eckd(void)
{
guessed_disk_nature = true;
blk_cfg.blk_size = 4096;
+ blk_cfg.physical_block_exp = 0;
/* this must be here to calculate code segment position */
blk_cfg.geometry.heads = 15;
@@ -290,36 +292,52 @@ void virtio_assume_eckd(void)
bool virtio_disk_is_scsi(void)
{
if (guessed_disk_nature) {
- return (blk_cfg.blk_size == 512);
+ return (virtio_get_block_size() == 512);
}
return (blk_cfg.geometry.heads == 255)
&& (blk_cfg.geometry.sectors == 63)
- && (blk_cfg.blk_size == 512);
+ && (virtio_get_block_size() == 512);
+}
+
+/*
+ * Other supported value pairs, if any, would need to be added here.
+ * Note: head count is always 15.
+ */
+static inline u8 virtio_eckd_sectors_for_block_size(int size)
+{
+ switch (size) {
+ case 512:
+ return 49;
+ case 1024:
+ return 33;
+ case 2048:
+ return 21;
+ case 4096:
+ return 12;
+ }
+ return 0;
}
bool virtio_disk_is_eckd(void)
{
+ const int block_size = virtio_get_block_size();
+
if (guessed_disk_nature) {
- return (blk_cfg.blk_size == 4096);
+ return (block_size == 4096);
}
return (blk_cfg.geometry.heads == 15)
- && (blk_cfg.geometry.sectors == 12)
- && (blk_cfg.blk_size == 4096);
+ && (blk_cfg.geometry.sectors ==
+ virtio_eckd_sectors_for_block_size(block_size));
}
bool virtio_ipl_disk_is_valid(void)
{
- return blk_cfg.blk_size && (virtio_disk_is_scsi() || virtio_disk_is_eckd());
+ return virtio_disk_is_scsi() || virtio_disk_is_eckd();
}
int virtio_get_block_size(void)
{
- return blk_cfg.blk_size;
-}
-
-uint16_t virtio_get_cylinders(void)
-{
- return blk_cfg.geometry.cylinders;
+ return blk_cfg.blk_size << blk_cfg.physical_block_exp;
}
uint8_t virtio_get_heads(void)
@@ -332,6 +350,12 @@ uint8_t virtio_get_sectors(void)
return blk_cfg.geometry.sectors;
}
+uint64_t virtio_get_blocks(void)
+{
+ return blk_cfg.capacity /
+ (virtio_get_block_size() / VIRTIO_SECTOR_SIZE);
+}
+
void virtio_setup_block(struct subchannel_id schid)
{
struct vq_info_block info;
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index f1fb1b08f..c23466b8d 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -192,9 +192,9 @@ extern bool virtio_disk_is_scsi(void);
extern bool virtio_disk_is_eckd(void);
extern bool virtio_ipl_disk_is_valid(void);
extern int virtio_get_block_size(void);
-extern uint16_t virtio_get_cylinders(void);
extern uint8_t virtio_get_heads(void);
extern uint8_t virtio_get_sectors(void);
+extern uint64_t virtio_get_blocks(void);
extern int virtio_read_many(ulong sector, void *load_addr, int sec_num);
#define VIRTIO_SECTOR_SIZE 512
diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin
index 57a5f954a..0c4d25346 100644
--- a/pc-bios/vgabios-cirrus.bin
+++ b/pc-bios/vgabios-cirrus.bin
Binary files differ
diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin
index ed79993ad..4e08e1362 100644
--- a/pc-bios/vgabios-qxl.bin
+++ b/pc-bios/vgabios-qxl.bin
Binary files differ
diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin
index d3579b4fb..e5e5b14e4 100644
--- a/pc-bios/vgabios-stdvga.bin
+++ b/pc-bios/vgabios-stdvga.bin
Binary files differ
diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin
index f89845e75..cf2576d34 100644
--- a/pc-bios/vgabios-vmware.bin
+++ b/pc-bios/vgabios-vmware.bin
Binary files differ
diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin
index d3038f418..bad187dc2 100644
--- a/pc-bios/vgabios.bin
+++ b/pc-bios/vgabios.bin
Binary files differ