diff -Nru seabios-1.14.0/debian/changelog seabios-1.15.0/debian/changelog --- seabios-1.14.0/debian/changelog 2020-12-08 11:52:59.000000000 +0000 +++ seabios-1.15.0/debian/changelog 2021-12-05 09:58:22.000000000 +0000 @@ -1,3 +1,18 @@ +seabios (1.15.0-1) unstable; urgency=medium + + * New upstream release: + * Improved support for USB devices with multiple interfaces. + * Support for USB XHCI devices using direct MMIO access (instead of PCI). + * NVMe improvements. + * Increased "f-segment" RAM allocations for BIOS tables. + * Several bug fixes and code cleanups. + * Update Standards-Version to 4.6.0 (no changes) + * Stop breaking pre-historic (0.14) qemu + * Stop building qemu optionrom which is built on qemy itself + since qemu 3.1 (buster) + + -- Michael Tokarev Sun, 05 Dec 2021 12:58:22 +0300 + seabios (1.14.0-2) unstable; urgency=medium * install vgabios-ramfb.bin, not romfb diff -Nru seabios-1.14.0/debian/control seabios-1.15.0/debian/control --- seabios-1.14.0/debian/control 2020-12-08 11:52:53.000000000 +0000 +++ seabios-1.15.0/debian/control 2021-12-05 09:58:22.000000000 +0000 @@ -5,7 +5,7 @@ Uploaders: Riku Voipio , Michael Tokarev Build-Depends: debhelper-compat (= 12), python3, acpica-tools | iasl -Standards-Version: 4.5.1 +Standards-Version: 4.6.0 Rules-Requires-Root: no Vcs-Browser: https://salsa.debian.org/qemu-team/seabios Vcs-Git: https://salsa.debian.org/qemu-team/seabios.git @@ -15,7 +15,6 @@ Architecture: all Multi-Arch: foreign Depends: ${misc:Depends} -Breaks: qemu-system (<< 0.14.0), qemu-kvm (<< 0.14.0) Description: Legacy BIOS implementation SeaBIOS is a legacy BIOS implementation, aimed at supporting not only emulated hosts such as QEMU, but also real hardware. diff -Nru seabios-1.14.0/debian/install seabios-1.15.0/debian/install --- seabios-1.14.0/debian/install 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/install 2021-12-05 09:58:22.000000000 +0000 @@ -1,3 +1,2 @@ build/*.bin usr/share/seabios build/src/fw/*dsdt.aml usr/share/seabios -debian/optionrom/*.bin usr/share/seabios diff -Nru seabios-1.14.0/debian/optionrom/extboot.S seabios-1.15.0/debian/optionrom/extboot.S --- seabios-1.14.0/debian/optionrom/extboot.S 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/extboot.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,691 +0,0 @@ -/* - * Extended Boot Option ROM - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Copyright IBM Corporation, 2007 - * Authors: Anthony Liguori - */ - -#define OLD_INT19 (0x80 * 4) /* re-use INT 0x80 BASIC vector */ -#define OLD_INT13 (0x81 * 4) /* re-use INT 0x81 BASIC vector */ - -.code16 -.text - .global _start -_start: - .short 0xaa55 - .byte (_end - _start) / 512 - push %eax - push %ds - - /* setup ds so we can access the IVT */ - xor %ax, %ax - mov %ax, %ds - - /* there is one more bootable HD */ - incb 0x0475 - - /* save old int 19 */ - mov (0x19*4), %eax - mov %eax, (OLD_INT19) - - /* install out int 19 handler */ - movw $int19_handler, (0x19*4) - mov %cs, (0x19*4+2) - - pop %ds - pop %eax - lret - -int19_handler: - push %eax /* reserve space for lret */ - push %eax - push %bx - push %cx - push %dx - push %ds - - /* setup ds to access IVT */ - xor %ax, %ax - mov %ax, %ds - - /* save old int 13 to int 2c */ - mov (0x13*4), %eax - mov %eax, (OLD_INT13) - - /* install our int 13 handler */ - movw $int13_handler, (0x13*4) - mov %cs, (0x13*4+2) - - /* restore previous int $0x19 handler */ - mov (OLD_INT19),%eax - mov %eax,(0x19*4) - - /* write old handler as return address onto stack */ - push %bp - mov %sp, %bp - mov %eax, 14(%bp) - pop %bp - - pop %ds - pop %dx - pop %cx - pop %bx - pop %eax - lret - -#define FLAGS_CF 0x01 - -/* The two macro below clear/set the carry flag to indicate the status - * of the interrupt execution. It is not enough to issue a clc/stc instruction, - * since the value of the flags register will be overwritten by whatever is - * in the stack frame - */ -.macro clc_stack - push %bp - mov %sp, %bp - /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */ - and $(~FLAGS_CF), 8(%bp) - pop %bp -.endm - -.macro stc_stack - push %bp - /* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */ - or $(FLAGS_CF), 8(%bp) - pop %bp -.endm - -/* we clobber %bx */ -.macro alloca size - push %ds - push %bp - mov %sp, %bp /* remember the current stack position */ - - mov %ss, %bx - mov %bx, %ds - - sub \size, %sp - and $(~0x0F), %sp - mov %sp, %bx - - push %bp - mov 0(%bp), %bp -.endm - -/* we clobber %bp */ -.macro allocbpa size - mov %sp, %bp /* remember the current stack position */ - sub \size, %sp - and $(~0x0F), %sp - push %bp - mov %sp, %bp - add $2, %bp -.endm - -.macro freea - pop %sp - add $2, %sp - pop %ds -.endm - -.macro freebpa - pop %sp -.endm - -.macro dump reg - push %ax - push %dx - - mov \reg, %ax - mov $0x406, %dx - outw %ax, %dx - - pop %dx - pop %ax -.endm - -.macro callout value - push %bp - push %bx - mov %sp, %bp - alloca $16 - push %ax - push %dx - - mov %ax, 0(%bx) /* ax */ - mov 0(%bp), %ax /* bx */ - mov %ax, 2(%bx) - mov %cx, 4(%bx) /* cx */ - mov %dx, 6(%bx) /* dx */ - mov %si, 8(%bx) /* si */ - mov %ds, 10(%bx) /* ds */ - mov %es, 12(%bx) /* ds */ - movw \value, 14(%bx) /* value */ - - mov %bx, %ax - shr $4, %ax - mov %ds, %dx - add %dx, %ax - - mov $0x407, %dx - outw %ax, %dx - - pop %dx - pop %ax - freea - pop %bx - pop %bp -.endm - -send_command: - push %bp - mov %sp, %bp - push %ax - push %bx - push %dx - - mov 4(%bp), %ax - shr $4, %ax - and $0x0FFF, %ax - mov %ss, %bx - add %bx, %ax - - mov $0x405, %dx - outw %ax, %dx - - pop %dx - pop %bx - pop %ax - pop %bp - - push %ax - mov 2(%bx), %ax - pop %ax - - ret - -add32: /* lo, hi, lo, hi */ - push %bp - mov %sp, %bp - - movw 4(%bp), %cx /* hi */ - movw 6(%bp), %dx /* lo */ - - add 10(%bp), %dx - jnc 1f - add $1, %cx -1: add 8(%bp), %cx - - pop %bp - ret - -mul32: /* lo, hi, lo, hi */ - /* 10(%bp), 8(%bp), 6(%bp), 4(%bp) */ - push %bp - mov %sp, %bp - push %ax - push %bx - - xor %cx, %cx - xor %dx, %dx - - /* for (i = 0; i < 16;) */ - xor %bx, %bx -0: - cmp $16, %bx - jge 2f - - mov 6(%bp), %ax - and $1, %ax - cmp $1, %ax - jne 1f - push 10(%bp) - push 8(%bp) - push %dx - push %cx - call add32 - add $8, %sp -1: - shlw $1, 8(%bp) - movw 10(%bp), %ax - and $0x8000, %ax - cmp $0x8000, %ax - jne 1f - orw $1, 8(%bp) -1: - shlw $1, 10(%bp) - shrw $1, 6(%bp) - - /* i++) { */ - add $1, %bx - jmp 0b - -2: - pop %bx - pop %ax - pop %bp - ret - -disk_reset: - movb $0, %ah - clc_stack - ret - -/* this really should be a function, not a macro but i'm lazy */ -.macro read_write_disk_sectors cmd - push %ax - push %bx - push %cx - push %dx - push %si - - push %bp - sub $10, %sp - mov %sp, %bp - - /* save nb_sectors */ - mov %al, 6(%bp) - movb $0, 7(%bp) - - /* save buffer */ - mov %bx, 8(%bp) - - /* cylinders */ - xor %ax, %ax - mov %cl, %al - shl $2, %ax - and $0x300, %ax - mov %ch, %al - mov %ax, 0(%bp) - - /* heads */ - xor %ax, %ax - mov %dh, %al - mov %ax, 2(%bp) - - /* sectors - 1 */ - xor %ax, %ax - mov %cl, %al - and $0x3F, %al - sub $1, %ax - mov %ax, 4(%bp) - - alloca $16 - - movw $0, 0(%bx) /* read c,h,s */ - push %bx - call send_command - add $2, %sp - - mov 6(%bx), %ax /* total_sectors */ - mov 2(%bp), %si /* *= heads */ - mul %si - add 4(%bp), %ax /* += sectors - 1 */ - - push 4(%bx) /* total_heads */ - push $0 - push 6(%bx) /* total_sectors */ - push $0 - call mul32 - add $8, %sp - - push 0(%bp) /* cylinders */ - push $0 - push %dx - push %cx - call mul32 - add $8, %sp - - add %ax, %dx - jnc 1f - add $1, %cx -1: - freea - - alloca $16 - - movw \cmd, 0(%bx) /* read */ - movw 6(%bp), %ax /* nb_sectors */ - movw %ax, 2(%bx) - movw %es, 4(%bx) /* segment */ - movw 8(%bp), %ax /* offset */ - mov %ax, 6(%bx) - movw %dx, 8(%bx) /* sector */ - movw %cx, 10(%bx) - movw $0, 12(%bx) - movw $0, 14(%bx) - - push %bx - call send_command - add $2, %sp - - freea - - add $10, %sp - pop %bp - - pop %si - pop %dx - pop %cx - pop %bx - pop %ax - - mov $0, %ah - clc_stack - ret -.endm - -read_disk_sectors: - read_write_disk_sectors $0x01 - -write_disk_sectors: - read_write_disk_sectors $0x02 - -read_disk_drive_parameters: - push %bx - - /* allocate memory for packet, pointer gets returned in bx */ - alloca $16 - - /* issue command */ - movw $0, 0(%bx) /* cmd = 0, read c,h,s */ - push %bx - call send_command - add $2, %sp - - /* normalize sector value */ - movb 6(%bx), %cl - andb $0x3F, %cl - movb %cl, 6(%bx) - - /* normalize cylinders */ - subw $2, 2(%bx) - - /* normalize heads */ - subw $1, 4(%bx) - - /* return code */ - mov $0, %ah - - /* cylinders */ - movb 2(%bx), %ch - movb 3(%bx), %cl - shlb $6, %cl - andb $0xC0, %cl - - /* sectors */ - orb 6(%bx), %cl - - /* heads */ - movb 4(%bx), %dh - - /* drives */ - movb $1, %dl - - /* status */ - mov $0, %ah - - freea - - pop %bx - - /* do this last since it's the most sensitive */ - clc_stack - ret - -alternate_disk_reset: - movb $0, %ah - clc_stack - ret - -read_disk_drive_size: - push %bx - alloca $16 - - movw $0, 0(%bx) /* cmd = 0, read c,h,s */ - push %bx - call send_command - add $2, %sp - - /* cylinders - 1 to cx:dx */ - mov 2(%bx), %dx - xor %cx, %cx - sub $1, %dx - - /* heads */ - push 4(%bx) - push $0 - push %dx - push %cx - call mul32 - add $8, %sp - - /* sectors */ - push 6(%bx) - push $0 - push %dx - push %cx - call mul32 - add $8, %sp - - /* status */ - mov $3, %ah - - freea - pop %bx - - clc_stack - ret - -check_if_extensions_present: - mov $0x30, %ah - mov $0xAA55, %bx - mov $0x07, %cx - clc_stack - ret - -.macro extended_read_write_sectors cmd - cmpb $10, 0(%si) - jg 1f - mov $1, %ah - stc_stack - ret -1: - push %ax - push %bp - allocbpa $16 - - movw \cmd, 0(%bp) /* read */ - movw 2(%si), %ax /* nb_sectors */ - movw %ax, 2(%bp) - movw 4(%si), %ax /* offset */ - movw %ax, 6(%bp) - movw 6(%si), %ax /* segment */ - movw %ax, 4(%bp) - movw 8(%si), %ax /* block */ - movw %ax, 8(%bp) - movw 10(%si), %ax - movw %ax, 10(%bp) - movw 12(%si), %ax - movw %ax, 12(%bp) - movw 14(%si), %ax - movw %ax, 14(%bp) - - push %bp - call send_command - add $2, %sp - - freebpa - pop %bp - pop %ax - - mov $0, %ah - clc_stack - ret -.endm - -extended_read_sectors: - extended_read_write_sectors $0x01 - -extended_write_sectors: - extended_read_write_sectors $0x02 - -get_extended_drive_parameters: - push %ax - push %bp - push %cx - push %dx - - allocbpa $16 - - movw $0, 0(%bp) /* read c,h,s */ - push %bp - call send_command - add $2, %sp - - /* write size */ - movw $26, 0(%si) - - /* set flags to 2 */ - movw $2, 2(%si) - - /* cylinders */ - mov 2(%bp), %ax - mov %ax, 4(%si) - xor %ax, %ax - mov %ax, 6(%si) - - /* heads */ - mov 4(%bp), %ax - mov %ax, 8(%si) - xor %ax, %ax - mov %ax, 10(%si) - - /* sectors */ - mov 6(%bp), %ax - mov %ax, 12(%si) - xor %ax, %ax - mov %ax, 14(%si) - - /* set total number of sectors */ - mov 8(%bp), %ax - mov %ax, 16(%si) - mov 10(%bp), %ax - mov %ax, 18(%si) - mov 12(%bp), %ax - mov %ax, 20(%si) - mov 14(%bp), %ax - mov %ax, 22(%si) - - /* number of bytes per sector */ - movw $512, 24(%si) - - freebpa - - pop %dx - pop %cx - pop %bp - pop %ax - - mov $0, %ah - clc_stack - ret - -terminate_disk_emulation: - mov $1, %ah - stc_stack - ret - -int13_handler: - cmp $0x80, %dl - je 1f - - /* write old handler as return address onto stack */ - push %eax - push %eax - push %ds - push %bp - mov %sp, %bp - xor %ax, %ax - mov %ax, %ds - mov (OLD_INT13), %eax - mov %eax, 8(%bp) - pop %bp - pop %ds - pop %eax - lret -1: - cmp $0x0, %ah - jne 1f - call disk_reset - iret -1: - cmp $0x2, %ah - jne 1f - call read_disk_sectors - iret -1: - cmp $0x8, %ah - jne 1f - call read_disk_drive_parameters - iret -1: - cmp $0x15, %ah - jne 1f - call read_disk_drive_size - iret -1: - cmp $0x41, %ah - jne 1f - call check_if_extensions_present - iret -1: - cmp $0x42, %ah - jne 1f - call extended_read_sectors - iret -1: - cmp $0x48, %ah - jne 1f - call get_extended_drive_parameters - iret -1: - cmp $0x4b, %ah - jne 1f - call terminate_disk_emulation - iret -1: - cmp $0x0d, %ah - jne 1f - call alternate_disk_reset - iret -1: - cmp $0x03, %ah - jne 1f - call write_disk_sectors - iret -1: - cmp $0x43, %ah - jne 1f - call extended_write_sectors - iret -1: - int $0x18 /* boot failed */ - iret - -.align 512, 0 -_end: diff -Nru seabios-1.14.0/debian/optionrom/fw_cfg_keys.h seabios-1.15.0/debian/optionrom/fw_cfg_keys.h --- seabios-1.14.0/debian/optionrom/fw_cfg_keys.h 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/fw_cfg_keys.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -#ifndef FW_CFG_KEYS_H -#define FW_CFG_KEYS_H - -#define FW_CFG_SIGNATURE 0x00 -#define FW_CFG_ID 0x01 -#define FW_CFG_UUID 0x02 -#define FW_CFG_RAM_SIZE 0x03 -#define FW_CFG_NOGRAPHIC 0x04 -#define FW_CFG_NB_CPUS 0x05 -#define FW_CFG_MACHINE_ID 0x06 -#define FW_CFG_KERNEL_ADDR 0x07 -#define FW_CFG_KERNEL_SIZE 0x08 -#define FW_CFG_KERNEL_CMDLINE 0x09 -#define FW_CFG_INITRD_ADDR 0x0a -#define FW_CFG_INITRD_SIZE 0x0b -#define FW_CFG_BOOT_DEVICE 0x0c -#define FW_CFG_NUMA 0x0d -#define FW_CFG_BOOT_MENU 0x0e -#define FW_CFG_MAX_CPUS 0x0f -#define FW_CFG_KERNEL_ENTRY 0x10 -#define FW_CFG_KERNEL_DATA 0x11 -#define FW_CFG_INITRD_DATA 0x12 -#define FW_CFG_CMDLINE_ADDR 0x13 -#define FW_CFG_CMDLINE_SIZE 0x14 -#define FW_CFG_CMDLINE_DATA 0x15 -#define FW_CFG_SETUP_ADDR 0x16 -#define FW_CFG_SETUP_SIZE 0x17 -#define FW_CFG_SETUP_DATA 0x18 -#define FW_CFG_FILE_DIR 0x19 - -#define FW_CFG_FILE_FIRST 0x20 -#define FW_CFG_FILE_SLOTS 0x10 -#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST + FW_CFG_FILE_SLOTS) - -#define FW_CFG_WRITE_CHANNEL 0x4000 -#define FW_CFG_ARCH_LOCAL 0x8000 -#define FW_CFG_ENTRY_MASK (~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)) - -#define FW_CFG_INVALID 0xffff - -/* width in bytes of fw_cfg control register */ -#define FW_CFG_CTL_SIZE 0x02 - -#define FW_CFG_MAX_FILE_PATH 56 - -#endif diff -Nru seabios-1.14.0/debian/optionrom/kvmvapic.S seabios-1.15.0/debian/optionrom/kvmvapic.S --- seabios-1.14.0/debian/optionrom/kvmvapic.S 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/kvmvapic.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,335 +0,0 @@ -# -# Local APIC acceleration for Windows XP and related guests -# -# Copyright 2011 Red Hat, Inc. and/or its affiliates -# -# Author: Avi Kivity -# -# 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 "optionrom.h" - -OPTION_ROM_START - - # clear vapic area: firmware load using rep insb may cause - # stale tpr/isr/irr data to corrupt the vapic area. - push %es - push %cs - pop %es - xor %ax, %ax - mov $vapic_size/2, %cx - lea vapic, %di - cld - rep stosw - pop %es - - # announce presence to the hypervisor - mov $vapic_base, %ax - out %ax, $0x7e - - lret - - .code32 -vapic_size = 2*4096 - -.macro fixup delta=-4 -777: - .text 1 - .long 777b + \delta - vapic_base - .text 0 -.endm - -.macro reenable_vtpr - out %al, $0x7e -.endm - -.text 1 - fixup_start = . -.text 0 - -.align 16 - -vapic_base: - .ascii "kvm aPiC" - - /* relocation data */ - .long vapic_base ; fixup - .long fixup_start ; fixup - .long fixup_end ; fixup - - .long vapic ; fixup - .long vapic_size -vcpu_shift: - .long 0 -real_tpr: - .long 0 - .long up_set_tpr ; fixup - .long up_set_tpr_eax ; fixup - .long up_get_tpr_eax ; fixup - .long up_get_tpr_ecx ; fixup - .long up_get_tpr_edx ; fixup - .long up_get_tpr_ebx ; fixup - .long 0 /* esp. won't work. */ - .long up_get_tpr_ebp ; fixup - .long up_get_tpr_esi ; fixup - .long up_get_tpr_edi ; fixup - .long up_get_tpr_stack ; fixup - .long mp_set_tpr ; fixup - .long mp_set_tpr_eax ; fixup - .long mp_get_tpr_eax ; fixup - .long mp_get_tpr_ecx ; fixup - .long mp_get_tpr_edx ; fixup - .long mp_get_tpr_ebx ; fixup - .long 0 /* esp. won't work. */ - .long mp_get_tpr_ebp ; fixup - .long mp_get_tpr_esi ; fixup - .long mp_get_tpr_edi ; fixup - .long mp_get_tpr_stack ; fixup - -.macro kvm_hypercall - .byte 0x0f, 0x01, 0xc1 -.endm - -kvm_hypercall_vapic_poll_irq = 1 - -pcr_cpu = 0x51 - -.align 64 - -mp_get_tpr_eax: - pushf - cli - reenable_vtpr - push %ecx - - fs/movzbl pcr_cpu, %eax - - mov vcpu_shift, %ecx ; fixup - shl %cl, %eax - testb $1, vapic+4(%eax) ; fixup delta=-5 - jz mp_get_tpr_bad - movzbl vapic(%eax), %eax ; fixup - -mp_get_tpr_out: - pop %ecx - popf - ret - -mp_get_tpr_bad: - mov real_tpr, %eax ; fixup - mov (%eax), %eax - jmp mp_get_tpr_out - -mp_get_tpr_ebx: - mov %eax, %ebx - call mp_get_tpr_eax - xchg %eax, %ebx - ret - -mp_get_tpr_ecx: - mov %eax, %ecx - call mp_get_tpr_eax - xchg %eax, %ecx - ret - -mp_get_tpr_edx: - mov %eax, %edx - call mp_get_tpr_eax - xchg %eax, %edx - ret - -mp_get_tpr_esi: - mov %eax, %esi - call mp_get_tpr_eax - xchg %eax, %esi - ret - -mp_get_tpr_edi: - mov %eax, %edi - call mp_get_tpr_edi - xchg %eax, %edi - ret - -mp_get_tpr_ebp: - mov %eax, %ebp - call mp_get_tpr_eax - xchg %eax, %ebp - ret - -mp_get_tpr_stack: - call mp_get_tpr_eax - xchg %eax, 4(%esp) - ret - -mp_set_tpr_eax: - push %eax - call mp_set_tpr - ret - -mp_set_tpr: - pushf - push %eax - push %ecx - push %edx - push %ebx - cli - reenable_vtpr - -mp_set_tpr_failed: - fs/movzbl pcr_cpu, %edx - - mov vcpu_shift, %ecx ; fixup - shl %cl, %edx - - testb $1, vapic+4(%edx) ; fixup delta=-5 - jz mp_set_tpr_bad - - mov vapic(%edx), %eax ; fixup - - mov %eax, %ebx - mov 24(%esp), %bl - - /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */ - - lock cmpxchg %ebx, vapic(%edx) ; fixup - jnz mp_set_tpr_failed - - /* compute ppr */ - cmp %bh, %bl - jae mp_tpr_is_bigger -mp_isr_is_bigger: - mov %bh, %bl -mp_tpr_is_bigger: - /* %bl = ppr */ - rol $8, %ebx - /* now: %bl = irr, %bh = ppr */ - cmp %bh, %bl - ja mp_set_tpr_poll_irq - -mp_set_tpr_out: - pop %ebx - pop %edx - pop %ecx - pop %eax - popf - ret $4 - -mp_set_tpr_poll_irq: - mov $kvm_hypercall_vapic_poll_irq, %eax - kvm_hypercall - jmp mp_set_tpr_out - -mp_set_tpr_bad: - mov 24(%esp), %ecx - mov real_tpr, %eax ; fixup - mov %ecx, (%eax) - jmp mp_set_tpr_out - -up_get_tpr_eax: - reenable_vtpr - movzbl vapic, %eax ; fixup - ret - -up_get_tpr_ebx: - reenable_vtpr - movzbl vapic, %ebx ; fixup - ret - -up_get_tpr_ecx: - reenable_vtpr - movzbl vapic, %ecx ; fixup - ret - -up_get_tpr_edx: - reenable_vtpr - movzbl vapic, %edx ; fixup - ret - -up_get_tpr_esi: - reenable_vtpr - movzbl vapic, %esi ; fixup - ret - -up_get_tpr_edi: - reenable_vtpr - movzbl vapic, %edi ; fixup - ret - -up_get_tpr_ebp: - reenable_vtpr - movzbl vapic, %ebp ; fixup - ret - -up_get_tpr_stack: - reenable_vtpr - movzbl vapic, %eax ; fixup - xchg %eax, 4(%esp) - ret - -up_set_tpr_eax: - push %eax - call up_set_tpr - ret - -up_set_tpr: - pushf - push %eax - push %ebx - reenable_vtpr - -up_set_tpr_failed: - mov vapic, %eax ; fixup - - mov %eax, %ebx - mov 16(%esp), %bl - - /* %ebx = new vapic (%bl = tpr, %bh = isr, %b3 = irr) */ - - lock cmpxchg %ebx, vapic ; fixup - jnz up_set_tpr_failed - - /* compute ppr */ - cmp %bh, %bl - jae up_tpr_is_bigger -up_isr_is_bigger: - mov %bh, %bl -up_tpr_is_bigger: - /* %bl = ppr */ - rol $8, %ebx - /* now: %bl = irr, %bh = ppr */ - cmp %bh, %bl - ja up_set_tpr_poll_irq - -up_set_tpr_out: - pop %ebx - pop %eax - popf - ret $4 - -up_set_tpr_poll_irq: - mov $kvm_hypercall_vapic_poll_irq, %eax - kvm_hypercall - jmp up_set_tpr_out - -.text 1 - fixup_end = . -.text 0 - -/* - * vapic format: - * per-vcpu records of size 2^vcpu shift. - * byte 0: tpr (r/w) - * byte 1: highest in-service interrupt (isr) (r/o); bits 3:0 are zero - * byte 2: zero (r/o) - * byte 3: highest pending interrupt (irr) (r/o) - */ -.text 2 - -.align 128 - -vapic: -. = . + vapic_size - -OPTION_ROM_END diff -Nru seabios-1.14.0/debian/optionrom/linuxboot_dma.c seabios-1.15.0/debian/optionrom/linuxboot_dma.c --- seabios-1.14.0/debian/optionrom/linuxboot_dma.c 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/linuxboot_dma.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,288 +0,0 @@ -/* - * Linux Boot Option ROM for fw_cfg DMA - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Copyright (c) 2015-2016 Red Hat Inc. - * Authors: - * Marc MarĂ­ - * Richard W.M. Jones - */ - -asm( -".text\n" -".global _start\n" -"_start:\n" -" .short 0xaa55\n" -" .byte 3\n" /* desired size in 512 units; signrom.py adds padding */ -" .byte 0xcb\n" /* far return without prefix */ -" .org 0x18\n" -" .short 0\n" -" .short _pnph\n" -"_pnph:\n" -" .ascii \"$PnP\"\n" -" .byte 0x01\n" -" .byte (_pnph_len / 16)\n" -" .short 0x0000\n" -" .byte 0x00\n" -" .byte 0x00\n" -" .long 0x00000000\n" -" .short _manufacturer\n" -" .short _product\n" -" .long 0x00000000\n" -" .short 0x0000\n" -" .short 0x0000\n" -" .short _bev\n" -" .short 0x0000\n" -" .short 0x0000\n" -" .equ _pnph_len, . - _pnph\n" -"_manufacturer:\n" -" .asciz \"QEMU\"\n" -"_product:\n" -" .asciz \"Linux loader DMA\"\n" -" .align 4, 0\n" -"_bev:\n" -" cli\n" -" cld\n" -" jmp load_kernel\n" -); - -#include "fw_cfg_keys.h" - -/* QEMU_CFG_DMA_CONTROL bits */ -#define BIOS_CFG_DMA_CTL_ERROR 0x01 -#define BIOS_CFG_DMA_CTL_READ 0x02 -#define BIOS_CFG_DMA_CTL_SKIP 0x04 -#define BIOS_CFG_DMA_CTL_SELECT 0x08 - -#define BIOS_CFG_DMA_ADDR_HIGH 0x514 -#define BIOS_CFG_DMA_ADDR_LOW 0x518 - -#define uint64_t unsigned long long -#define uint32_t unsigned int -#define uint16_t unsigned short - -#define barrier() asm("" : : : "memory") - -typedef struct FWCfgDmaAccess { - uint32_t control; - uint32_t length; - uint64_t address; -} __attribute__((packed)) FWCfgDmaAccess; - -static inline void outl(uint32_t value, uint16_t port) -{ - asm("outl %0, %w1" : : "a"(value), "Nd"(port)); -} - -static inline void set_es(void *addr) -{ - uint32_t seg = (uint32_t)addr >> 4; - asm("movl %0, %%es" : : "r"(seg)); -} - -#ifdef __clang__ -#define ADDR32 -#else -#define ADDR32 "addr32 " -#endif - -static inline uint16_t readw_es(uint16_t offset) -{ - uint16_t val; - asm(ADDR32 "movw %%es:(%1), %0" : "=r"(val) : "r"((uint32_t)offset)); - barrier(); - return val; -} - -static inline uint32_t readl_es(uint16_t offset) -{ - uint32_t val; - asm(ADDR32 "movl %%es:(%1), %0" : "=r"(val) : "r"((uint32_t)offset)); - barrier(); - return val; -} - -static inline void writel_es(uint16_t offset, uint32_t val) -{ - barrier(); - asm(ADDR32 "movl %0, %%es:(%1)" : : "r"(val), "r"((uint32_t)offset)); -} - -static inline uint32_t bswap32(uint32_t x) -{ - asm("bswapl %0" : "=r" (x) : "0" (x)); - return x; -} - -static inline uint64_t bswap64(uint64_t x) -{ - asm("bswapl %%eax; bswapl %%edx; xchg %%eax, %%edx" : "=A" (x) : "0" (x)); - return x; -} - -static inline uint64_t cpu_to_be64(uint64_t x) -{ - return bswap64(x); -} - -static inline uint32_t cpu_to_be32(uint32_t x) -{ - return bswap32(x); -} - -static inline uint32_t be32_to_cpu(uint32_t x) -{ - return bswap32(x); -} - -/* clang is happy to inline this function, and bloats the - * ROM. - */ -static __attribute__((__noinline__)) -void bios_cfg_read_entry(void *buf, uint16_t entry, uint32_t len) -{ - FWCfgDmaAccess access; - uint32_t control = (entry << 16) | BIOS_CFG_DMA_CTL_SELECT - | BIOS_CFG_DMA_CTL_READ; - - access.address = cpu_to_be64((uint64_t)(uint32_t)buf); - access.length = cpu_to_be32(len); - access.control = cpu_to_be32(control); - - barrier(); - - outl(cpu_to_be32((uint32_t)&access), BIOS_CFG_DMA_ADDR_LOW); - - while (be32_to_cpu(access.control) & ~BIOS_CFG_DMA_CTL_ERROR) { - barrier(); - } -} - -/* Return top of memory using BIOS function E801. */ -static uint32_t get_e801_addr(void) -{ - uint16_t ax, bx, cx, dx; - uint32_t ret; - - asm("int $0x15\n" - : "=a"(ax), "=b"(bx), "=c"(cx), "=d"(dx) - : "a"(0xe801), "b"(0), "c"(0), "d"(0)); - - /* Not SeaBIOS, but in theory a BIOS could return CX=DX=0 in which - * case we need to use the result from AX & BX instead. - */ - if (cx == 0 && dx == 0) { - cx = ax; - dx = bx; - } - - if (dx) { - /* DX = extended memory above 16M, in 64K units. - * Convert it to bytes and return. - */ - ret = ((uint32_t)dx + 256 /* 16M in 64K units */) << 16; - } else { - /* This is a fallback path for machines with <= 16MB of RAM, - * which probably would never be the case, but deal with it - * anyway. - * - * CX = extended memory between 1M and 16M, in kilobytes - * Convert it to bytes and return. - */ - ret = ((uint32_t)cx + 1024 /* 1M in K */) << 10; - } - - return ret; -} - -/* Force the asm name without leading underscore, even on Win32. */ -extern void load_kernel(void) asm("load_kernel"); - -void load_kernel(void) -{ - void *setup_addr; - void *initrd_addr; - void *kernel_addr; - void *cmdline_addr; - uint32_t setup_size; - uint32_t initrd_size; - uint32_t kernel_size; - uint32_t cmdline_size; - uint32_t initrd_end_page, max_allowed_page; - uint32_t segment_addr, stack_addr; - - bios_cfg_read_entry(&setup_addr, FW_CFG_SETUP_ADDR, 4); - bios_cfg_read_entry(&setup_size, FW_CFG_SETUP_SIZE, 4); - bios_cfg_read_entry(setup_addr, FW_CFG_SETUP_DATA, setup_size); - - set_es(setup_addr); - - /* For protocol < 0x203 we don't have initrd_max ... */ - if (readw_es(0x206) < 0x203) { - /* ... so we assume initrd_max = 0x37ffffff. */ - writel_es(0x22c, 0x37ffffff); - } - - bios_cfg_read_entry(&initrd_addr, FW_CFG_INITRD_ADDR, 4); - bios_cfg_read_entry(&initrd_size, FW_CFG_INITRD_SIZE, 4); - - initrd_end_page = ((uint32_t)(initrd_addr + initrd_size) & -4096); - max_allowed_page = (readl_es(0x22c) & -4096); - - if (initrd_end_page != 0 && max_allowed_page != 0 && - initrd_end_page != max_allowed_page) { - /* Initrd at the end of memory. Compute better initrd address - * based on e801 data - */ - initrd_addr = (void *)((get_e801_addr() - initrd_size) & -4096); - writel_es(0x218, (uint32_t)initrd_addr); - - } - - bios_cfg_read_entry(initrd_addr, FW_CFG_INITRD_DATA, initrd_size); - - bios_cfg_read_entry(&kernel_addr, FW_CFG_KERNEL_ADDR, 4); - bios_cfg_read_entry(&kernel_size, FW_CFG_KERNEL_SIZE, 4); - bios_cfg_read_entry(kernel_addr, FW_CFG_KERNEL_DATA, kernel_size); - - bios_cfg_read_entry(&cmdline_addr, FW_CFG_CMDLINE_ADDR, 4); - bios_cfg_read_entry(&cmdline_size, FW_CFG_CMDLINE_SIZE, 4); - bios_cfg_read_entry(cmdline_addr, FW_CFG_CMDLINE_DATA, cmdline_size); - - /* Boot linux */ - segment_addr = ((uint32_t)setup_addr >> 4); - stack_addr = (uint32_t)(cmdline_addr - setup_addr - 16); - - /* As we are changing critical registers, we cannot leave freedom to the - * compiler. - */ - asm("movw %%ax, %%ds\n" - "movw %%ax, %%es\n" - "movw %%ax, %%fs\n" - "movw %%ax, %%gs\n" - "movw %%ax, %%ss\n" - "movl %%ebx, %%esp\n" - "addw $0x20, %%ax\n" - "pushw %%ax\n" /* CS */ - "pushw $0\n" /* IP */ - /* Clear registers and jump to Linux */ - "xor %%ebx, %%ebx\n" - "xor %%ecx, %%ecx\n" - "xor %%edx, %%edx\n" - "xor %%edi, %%edi\n" - "xor %%ebp, %%ebp\n" - "lretw\n" - : : "a"(segment_addr), "b"(stack_addr)); -} diff -Nru seabios-1.14.0/debian/optionrom/linuxboot.S seabios-1.15.0/debian/optionrom/linuxboot.S --- seabios-1.14.0/debian/optionrom/linuxboot.S 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/linuxboot.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,195 +0,0 @@ -/* - * Linux Boot Option ROM - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Copyright Novell Inc, 2009 - * Authors: Alexander Graf - * - * Based on code in hw/pc.c. - */ - -#include "optionrom.h" - -#define BOOT_ROM_PRODUCT "Linux loader" - -BOOT_ROM_START - -run_linuxboot: - - cli - cld - - jmp copy_kernel -boot_kernel: - - read_fw FW_CFG_SETUP_ADDR - - mov %eax, %ebx - shr $4, %ebx - - /* All segments contain real_addr */ - mov %bx, %ds - mov %bx, %es - mov %bx, %fs - mov %bx, %gs - mov %bx, %ss - - /* CX = CS we want to jump to */ - add $0x20, %bx - mov %bx, %cx - - /* SP = cmdline_addr-real_addr-16 */ - read_fw FW_CFG_CMDLINE_ADDR - mov %eax, %ebx - read_fw FW_CFG_SETUP_ADDR - sub %eax, %ebx - sub $16, %ebx - mov %ebx, %esp - - /* Build indirect lret descriptor */ - pushw %cx /* CS */ - xor %ax, %ax - pushw %ax /* IP = 0 */ - - /* Clear registers */ - xor %eax, %eax - xor %ebx, %ebx - xor %ecx, %ecx - xor %edx, %edx - xor %edi, %edi - xor %ebp, %ebp - - /* Jump to Linux */ - lret - - -copy_kernel: - /* Read info block in low memory (0x10000 or 0x90000) */ - read_fw FW_CFG_SETUP_ADDR - shr $4, %eax - mov %eax, %es - xor %edi, %edi - read_fw_blob_addr32_edi(FW_CFG_SETUP) - - cmpw $0x203, %es:0x206 // if protocol >= 0x203 - jae 1f // have initrd_max - movl $0x37ffffff, %es:0x22c // else assume 0x37ffffff -1: - - /* Check if using kernel-specified initrd address */ - read_fw FW_CFG_INITRD_ADDR - mov %eax, %edi // (load_kernel wants it in %edi) - read_fw FW_CFG_INITRD_SIZE // find end of initrd - add %edi, %eax - xor %es:0x22c, %eax // if it matches es:0x22c - and $-4096, %eax // (apart from padding for page) - jz load_kernel // then initrd is not at top - // of memory - - /* pc.c placed the initrd at end of memory. Compute a better - * initrd address based on e801 data. - */ - 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 */ - movl %edi, %es:0x218 /* put it in the header */ - -load_kernel: - /* 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 - - /* Now create the GDT descriptor */ - movw $((3 * 8) - 1), -16(%bp) - mov %cs, %eax - movzwl %ax, %eax - shl $4, %eax - addl $gdt, %eax - movl %eax, -14(%bp) - - /* And load the GDT */ - data32 lgdt -16(%bp) - mov %ebp, %esp - - /* Get us to protected mode now */ - mov $1, %eax - mov %eax, %cr0 - - /* So we can set ES to a 32-bit segment */ - mov $0x10, %eax - mov %eax, %es - - /* We're now running in 16-bit CS, but 32-bit ES! */ - - /* Load kernel and initrd */ - read_fw_blob_addr32_edi(FW_CFG_INITRD) - read_fw_blob_addr32(FW_CFG_KERNEL) - read_fw_blob_addr32(FW_CFG_CMDLINE) - - /* And now jump into Linux! */ - mov $0, %eax - mov %eax, %cr0 - - /* ES = CS */ - mov %cs, %ax - mov %ax, %es - - jmp boot_kernel - -/* Variables */ - -.align 4, 0 -gdt: - /* 0x00 */ -.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - - /* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */ -.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00 - - /* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */ -.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00 - -BOOT_ROM_END diff -Nru seabios-1.14.0/debian/optionrom/Makefile seabios-1.15.0/debian/optionrom/Makefile --- seabios-1.14.0/debian/optionrom/Makefile 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/Makefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -LD = ld -OBJCOPY = objcopy -CC = cc -CFLAGS = -O2 -m16 -Wa,-32 -ffreestanding -fno-stack-protector -fno-pie - -all: extboot.bin kvmvapic.bin linuxboot.bin linuxboot_dma.bin multiboot.bin - -%.o: %.S - $(CC) $(CFLAGS) -c -o $@ $< -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - -%.img: %.o - $(LD) -Ttext 0 -e _start -m elf_i386 -s -o $@ $< - -%.raw: %.img - $(OBJCOPY) -O binary -j .text $< $@ - -%.bin: %.raw - python3 ./signrom.py $< $@ - -clean: - rm -f *.o *.d *.raw *.img *.bin *~ - -.PHONY: all clean diff -Nru seabios-1.14.0/debian/optionrom/multiboot.S seabios-1.15.0/debian/optionrom/multiboot.S --- seabios-1.14.0/debian/optionrom/multiboot.S 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/multiboot.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,232 +0,0 @@ -/* - * Multiboot Option ROM - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Copyright Novell Inc, 2009 - * Authors: Alexander Graf - */ - -#include "optionrom.h" - -#define BOOT_ROM_PRODUCT "multiboot loader" - -#define MULTIBOOT_MAGIC 0x2badb002 - -#define GS_PROT_JUMP 0 -#define GS_GDT_DESC 6 - - -BOOT_ROM_START - -run_multiboot: - - cli - cld - - mov %cs, %eax - shl $0x4, %eax - - /* set up a long jump descriptor that is PC relative */ - - /* move stack memory to %gs */ - mov %ss, %ecx - shl $0x4, %ecx - mov %esp, %ebx - add %ebx, %ecx - sub $0x20, %ecx - sub $0x30, %esp - shr $0x4, %ecx - mov %cx, %gs - - /* now push the indirect jump descriptor there */ - mov (prot_jump), %ebx - add %eax, %ebx - movl %ebx, %gs:GS_PROT_JUMP - mov $8, %bx - movw %bx, %gs:GS_PROT_JUMP + 4 - - /* fix the gdt descriptor to be PC relative */ - movw (gdt_desc), %bx - movw %bx, %gs:GS_GDT_DESC - movl (gdt_desc+2), %ebx - add %eax, %ebx - movl %ebx, %gs:GS_GDT_DESC + 2 - - xor %eax, %eax - mov %eax, %es - - /* Read the bootinfo struct into RAM */ - read_fw_blob(FW_CFG_INITRD) - - /* FS = bootinfo_struct */ - read_fw FW_CFG_INITRD_ADDR - shr $4, %eax - mov %ax, %fs - - /* Account for the EBDA in the multiboot structure's e801 - * map. - */ - int $0x12 - cwtl - movl %eax, %fs:4 - - /* ES = mmap_addr */ - mov %fs:48, %eax - shr $4, %eax - mov %ax, %es - - /* Initialize multiboot mmap structs using int 0x15(e820) */ - xor %ebx, %ebx - /* 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 - /* e820 */ - movl $0x0000e820, %eax - /* 'SMAP' magic */ - movl $0x534d4150, %edx - int $0x15 - -mmap_check_entry: - /* Error or last entry already done? */ - jb mmap_done - -mmap_store_entry: - /* 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 - - /* 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: - data32 lgdt %gs:GS_GDT_DESC - - /* get us to protected mode now */ - movl $1, %eax - movl %eax, %cr0 - - /* the LJMP sets CS for us and gets us to 32-bit */ -ljmp: - data32 ljmp *%gs:GS_PROT_JUMP - -prot_mode: -.code32 - - /* initialize all other segments */ - movl $0x10, %eax - movl %eax, %ss - movl %eax, %ds - movl %eax, %es - movl %eax, %fs - movl %eax, %gs - - /* Read the kernel and modules into RAM */ - read_fw_blob(FW_CFG_KERNEL) - - /* Jump off to the kernel */ - read_fw FW_CFG_KERNEL_ENTRY - mov %eax, %ecx - - /* EBX contains a pointer to the bootinfo struct */ - read_fw FW_CFG_INITRD_ADDR - movl %eax, %ebx - - /* EAX has to contain the magic */ - movl $MULTIBOOT_MAGIC, %eax -ljmp2: - jmp *%ecx - -/* Variables */ -.align 4, 0 -prot_jump: .long prot_mode - .short 8 - -.align 4, 0 -gdt: - /* 0x00 */ -.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - - /* 0x08: code segment (base=0, limit=0xfffff, type=32bit code exec/read, DPL=0, 4k) */ -.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00 - - /* 0x10: data segment (base=0, limit=0xfffff, type=32bit data read/write, DPL=0, 4k) */ -.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00 - - /* 0x18: code segment (base=0, limit=0x0ffff, type=16bit code exec/read/conf, DPL=0, 1b) */ -.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00 - - /* 0x20: data segment (base=0, limit=0x0ffff, type=16bit data read/write, DPL=0, 1b) */ -.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00 - -gdt_desc: -.short (5 * 8) - 1 -.long gdt - -BOOT_ROM_END diff -Nru seabios-1.14.0/debian/optionrom/optionrom.h seabios-1.15.0/debian/optionrom/optionrom.h --- seabios-1.14.0/debian/optionrom/optionrom.h 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/optionrom.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -/* - * Common Option ROM Functions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Copyright Novell Inc, 2009 - * Authors: Alexander Graf - */ - - -#include "fw_cfg_keys.h" - -#define BIOS_CFG_IOPORT_CFG 0x510 -#define BIOS_CFG_IOPORT_DATA 0x511 - -/* Break the translation block flow so -d cpu shows us values */ -#define DEBUG_HERE \ - jmp 1f; \ - 1: - -/* - * Read a variable from the fw_cfg device. - * Clobbers: %edx - * Out: %eax - */ -.macro read_fw VAR - mov $\VAR, %ax - mov $BIOS_CFG_IOPORT_CFG, %dx - outw %ax, (%dx) - mov $BIOS_CFG_IOPORT_DATA, %dx - inb (%dx), %al - shl $8, %eax - inb (%dx), %al - shl $8, %eax - inb (%dx), %al - shl $8, %eax - inb (%dx), %al - bswap %eax -.endm - -#define read_fw_blob_pre(var) \ - read_fw var ## _SIZE; \ - mov %eax, %ecx; \ - mov $var ## _DATA, %ax; \ - mov $BIOS_CFG_IOPORT_CFG, %edx; \ - outw %ax, (%dx); \ - mov $BIOS_CFG_IOPORT_DATA, %dx; \ - cld - -/* - * Read a blob from the fw_cfg device. - * Requires _ADDR, _SIZE and _DATA values for the parameter. - * - * 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); \ - */ \ - .dc.b 0xf3,0x6c - -/* - * Read a blob from the fw_cfg device in forced addr32 mode. - * Requires _ADDR, _SIZE and _DATA values for the parameter. - * - * Clobbers: %eax, %edx, %es, %ecx, %edi - */ -#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); \ - */ \ - .dc.b 0x67,0xf3,0x6c - -#define OPTION_ROM_START \ - .code16; \ - .text; \ - .global _start; \ - _start:; \ - .short 0xaa55; \ - .byte (_end - _start) / 512; - -#define BOOT_ROM_START \ - OPTION_ROM_START \ - lret; \ - .org 0x18; \ - .short 0; \ - .short _pnph; \ - _pnph: \ - .ascii "$PnP"; \ - .byte 0x01; \ - .byte ( _pnph_len / 16 ); \ - .short 0x0000; \ - .byte 0x00; \ - .byte 0x00; \ - .long 0x00000000; \ - .short _manufacturer; \ - .short _product; \ - .long 0x00000000; \ - .short 0x0000; \ - .short 0x0000; \ - .short _bev; \ - .short 0x0000; \ - .short 0x0000; \ - .equ _pnph_len, . - _pnph; \ - _bev:; \ - /* DS = CS */ \ - movw %cs, %ax; \ - movw %ax, %ds; - -#define OPTION_ROM_END \ - .byte 0; \ - .align 512, 0; \ - _end: - -#define BOOT_ROM_END \ - _manufacturer:; \ - .asciz "QEMU"; \ - _product:; \ - .asciz BOOT_ROM_PRODUCT; \ - OPTION_ROM_END - diff -Nru seabios-1.14.0/debian/optionrom/README seabios-1.15.0/debian/optionrom/README --- seabios-1.14.0/debian/optionrom/README 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -README file for seabios/debian/optionrom - -The files in this directory are taken from qemu sources, -git commits below. They're from qemu and used by qemu, -but are packaged with seabios, because the files must -be built on x86 arch (just like seabios itself) but are -Arch: all. Seabios package itself is Arch: all, so it -has no issues building some more stuff with it. But -qemu is Arch: any, but the only architecture where these -files can be built is x86. So we just move them into -seabios package and build here. - -The files taken from qemu: - -pc-bios/optionrom - kvmvapic.S linuxboot.S linuxboot_dma.c multiboot.S optionrom.h - (inludes a trivial change for #include'ing fw_cfg.h from optionrom.h) -include/hw/nvram/fw_cfg_keys.h -scripts/signrom.py -pc-bios/optionrom/extboot.S 211721f31c62cc889369da79d75c38f7297b6465 Feb 18 17:13:30 2010 +0100 - (removed upstream) - -and Makefile to build it all. diff -Nru seabios-1.14.0/debian/optionrom/signrom.py seabios-1.15.0/debian/optionrom/signrom.py --- seabios-1.14.0/debian/optionrom/signrom.py 2020-12-08 10:46:21.000000000 +0000 +++ seabios-1.15.0/debian/optionrom/signrom.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -from __future__ import print_function -# -# Option ROM signing utility -# -# Authors: -# Jan Kiszka -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. -# See the COPYING file in the top-level directory. - -import sys -import struct - -if len(sys.argv) < 3: - print('usage: signrom.py input output') - sys.exit(1) - -fin = open(sys.argv[1], 'rb') -fout = open(sys.argv[2], 'wb') - -magic = fin.read(2) -if magic != b'\x55\xaa': - sys.exit("%s: option ROM does not begin with magic 55 aa" % sys.argv[1]) - -size_byte = ord(fin.read(1)) -fin.seek(0) -data = fin.read() - -size = size_byte * 512 -if len(data) > size: - sys.stderr.write('error: ROM is too large (%d > %d)\n' % (len(data), size)) - sys.exit(1) -elif len(data) < size: - # Add padding if necessary, rounding the whole input to a multiple of - # 512 bytes according to the third byte of the input. - # size-1 because a final byte is added below to store the checksum. - data = data.ljust(size-1, b'\0') -else: - if ord(data[-1:]) != 0: - sys.stderr.write('WARNING: ROM includes nonzero checksum\n') - data = data[:size-1] - -fout.write(data) - -checksum = 0 -for b in data: - # catch Python 2 vs. 3 differences - if isinstance(b, int): - checksum += b - else: - checksum += ord(b) -checksum = (256 - checksum) % 256 - -# Python 3 no longer allows chr(checksum) -fout.write(struct.pack('B', checksum)) - -fin.close() -fout.close() diff -Nru seabios-1.14.0/debian/rules seabios-1.15.0/debian/rules --- seabios-1.14.0/debian/rules 2020-12-08 11:52:41.000000000 +0000 +++ seabios-1.15.0/debian/rules 2021-12-05 09:58:22.000000000 +0000 @@ -13,8 +13,8 @@ VGABIOSES = ati bochs-display cirrus stdvga virtio vmware qxl isavga ramfb VGABIOS_TARGETS = $(addprefix build/vgabios-, $(addsuffix .bin, $(VGABIOSES))) -BIOS_TARGETS = build/bios.bin build/bios-256k.bin ${VGABIOS_TARGETS} -BUILD_TARGETS = $(BIOS_TARGETS) build/optionrom-stamp +BIOS_TARGETS = build/bios.bin build/bios-256k.bin build/bios-microvm.bin ${VGABIOS_TARGETS} +BUILD_TARGETS = $(BIOS_TARGETS) build build-indep: $(BUILD_TARGETS) @@ -27,12 +27,7 @@ set -e; \ if [ ! -e $(basename $@)/.config.old ]; then \ rm -rf $(basename $@); mkdir -p $(basename $@); \ - for x in $2; do \ - case $$x in \ - (*=n) echo "# CONFIG_$${x%=*} is not set";; \ - (*) echo CONFIG_$$x;; \ - esac; \ - done > $(basename $@)/.config; \ + for x in $2; do echo CONFIG_$$x; done > $(basename $@)/.config; \ $(MAKE) ${MAKEVARS} KCONFIG_CONFIG=$(CURDIR)/$(basename $@)/.config OUT=$(basename $@)/ oldnoconfig; \ fi +$(MAKE) ${MAKEVARS} KCONFIG_CONFIG=$(CURDIR)/$(basename $@)/.config OUT=$(basename $@)/ $(basename $@)/$1.bin @@ -45,6 +40,9 @@ $(call build-bios,bios,QEMU=y ROM_SIZE=128 PVSCSI=n ATA_DMA=n BOOTSPLASH=n XEN=n USB_OHCI=n USB_XHCI=n USB_UAS=n SDCARD=n TCGBIOS=n MPT_SCSI=n ESP_SCSI=n MEGASAS=n NVME=n USE_SMM=n VGAHOOKS=n HOST_BIOS_GEOMETRY=n ACPI_PARSE=n) build/bios-256k.bin: $(call build-bios,bios,QEMU=y ROM_SIZE=256) +build/bios-microvm.bin: + $(call build-bios,bios,QEMU=y ROM_SIZE=256 XEN=n BOOTSPLASH=n ATA=n AHCI=n SDCARD=n PVSCSI=n ESP_SCSI=n LSI_SCSI=n MEGASAS=n MPT_SCSI=n FLOPPY=n NVME=n PS2PORT=n USB=n LPT=n RTC_TIMER=n USE_SMM=n PMTIMER=n TCGBIOS=n HARDWARE_IRQ=n ACPI_PARSE=y) + ${BIOS_TARGETS}: build/env-stamp build/env-stamp: @@ -81,17 +79,10 @@ build/vgabios-ramfb.bin: $(call build-bios,vgabios,BUILD_VGABIOS=y VGA_RAMFB=y VGA_PCI=n) -build/optionrom-stamp: - $(MAKE) -C debian/optionrom/ - chmod -x debian/optionrom/*.bin - ln -s kvmvapic.bin debian/optionrom/vapic.bin - mkdir -p $(dir $@) && touch $@ - clean: dh_testdir rm -rf build/ rm -f src/fw/*.hex - $(MAKE) -C debian/optionrom/ clean dh_clean install install-indep: build-indep diff -Nru seabios-1.14.0/docs/Releases.md seabios-1.15.0/docs/Releases.md --- seabios-1.14.0/docs/Releases.md 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/docs/Releases.md 2021-12-03 01:43:20.000000000 +0000 @@ -1,6 +1,17 @@ History of SeaBIOS releases. Please see [download](Download) for information on obtaining these releases. +SeaBIOS 1.15.0 +============== + +Available on 20211202. Major changes in this release: + +* Improved support for USB devices with multiple interfaces. +* Support for USB XHCI devices using direct MMIO access (instead of PCI). +* NVMe improvements. +* Increased "f-segment" RAM allocations for BIOS tables. +* Several bug fixes and code cleanups. + SeaBIOS 1.14.0 ============== diff -Nru seabios-1.14.0/Makefile seabios-1.15.0/Makefile --- seabios-1.14.0/Makefile 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/Makefile 2021-12-03 01:43:20.000000000 +0000 @@ -46,7 +46,7 @@ fw/mtrr.c fw/xen.c fw/acpi.c fw/mptable.c fw/pirtable.c \ fw/smbios.c fw/romfile_loader.c fw/dsdt_parser.c hw/virtio-ring.c \ hw/virtio-pci.c hw/virtio-mmio.c hw/virtio-blk.c hw/virtio-scsi.c \ - hw/tpm_drivers.c hw/nvme.c + hw/tpm_drivers.c hw/nvme.c sha256.c sha512.c SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c DIRS=src src/hw src/fw vgasrc diff -Nru seabios-1.14.0/scripts/layoutrom.py seabios-1.15.0/scripts/layoutrom.py --- seabios-1.14.0/scripts/layoutrom.py 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/scripts/layoutrom.py 2021-12-03 01:43:20.000000000 +0000 @@ -651,6 +651,10 @@ # Read kconfig config file config = scanconfig(cfgfile) + # larger roms have more room in the f-segment due to moving out 32bit code + if config.get('CONFIG_ROM_SIZE') >= 256: + BUILD_MIN_BIOSTABLE = 8192 + # Figure out which sections to keep. allsections = info16[0] + info32seg[0] + info32flat[0] symbols = {'16': info16[1], '32seg': info32seg[1], '32flat': info32flat[1]} diff -Nru seabios-1.14.0/src/boot.c seabios-1.15.0/src/boot.c --- seabios-1.14.0/src/boot.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/boot.c 2021-12-03 01:43:20.000000000 +0000 @@ -423,9 +423,19 @@ { if (!CONFIG_BOOTORDER) return -1; - // Find usb - for example: /pci@i0cf8/usb@1,2/storage@1/channel@0/disk@0,0 + // Find usb - examples: + // pci: /pci@i0cf8/usb@1,2/storage@1/channel@0/disk@0,0 + // mmio: /sysbus-xhci@00000000fe900000/storage@1/channel@0/disk@0,0 char desc[256], *p; - p = build_pci_path(desc, sizeof(desc), "usb", usbdev->hub->cntl->pci); + + if (usbdev->hub->cntl->pci) + p = build_pci_path(desc, sizeof(desc), "usb", usbdev->hub->cntl->pci); + else if (usbdev->hub->cntl->mmio) + p = desc + snprintf(desc, sizeof(desc), "/*@%016x" + , (u32)usbdev->hub->cntl->mmio); + else + return -1; + p = build_usb_path(p, desc+sizeof(desc)-p, usbdev->hub); snprintf(p, desc+sizeof(desc)-p, "/storage@%x/*@0/*@0,%x" , usb_portmap(usbdev), lun); diff -Nru seabios-1.14.0/src/fw/biostables.c seabios-1.15.0/src/fw/biostables.c --- seabios-1.14.0/src/fw/biostables.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/fw/biostables.c 2021-12-03 01:43:20.000000000 +0000 @@ -462,10 +462,16 @@ /* common case: add our own type 0, with 3 strings and 4 '\0's */ u16 t0_len = sizeof(struct smbios_type_0) + strlen(BIOS_NAME) + strlen(VERSION) + strlen(BIOS_DATE) + 4; - ep.structure_table_length += t0_len; - if (t0_len > ep.max_structure_size) - ep.max_structure_size = t0_len; - ep.number_of_structures++; + if (t0_len > (0xffff - ep.structure_table_length)) { + dprintf(1, "Insufficient space (%d bytes) to add SMBIOS type 0 table (%d bytes)\n", + 0xffff - ep.structure_table_length, t0_len); + need_t0 = 0; + } else { + ep.structure_table_length += t0_len; + if (t0_len > ep.max_structure_size) + ep.max_structure_size = t0_len; + ep.number_of_structures++; + } } /* allocate final blob and record its address in the entry point */ diff -Nru seabios-1.14.0/src/fw/dsdt_parser.c seabios-1.15.0/src/fw/dsdt_parser.c --- seabios-1.14.0/src/fw/dsdt_parser.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/fw/dsdt_parser.c 2021-12-03 01:43:20.000000000 +0000 @@ -515,7 +515,8 @@ } static struct acpi_device *acpi_dsdt_find(struct acpi_device *prev, - const u8 *aml, int size) + const u8 *aml1, int size1, + const u8 *aml2, int size2) { struct acpi_device *dev; struct hlist_node *node; @@ -527,11 +528,13 @@ for (; node != NULL; node = dev->node.next) { dev = container_of(node, struct acpi_device, node); - if (!aml) + if (!aml1 && !aml2) return dev; if (!dev->hid_aml) continue; - if (memcmp(dev->hid_aml + 5, aml, size) == 0) + if (aml1 && memcmp(dev->hid_aml + 5, aml1, size1) == 0) + return dev; + if (aml2 && memcmp(dev->hid_aml + 5, aml2, size2) == 0) return dev; } return NULL; @@ -568,19 +571,21 @@ u8 aml[10]; int len = snprintf((char*)aml, sizeof(aml), "\x0d%s", hid); - return acpi_dsdt_find(prev, aml, len); + return acpi_dsdt_find(prev, aml, len, NULL, 0); } struct acpi_device *acpi_dsdt_find_eisaid(struct acpi_device *prev, u16 eisaid) { if (!CONFIG_ACPI_PARSE) return NULL; - u8 aml[] = { + u8 aml1[] = { 0x0c, 0x41, 0xd0, eisaid >> 8, eisaid & 0xff }; - return acpi_dsdt_find(prev, aml, 5); + u8 aml2[10]; + int len2 = snprintf((char*)aml2, sizeof(aml2), "\x0dPNP%04X", eisaid); + return acpi_dsdt_find(prev, aml1, 5, aml2, len2); } char *acpi_dsdt_name(struct acpi_device *dev) @@ -651,9 +656,9 @@ struct acpi_device *dev; dprintf(1, "ACPI: dumping dsdt devices\n"); - for (dev = acpi_dsdt_find(NULL, NULL, 0); + for (dev = acpi_dsdt_find(NULL, NULL, 0, NULL, 0); dev != NULL; - dev = acpi_dsdt_find(dev, NULL, 0)) { + dev = acpi_dsdt_find(dev, NULL, 0, NULL, 0)) { dprintf(1, " %s", acpi_dsdt_name(dev)); if (dev->hid_aml) dprintf(1, ", hid"); diff -Nru seabios-1.14.0/src/hw/blockcmd.c seabios-1.15.0/src/hw/blockcmd.c --- seabios-1.14.0/src/hw/blockcmd.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/hw/blockcmd.c 2021-12-03 01:43:20.000000000 +0000 @@ -144,8 +144,9 @@ dprintf(6, "scsi_is_ready (drive=%p)\n", op->drive_fl); /* Retry TEST UNIT READY for 5 seconds unless MEDIUM NOT PRESENT is - * reported by the device. If the device reports "IN PROGRESS", + * reported by the device 3 times. If the device reports "IN PROGRESS", * 30 seconds is added. */ + int tries = 3; int in_progress = 0; u32 end = timer_calc(5000); for (;;) { @@ -167,8 +168,11 @@ // Sense succeeded. if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */ - dprintf(1, "Device reports MEDIUM NOT PRESENT\n"); - return -1; + tries--; + dprintf(1, "Device reports MEDIUM NOT PRESENT - %d tries left\n", + tries); + if (!tries) + return -1; } if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) { diff -Nru seabios-1.14.0/src/hw/nvme.c seabios-1.15.0/src/hw/nvme.c --- seabios-1.14.0/src/hw/nvme.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/hw/nvme.c 2021-12-03 01:43:20.000000000 +0000 @@ -152,10 +152,10 @@ /* Returns the next submission queue entry (or NULL if the queue is full). It also fills out Command Dword 0 and clears the rest. */ static struct nvme_sqe * -nvme_get_next_sqe(struct nvme_sq *sq, u8 opc, void *metadata, void *data) +nvme_get_next_sqe(struct nvme_sq *sq, u8 opc, void *metadata, void *data, void *data2) { if (((sq->head + 1) & sq->common.mask) == sq->tail) { - dprintf(3, "submission queue is full"); + dprintf(3, "submission queue is full\n"); return NULL; } @@ -166,11 +166,7 @@ sqe->cdw0 = opc | (sq->tail << 16 /* CID */); sqe->mptr = (u32)metadata; sqe->dptr_prp1 = (u32)data; - - if (sqe->dptr_prp1 & (NVME_PAGE_SIZE - 1)) { - /* Data buffer not page aligned. */ - warn_internalerror(); - } + sqe->dptr_prp2 = (u32)data2; return sqe; } @@ -200,7 +196,7 @@ struct nvme_sqe *cmd_identify; cmd_identify = nvme_get_next_sqe(&ctrl->admin_sq, NVME_SQE_OPC_ADMIN_IDENTIFY, NULL, - identify_buf); + identify_buf, NULL); if (!cmd_identify) { warn_internalerror(); @@ -238,10 +234,9 @@ } static void -nvme_probe_ns(struct nvme_ctrl *ctrl, struct nvme_namespace *ns, u32 ns_id) +nvme_probe_ns(struct nvme_ctrl *ctrl, u32 ns_idx, u8 mdts) { - ns->ctrl = ctrl; - ns->ns_id = ns_id; + u32 ns_id = ns_idx + 1; struct nvme_identify_ns *id = nvme_admin_identify_ns(ctrl, ns_id); if (!id) { @@ -257,12 +252,21 @@ goto free_buffer; } - ns->lba_count = id->nsze; - if (!ns->lba_count) { + if (!id->nsze) { dprintf(2, "NVMe NS %u is inactive.\n", ns_id); goto free_buffer; } + struct nvme_namespace *ns = malloc_fseg(sizeof(*ns)); + if (!ns) { + warn_noalloc(); + goto free_buffer; + } + memset(ns, 0, sizeof(*ns)); + ns->ctrl = ctrl; + ns->ns_id = ns_id; + ns->lba_count = id->nsze; + struct nvme_lba_format *fmt = &id->lbaf[current_lba_format]; ns->block_size = 1U << fmt->lbads; @@ -272,23 +276,32 @@ /* If we see devices that trigger this path, we need to increase our buffer size. */ warn_internalerror(); + free(ns); goto free_buffer; } - ns->drive.cntl_id = ns - ctrl->ns; + ns->drive.cntl_id = ns_idx; ns->drive.removable = 0; ns->drive.type = DTYPE_NVME; ns->drive.blksize = ns->block_size; ns->drive.sectors = ns->lba_count; + if (mdts) { + ns->max_req_size = ((1U << mdts) * NVME_PAGE_SIZE) / ns->block_size; + dprintf(3, "NVME NS %u max request size: %d sectors\n", + ns_id, ns->max_req_size); + } else { + ns->max_req_size = -1U; + } + ns->dma_buffer = zalloc_page_aligned(&ZoneHigh, NVME_PAGE_SIZE); char *desc = znprintf(MAXDESCSIZE, "NVMe NS %u: %llu MiB (%llu %u-byte " - "blocks + %u-byte metadata)\n", + "blocks + %u-byte metadata)", ns_id, (ns->lba_count * ns->block_size) >> 20, ns->lba_count, ns->block_size, ns->metadata_size); - dprintf(3, "%s", desc); + dprintf(3, "%s\n", desc); boot_add_hd(&ns->drive, desc, bootprio_find_pci_device(ctrl->pci)); free_buffer: @@ -329,7 +342,7 @@ cmd_create_cq = nvme_get_next_sqe(&ctrl->admin_sq, NVME_SQE_OPC_ADMIN_CREATE_IO_CQ, NULL, - cq->cqe); + cq->cqe, NULL); if (!cmd_create_cq) { goto err_destroy_cq; } @@ -373,7 +386,7 @@ cmd_create_sq = nvme_get_next_sqe(&ctrl->admin_sq, NVME_SQE_OPC_ADMIN_CREATE_IO_SQ, NULL, - sq->sqe); + sq->sqe, NULL); if (!cmd_create_sq) { goto err_destroy_sq; } @@ -408,19 +421,29 @@ int write) { u32 buf_addr = (u32)buf; + void *prp2; - if ((buf_addr & 0x3) || - ((buf_addr & ~(NVME_PAGE_SIZE - 1)) != - ((buf_addr + ns->block_size * count - 1) & ~(NVME_PAGE_SIZE - 1)))) { - /* Buffer is misaligned or crosses page boundary */ + if (buf_addr & 0x3) { + /* Buffer is misaligned */ warn_internalerror(); return DISK_RET_EBADTRACK; } + if ((ns->block_size * count) > (NVME_PAGE_SIZE * 2)) { + /* We need to describe more than 2 pages, rely on PRP List */ + prp2 = ns->prpl; + } else if ((ns->block_size * count) > NVME_PAGE_SIZE) { + /* Directly embed the 2nd page if we only need 2 pages */ + prp2 = (void *)(long)ns->prpl[0]; + } else { + /* One page is enough, don't expose anything else */ + prp2 = NULL; + } + struct nvme_sqe *io_read = nvme_get_next_sqe(&ns->ctrl->io_sq, write ? NVME_SQE_OPC_IO_WRITE : NVME_SQE_OPC_IO_READ, - NULL, buf); + NULL, buf, prp2); io_read->nsid = ns->ns_id; io_read->dword[10] = (u32)lba; io_read->dword[11] = (u32)(lba >> 32); @@ -440,6 +463,61 @@ return DISK_RET_SUCCESS; } +static void nvme_reset_prpl(struct nvme_namespace *ns) +{ + ns->prpl_len = 0; +} + +static int nvme_add_prpl(struct nvme_namespace *ns, u64 base) +{ + if (ns->prpl_len >= NVME_MAX_PRPL_ENTRIES) + return -1; + + ns->prpl[ns->prpl_len++] = base; + + return 0; +} + +static int nvme_build_prpl(struct nvme_namespace *ns, void *op_buf, u16 count) +{ + int first_page = 1; + u32 base = (long)op_buf; + s32 size; + + if (count > ns->max_req_size) + count = ns->max_req_size; + + nvme_reset_prpl(ns); + + size = count * ns->block_size; + /* Special case for transfers that fit into PRP1, but are unaligned */ + if (((size + (base & ~NVME_PAGE_MASK)) <= NVME_PAGE_SIZE)) { + ns->prp1 = op_buf; + return count; + } + + /* Every request has to be page aligned */ + if (base & ~NVME_PAGE_MASK) + return 0; + + /* Make sure a full block fits into the last chunk */ + if (size & (ns->block_size - 1ULL)) + return 0; + + for (; size > 0; base += NVME_PAGE_SIZE, size -= NVME_PAGE_SIZE) { + if (first_page) { + /* First page is special */ + ns->prp1 = (void*)base; + first_page = 0; + continue; + } + if (nvme_add_prpl(ns, base)) + return 0; + } + + return count; +} + static int nvme_create_io_queues(struct nvme_ctrl *ctrl) { @@ -457,13 +535,6 @@ return -1; } -static void -nvme_destroy_io_queues(struct nvme_ctrl *ctrl) -{ - nvme_destroy_sq(&ctrl->io_sq); - nvme_destroy_cq(&ctrl->io_cq); -} - /* Waits for CSTS.RDY to match rdy. Returns 0 on success. */ static int nvme_wait_csts_rdy(struct nvme_ctrl *ctrl, unsigned rdy) @@ -557,24 +628,15 @@ goto err_destroy_admin_sq; } - ctrl->ns = malloc_fseg(sizeof(*ctrl->ns) * ctrl->ns_count); - if (!ctrl->ns) { - warn_noalloc(); - goto err_destroy_ioq; - } - memset(ctrl->ns, 0, sizeof(*ctrl->ns) * ctrl->ns_count); - /* Populate namespace IDs */ int ns_idx; for (ns_idx = 0; ns_idx < ctrl->ns_count; ns_idx++) { - nvme_probe_ns(ctrl, &ctrl->ns[ns_idx], ns_idx + 1); + nvme_probe_ns(ctrl, ns_idx, identify->mdts); } dprintf(3, "NVMe initialization complete!\n"); return 0; - err_destroy_ioq: - nvme_destroy_io_queues(ctrl); err_destroy_admin_sq: nvme_destroy_sq(&ctrl->admin_sq); err_destroy_admin_cq: @@ -656,25 +718,34 @@ { int res = DISK_RET_SUCCESS; u16 const max_blocks = NVME_PAGE_SIZE / ns->block_size; - u16 i; + u16 i, blocks; for (i = 0; i < op->count && res == DISK_RET_SUCCESS;) { u16 blocks_remaining = op->count - i; - u16 blocks = blocks_remaining < max_blocks ? blocks_remaining - : max_blocks; char *op_buf = op->buf_fl + i * ns->block_size; - if (write) { - memcpy(ns->dma_buffer, op_buf, blocks * ns->block_size); - } - - res = nvme_io_readwrite(ns, op->lba + i, ns->dma_buffer, blocks, write); - dprintf(5, "ns %u %s lba %llu+%u: %d\n", ns->ns_id, write ? "write" - : "read", - op->lba + i, blocks, res); + blocks = nvme_build_prpl(ns, op_buf, blocks_remaining); + if (blocks) { + res = nvme_io_readwrite(ns, op->lba + i, ns->prp1, blocks, write); + dprintf(5, "ns %u %s lba %llu+%u: %d\n", ns->ns_id, write ? "write" + : "read", + op->lba, blocks, res); + } else { + blocks = blocks_remaining < max_blocks ? blocks_remaining + : max_blocks; - if (!write && res == DISK_RET_SUCCESS) { - memcpy(op_buf, ns->dma_buffer, blocks * ns->block_size); + if (write) { + memcpy(ns->dma_buffer, op_buf, blocks * ns->block_size); + } + + res = nvme_io_readwrite(ns, op->lba + i, ns->dma_buffer, blocks, write); + dprintf(5, "ns %u %s lba %llu+%u: %d\n", ns->ns_id, write ? "write" + : "read", + op->lba + i, blocks, res); + + if (!write && res == DISK_RET_SUCCESS) { + memcpy(op_buf, ns->dma_buffer, blocks * ns->block_size); + } } i += blocks; diff -Nru seabios-1.14.0/src/hw/nvme-int.h seabios-1.15.0/src/hw/nvme-int.h --- seabios-1.14.0/src/hw/nvme-int.h 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/hw/nvme-int.h 2021-12-03 01:43:20.000000000 +0000 @@ -10,6 +10,8 @@ #include "types.h" // u32 #include "pcidevice.h" // struct pci_device +#define NVME_MAX_PRPL_ENTRIES 15 /* Allows requests up to 64kb */ + /* Data structures */ /* The register file of a NVMe host controller. This struct follows the naming @@ -101,7 +103,6 @@ struct nvme_cq admin_cq; u32 ns_count; - struct nvme_namespace *ns; struct nvme_sq io_sq; struct nvme_cq io_cq; @@ -117,9 +118,15 @@ u32 block_size; u32 metadata_size; + u32 max_req_size; /* Page aligned buffer of size NVME_PAGE_SIZE. */ char *dma_buffer; + + /* Page List */ + u32 prpl_len; + void *prp1; + u64 prpl[NVME_MAX_PRPL_ENTRIES]; }; /* Data structures for NVMe admin identify commands */ @@ -131,7 +138,12 @@ char mn[40]; char fr[8]; - char _boring[516 - 72]; + u8 rab; + u8 ieee[3]; + u8 cmic; + u8 mdts; + + char _boring[516 - 78]; u32 nn; /* number of namespaces */ }; @@ -189,6 +201,7 @@ #define NVME_CQE_DW3_P (1U << 16) #define NVME_PAGE_SIZE 4096 +#define NVME_PAGE_MASK ~(NVME_PAGE_SIZE - 1) /* Length for the queue entries. */ #define NVME_SQE_SIZE_LOG 6 diff -Nru seabios-1.14.0/src/hw/usb.c seabios-1.15.0/src/hw/usb.c --- seabios-1.14.0/src/hw/usb.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/hw/usb.c 2021-12-03 01:43:20.000000000 +0000 @@ -248,14 +248,14 @@ if (ret) return NULL; - void *config = malloc_tmphigh(cfg.wTotalLength); + struct usb_config_descriptor *config = malloc_tmphigh(cfg.wTotalLength); if (!config) { warn_noalloc(); return NULL; } req.wLength = cfg.wTotalLength; ret = usb_send_default_control(pipe, &req, config); - if (ret) { + if (ret || config->wTotalLength != cfg.wTotalLength) { free(config); return NULL; } @@ -367,13 +367,24 @@ return 0; // Determine if a driver exists for this device - only look at the - // first interface of the first configuration. + // interfaces of the first configuration. + int num_iface = config->bNumInterfaces; + void *config_end = (void*)config + config->wTotalLength; struct usb_interface_descriptor *iface = (void*)(&config[1]); - if (iface->bInterfaceClass != USB_CLASS_HID - && iface->bInterfaceClass != USB_CLASS_MASS_STORAGE - && iface->bInterfaceClass != USB_CLASS_HUB) - // Not a supported device. - goto fail; + for (;;) { + if (!num_iface-- || (void*)iface + iface->bLength > config_end) + // Not a supported device. + goto fail; + if (iface->bDescriptorType == USB_DT_INTERFACE + && (iface->bInterfaceClass == USB_CLASS_HUB + || (iface->bInterfaceClass == USB_CLASS_MASS_STORAGE + && (iface->bInterfaceProtocol == US_PR_BULK + || iface->bInterfaceProtocol == US_PR_UAS)) + || (iface->bInterfaceClass == USB_CLASS_HID + && iface->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT))) + break; + iface = (void*)iface + iface->bLength; + } // Set the configuration. ret = set_configuration(usbdev->defpipe, config->bConfigurationValue); diff -Nru seabios-1.14.0/src/hw/usb.h seabios-1.15.0/src/hw/usb.h --- seabios-1.14.0/src/hw/usb.h 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/hw/usb.h 2021-12-03 01:43:20.000000000 +0000 @@ -35,6 +35,7 @@ struct usb_pipe *freelist; struct mutex_s resetlock; struct pci_device *pci; + void *mmio; u8 type; u8 maxaddr; }; diff -Nru seabios-1.14.0/src/hw/usb-hid.c seabios-1.15.0/src/hw/usb-hid.c --- seabios-1.14.0/src/hw/usb-hid.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/hw/usb-hid.c 2021-12-03 01:43:20.000000000 +0000 @@ -56,7 +56,7 @@ u8 keys[6]; }; -#define MAX_KBD_EVENT 10 +#define MAX_KBD_EVENT 16 static int usb_kbd_setup(struct usbdevice_s *usbdev diff -Nru seabios-1.14.0/src/hw/usb-xhci.c seabios-1.15.0/src/hw/usb-xhci.c --- seabios-1.14.0/src/hw/usb-xhci.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/hw/usb-xhci.c 2021-12-03 01:43:20.000000000 +0000 @@ -467,9 +467,9 @@ dprintf(3, "%s: resetting\n", __func__); writel(&xhci->op->usbcmd, XHCI_CMD_HCRST); - if (wait_bit(&xhci->op->usbcmd, XHCI_CMD_HCRST, 0, 100) != 0) + if (wait_bit(&xhci->op->usbcmd, XHCI_CMD_HCRST, 0, 1000) != 0) goto fail; - if (wait_bit(&xhci->op->usbsts, XHCI_STS_CNR, 0, 100) != 0) + if (wait_bit(&xhci->op->usbsts, XHCI_STS_CNR, 0, 1000) != 0) goto fail; writel(&xhci->op->config, xhci->slots); @@ -534,17 +534,13 @@ free(xhci); } -static void -xhci_controller_setup(struct pci_device *pci) +static struct usb_xhci_s* +xhci_controller_setup(void *baseaddr) { - void *baseaddr = pci_enable_membar(pci, PCI_BASE_ADDRESS_0); - if (!baseaddr) - return; - struct usb_xhci_s *xhci = malloc_high(sizeof(*xhci)); if (!xhci) { warn_noalloc(); - return; + return NULL; } memset(xhci, 0, sizeof(*xhci)); xhci->caps = baseaddr; @@ -559,13 +555,11 @@ xhci->slots = hcs1 & 0xff; xhci->xcap = ((hcc >> 16) & 0xffff) << 2; xhci->context64 = (hcc & 0x04) ? 1 : 0; - - xhci->usb.pci = pci; xhci->usb.type = USB_TYPE_XHCI; - dprintf(1, "XHCI init on dev %pP: regs @ %p, %d ports, %d slots" + dprintf(1, "XHCI init: regs @ %p, %d ports, %d slots" ", %d byte contexts\n" - , pci, xhci->caps, xhci->ports, xhci->slots + , xhci->caps, xhci->ports, xhci->slots , xhci->context64 ? 64 : 32); if (xhci->xcap) { @@ -616,11 +610,53 @@ dprintf(1, "XHCI driver does not support page size code %d\n" , pagesize<<12); free(xhci); - return; + return NULL; } + return xhci; +} + +static void +xhci_controller_setup_pci(struct pci_device *pci) +{ + struct usb_xhci_s *xhci; + void *baseaddr; + + baseaddr = pci_enable_membar(pci, PCI_BASE_ADDRESS_0); + if (!baseaddr) + return; + + dprintf(1, "PCI: XHCI at %pP (mmio %p)\n", pci, baseaddr); pci_enable_busmaster(pci); + xhci = xhci_controller_setup(baseaddr); + if (!xhci) + return; + + xhci->usb.pci = pci; + run_thread(configure_xhci, xhci); +} + +static void +xhci_controller_setup_acpi(struct acpi_device *dev) +{ + struct usb_xhci_s *xhci; + u64 mem, unused; + void *baseaddr; + + if (acpi_dsdt_find_mem(dev, &mem, &unused) < 0) + return; + if (mem >= 0x100000000ll) + return; + + baseaddr = (void*)(u32)mem; + dprintf(1, "ACPI: XHCI at mmio %p\n", baseaddr); + + xhci = xhci_controller_setup(baseaddr); + if (!xhci) + return; + + xhci->usb.mmio = baseaddr; run_thread(configure_xhci, xhci); } @@ -629,10 +665,19 @@ { if (! CONFIG_USB_XHCI) return; + struct pci_device *pci; foreachpci(pci) { if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_XHCI) - xhci_controller_setup(pci); + xhci_controller_setup_pci(pci); + } + + u16 xhci_eisaid = 0x0d10; + struct acpi_device *dev; + for (dev = acpi_dsdt_find_eisaid(NULL, xhci_eisaid); + dev != NULL; + dev = acpi_dsdt_find_eisaid(dev, xhci_eisaid)) { + xhci_controller_setup_acpi(dev); } } diff -Nru seabios-1.14.0/src/output.c seabios-1.15.0/src/output.c --- seabios-1.14.0/src/output.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/output.c 2021-12-03 01:43:20.000000000 +0000 @@ -160,10 +160,12 @@ // Output a single digit hex character. static inline void -putsinglehex(struct putcinfo *action, u32 val) +putsinglehex(struct putcinfo *action, u32 val, int uc) { if (val <= 9) val = '0' + val; + else if (uc) + val = 'A' + val - 10; else val = 'a' + val - 10; putc(action, val); @@ -171,23 +173,23 @@ // Output an integer in hexadecimal with a specified width. static void -puthex(struct putcinfo *action, u32 val, int width) +puthex(struct putcinfo *action, u32 val, int width, int uc) { switch (width) { - default: putsinglehex(action, (val >> 28) & 0xf); - case 7: putsinglehex(action, (val >> 24) & 0xf); - case 6: putsinglehex(action, (val >> 20) & 0xf); - case 5: putsinglehex(action, (val >> 16) & 0xf); - case 4: putsinglehex(action, (val >> 12) & 0xf); - case 3: putsinglehex(action, (val >> 8) & 0xf); - case 2: putsinglehex(action, (val >> 4) & 0xf); - case 1: putsinglehex(action, (val >> 0) & 0xf); + default: putsinglehex(action, (val >> 28) & 0xf, uc); + case 7: putsinglehex(action, (val >> 24) & 0xf, uc); + case 6: putsinglehex(action, (val >> 20) & 0xf, uc); + case 5: putsinglehex(action, (val >> 16) & 0xf, uc); + case 4: putsinglehex(action, (val >> 12) & 0xf, uc); + case 3: putsinglehex(action, (val >> 8) & 0xf, uc); + case 2: putsinglehex(action, (val >> 4) & 0xf, uc); + case 1: putsinglehex(action, (val >> 0) & 0xf, uc); } } // Output an integer in hexadecimal with a minimum width. static void -putprettyhex(struct putcinfo *action, u32 val, int width, char padchar) +putprettyhex(struct putcinfo *action, u32 val, int width, char padchar, int uc) { u32 tmp = val; int count = 1; @@ -196,18 +198,18 @@ width -= count; while (width-- > 0) putc(action, padchar); - puthex(action, val, count); + puthex(action, val, count, uc); } // Output 'struct pci_device' BDF as %02x:%02x.%x static void put_pci_device(struct putcinfo *action, struct pci_device *pci) { - puthex(action, pci_bdf_to_bus(pci->bdf), 2); + puthex(action, pci_bdf_to_bus(pci->bdf), 2, 0); putc(action, ':'); - puthex(action, pci_bdf_to_dev(pci->bdf), 2); + puthex(action, pci_bdf_to_dev(pci->bdf), 2, 0); putc(action, '.'); - puthex(action, pci_bdf_to_fn(pci->bdf), 1); + puthex(action, pci_bdf_to_fn(pci->bdf), 1, 0); } static inline int @@ -220,6 +222,7 @@ bvprintf(struct putcinfo *action, const char *fmt, va_list args) { const char *s = fmt; + int uc; for (;; s++) { char c = GET_GLOBAL(*(u8*)s); if (!c) @@ -284,19 +287,21 @@ } putc(action, '0'); putc(action, 'x'); - puthex(action, val, 8); + puthex(action, val, 8, 0); break; + case 'X': case 'x': + uc = (c == 'X'); val = va_arg(args, s32); if (is64) { u32 upper = va_arg(args, s32); if (upper) { - putprettyhex(action, upper, field_width - 8, padchar); - puthex(action, val, 8); + putprettyhex(action, upper, field_width - 8, padchar, uc); + puthex(action, val, 8, uc); break; } } - putprettyhex(action, val, field_width, padchar); + putprettyhex(action, val, field_width, padchar, uc); break; case 'c': val = va_arg(args, int); @@ -348,7 +353,7 @@ if (cur != &MainThread) { // Show "thread id" for this debug message. debug_putc(&debuginfo, '|'); - puthex(&debuginfo, (u32)cur, 8); + puthex(&debuginfo, (u32)cur, 8, 0); debug_putc(&debuginfo, '|'); debug_putc(&debuginfo, ' '); } @@ -450,12 +455,12 @@ while (len > 0) { if (count % 8 == 0) { putc(&debuginfo, '\n'); - puthex(&debuginfo, count*4, 8); + puthex(&debuginfo, count*4, 8, 0); putc(&debuginfo, ':'); } else { putc(&debuginfo, ' '); } - puthex(&debuginfo, *(u32*)d, 8); + puthex(&debuginfo, *(u32*)d, 8, 0); count++; len-=4; d+=4; diff -Nru seabios-1.14.0/src/sha1.c seabios-1.15.0/src/sha1.c --- seabios-1.14.0/src/sha1.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/sha1.c 2021-12-03 01:43:20.000000000 +0000 @@ -13,7 +13,7 @@ #include "config.h" #include "byteorder.h" // cpu_to_*, __swab64 -#include "sha1.h" // sha1 +#include "sha.h" // sha1 #include "string.h" // memcpy #include "x86.h" // rol @@ -126,11 +126,11 @@ } -u32 +void sha1(const u8 *data, u32 length, u8 *hash) { if (!CONFIG_TCGBIOS) - return 0; + return; sha1_ctx ctx = { .h[0] = 0x67452301, @@ -143,5 +143,5 @@ sha1_do(&ctx, data, length); memcpy(hash, &ctx.h[0], 20); - return 0; + return; } diff -Nru seabios-1.14.0/src/sha1.h seabios-1.15.0/src/sha1.h --- seabios-1.14.0/src/sha1.h 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/sha1.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#ifndef __SHA1_H -#define __SHA1_H - -#include "types.h" // u32 - -u32 sha1(const u8 *data, u32 length, u8 *hash); - -#endif // sha1.h diff -Nru seabios-1.14.0/src/sha256.c seabios-1.15.0/src/sha256.c --- seabios-1.14.0/src/sha256.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.15.0/src/sha256.c 2021-12-03 01:43:20.000000000 +0000 @@ -0,0 +1,211 @@ +/***************************************************************************** + * Copyright (c) 2015-2020 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* + * See: NIST standard for SHA-256 in FIPS PUB 180-4 + */ + +#include "config.h" +#include "byteorder.h" +#include "sha.h" +#include "string.h" +#include "x86.h" + +typedef struct _sha256_ctx { + u32 h[8]; +} sha256_ctx; + +static inline u32 Ch(u32 x, u32 y, u32 z) +{ + return (x & y) | ((x ^ 0xffffffff) & z); +} + +static inline u32 Maj(u32 x, u32 y, u32 z) +{ + return (x & y) | (x & z) | (y & z); +} + +static inline u32 sum0(u32 x) +{ + return ror(x, 2) ^ ror(x, 13) ^ ror(x, 22); +} + +static inline u32 sum1(u32 x) +{ + return ror(x, 6) ^ ror(x, 11) ^ ror(x, 25); +} + +static inline u32 sigma0(u32 x) +{ + return ror(x, 7) ^ ror(x, 18) ^ (x >> 3); +} + +static inline u32 sigma1(u32 x) +{ + return ror(x, 17) ^ ror(x, 19) ^ (x >> 10); +} + +static void sha256_block(u32 *w, sha256_ctx *ctx) +{ + u32 t; + u32 a, b, c, d, e, f, g, h; + u32 T1, T2; + + /* + * FIPS 180-4 4.2.2: SHA256 Constants + */ + static const u32 sha_ko[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + /* + * FIPS 180-4 6.2.2: step 1 + * + * 0 <= i <= 15: + * W(t) = M(t) + * 16 <= i <= 63: + * W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16) + */ + + /* w(0)..w(15) are in big endian format */ + for (t = 0; t <= 15; t++) + w[t] = be32_to_cpu(w[t]); + + for (t = 16; t <= 63; t++) + w[t] = sigma1(w[t-2]) + w[t-7] + sigma0(w[t-15]) + w[t-16]; + + /* + * step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7 + */ + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + /* + * step 3: For i = 0 to 63: + * T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t); + * T2 = sum0(a) + Maj(a,b,c) + * h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2 + */ + for (t = 0; t <= 63; t++) { + T1 = h + sum1(e) + Ch(e, f, g) + sha_ko[t] + w[t]; + T2 = sum0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* + * step 4: + * H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e + H4 + */ + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; +} + +static void sha256_do(sha256_ctx *ctx, const u8 *data32, u32 length) +{ + u32 offset; + u16 num; + u32 bits = 0; + u32 w[64]; + u64 tmp; + + /* treat data in 64-byte chunks */ + for (offset = 0; length - offset >= 64; offset += 64) { + memcpy(w, data32 + offset, 64); + sha256_block((u32 *)w, ctx); + bits += (64 * 8); + } + + /* last block with less than 64 bytes */ + num = length - offset; + bits += (num << 3); + + memcpy(w, data32 + offset, num); + /* + * FIPS 180-4 5.1: Padding the Message + */ + ((u8 *)w)[num] = 0x80; + if (64 - (num + 1) > 0) + memset( &((u8 *)w)[num + 1], 0, 64 - (num + 1)); + + if (num >= 56) { + /* cannot append number of bits here */ + sha256_block((u32 *)w, ctx); + memset(w, 0, 60); + } + + /* write number of bits to end of block */ + tmp = cpu_to_be64(bits); + memcpy(&w[14], &tmp, 8); + + sha256_block(w, ctx); + + /* need to switch result's endianness */ + for (num = 0; num < 8; num++) + ctx->h[num] = cpu_to_be32(ctx->h[num]); +} + +void sha256(const u8 *data, u32 length, u8 *hash) +{ + sha256_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.3: initial hash value + */ + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19 + } + }; + + sha256_do(&ctx, data, length); + memcpy(hash, ctx.h, sizeof(ctx.h)); +} diff -Nru seabios-1.14.0/src/sha512.c seabios-1.15.0/src/sha512.c --- seabios-1.14.0/src/sha512.c 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.15.0/src/sha512.c 2021-12-03 01:43:20.000000000 +0000 @@ -0,0 +1,244 @@ +/***************************************************************************** + * Copyright (c) 2021 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* + * See: NIST standard for SHA-512 and SHA-384 in FIPS PUB 180-4 & RFC 6234 + */ + +#include "config.h" +#include "byteorder.h" +#include "sha.h" +#include "string.h" + +typedef struct _sha512_ctx { + u64 h[8]; +} sha512_ctx; + +static inline u64 ror64(u64 x, u8 n) +{ + return (x >> n) | (x << (64 - n)); +} + +static inline u64 Ch64(u64 x, u64 y, u64 z) +{ + return (x & y) ^ ((x ^ 0xffffffffffffffffULL) & z); +} + +static inline u64 Maj64(u64 x, u64 y, u64 z) +{ + return (x & y) ^ (x & z) ^ (y & z); +} + +static inline u64 sum0_64(u64 x) +{ + return ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39); +} + +static inline u64 sum1_64(u64 x) +{ + return ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41); +} + +static inline u64 sigma0_64(u64 x) +{ + return ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7); +} + +static inline u64 sigma1_64(u64 x) +{ + return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6); +} + +static void sha512_block(u64 *w, sha512_ctx *ctx) +{ + u32 t; + u64 a, b, c, d, e, f, g, h; + u64 T1, T2; + + /* + * FIPS 180-4 4.2.2: SHA512 Constants + */ + static const u64 sha_ko[80] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 + }; + + /* + * FIPS 180-4 6.4.2: step 1 + * + * 0 <= i <= 15: + * W(t) = M(t) + * 16 <= i <= 79: + * W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16) + */ + + /* w(0)..w(15) are in big endian format */ + for (t = 0; t <= 15; t++) + w[t] = be64_to_cpu(w[t]); + + for (t = 16; t <= 79; t++) + w[t] = sigma1_64(w[t-2]) + w[t-7] + sigma0_64(w[t-15]) + w[t-16]; + + /* + * step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7 + */ + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + d = ctx->h[3]; + e = ctx->h[4]; + f = ctx->h[5]; + g = ctx->h[6]; + h = ctx->h[7]; + + /* + * step 3: For i = 0 to 79: + * T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t); + * T2 = sum0(a) + Maj(a,b,c) + * h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2 + */ + for (t = 0; t <= 79; t++) { + T1 = h + sum1_64(e) + Ch64(e, f, g) + sha_ko[t] + w[t]; + T2 = sum0_64(a) + Maj64(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* + * step 4: + * H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e + H4 + */ + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; + ctx->h[5] += f; + ctx->h[6] += g; + ctx->h[7] += h; +} + +static void sha512_do(sha512_ctx *ctx, const u8 *data32, u32 length) +{ + u32 offset; + u16 num; + u64 bits = 0; + u64 w[80]; + u64 tmp; + + /* treat data in 128-byte/1024 bit chunks */ + for (offset = 0; length - offset >= 128; offset += 128) { + memcpy(w, data32 + offset, 128); + sha512_block(w, ctx); + bits += (128 * 8); + } + + /* last block with less than 128 bytes */ + num = length - offset; + bits += (num << 3); + + memcpy(w, data32 + offset, num); + /* + * FIPS 180-4 5.1: Padding the Message + */ + ((u8 *)w)[num] = 0x80; + if (128 - (num + 1) > 0) + memset( &((u8 *)w)[num + 1], 0, 128 - (num + 1)); + + if (num >= 112) { + /* cannot append number of bits here; + * need space for 128 bits (16 bytes) + */ + sha512_block((u64 *)w, ctx); + memset(w, 0, 128); + } + + /* write number of bits to end of the block; we write 64 bits */ + tmp = cpu_to_be64(bits); + memcpy(&w[15], &tmp, 8); + + sha512_block(w, ctx); + + /* need to switch result's endianness */ + for (num = 0; num < 8; num++) + ctx->h[num] = cpu_to_be64(ctx->h[num]); +} + +void sha384(const u8 *data, u32 length, u8 *hash) +{ + sha512_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.4: initial hash value + */ + 0xcbbb9d5dc1059ed8, + 0x629a292a367cd507, + 0x9159015a3070dd17, + 0x152fecd8f70e5939, + 0x67332667ffc00b31, + 0x8eb44a8768581511, + 0xdb0c2e0d64f98fa7, + 0x47b5481dbefa4fa4 + } + }; + + sha512_do(&ctx, data, length); + memcpy(hash, ctx.h, 384/8); +} + +void sha512(const u8 *data, u32 length, u8 *hash) +{ + sha512_ctx ctx = { + .h = { + /* + * FIPS 180-4: 6.2.1 + * -> 5.3.5: initial hash value + */ + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179 + } + }; + + sha512_do(&ctx, data, length); + memcpy(hash, ctx.h, sizeof(ctx.h)); +} diff -Nru seabios-1.14.0/src/sha.h seabios-1.15.0/src/sha.h --- seabios-1.14.0/src/sha.h 1970-01-01 00:00:00.000000000 +0000 +++ seabios-1.15.0/src/sha.h 2021-12-03 01:43:20.000000000 +0000 @@ -0,0 +1,11 @@ +#ifndef __SHA_H +#define __SHA_H + +#include "types.h" // u32 + +void sha1(const u8 *data, u32 length, u8 *hash); +void sha256(const u8 *data, u32 length, u8 *hash); +void sha384(const u8 *data, u32 length, u8 *hash); +void sha512(const u8 *data, u32 length, u8 *hash); + +#endif // sha.h diff -Nru seabios-1.14.0/src/stacks.c seabios-1.15.0/src/stacks.c --- seabios-1.14.0/src/stacks.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/stacks.c 2021-12-03 01:43:20.000000000 +0000 @@ -549,6 +549,8 @@ dprintf(1, "All threads complete.\n"); } +void VISIBLE16 check_irqs(void); + // Create a new thread and start executing 'func' in it. void run_thread(void (*func)(void*), void *data) @@ -564,6 +566,7 @@ dprintf(DEBUG_thread, "/%08x\\ Start thread\n", (u32)thread); thread->stackpos = (void*)thread + THREADSTACKSIZE; struct thread_info *cur = getCurThread(); + struct thread_info *edx = cur; hlist_add_after(&thread->node, &cur->node); asm volatile( // Start thread @@ -582,9 +585,12 @@ " popl %%ebp\n" // restore %ebp " retl\n" // restore pc "1:\n" - : "+a"(data), "+c"(func), "+b"(thread), "+d"(cur) + : "+a"(data), "+c"(func), "+b"(thread), "+d"(edx) : "m"(*(u8*)__end_thread), "m"(MainThread) : "esi", "edi", "cc", "memory"); + if (cur == &MainThread) + // Permit irqs to fire + check_irqs(); return; fail: @@ -623,12 +629,11 @@ return; } struct thread_info *cur = getCurThread(); + // Switch to the next thread + switch_next(cur); if (cur == &MainThread) // Permit irqs to fire check_irqs(); - - // Switch to the next thread - switch_next(cur); } void VISIBLE16 diff -Nru seabios-1.14.0/src/tcgbios.c seabios-1.15.0/src/tcgbios.c --- seabios-1.14.0/src/tcgbios.c 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/tcgbios.c 2021-12-03 01:43:20.000000000 +0000 @@ -16,7 +16,7 @@ #include "fw/paravirt.h" // runningOnXen #include "hw/tpm_drivers.h" // tpm_drivers[] #include "output.h" // dprintf -#include "sha1.h" // sha1 +#include "sha.h" // sha1, sha256, ... #include "std/acpi.h" // RSDP_SIGNATURE, rsdt_descriptor #include "std/smbios.h" // struct smbios_entry_point #include "std/tcg.h" // TCG_PC_LOGOVERFLOW @@ -167,27 +167,32 @@ u8 hashalg_flag; u8 hash_buffersize; const char *name; + void (*hashfunc)(const u8 *data, u32 length, u8 *hash); } hash_parameters[] = { { .hashalg = TPM2_ALG_SHA1, .hashalg_flag = TPM2_ALG_SHA1_FLAG, .hash_buffersize = SHA1_BUFSIZE, .name = "SHA1", + .hashfunc = sha1, }, { .hashalg = TPM2_ALG_SHA256, .hashalg_flag = TPM2_ALG_SHA256_FLAG, .hash_buffersize = SHA256_BUFSIZE, .name = "SHA256", + .hashfunc = sha256, }, { .hashalg = TPM2_ALG_SHA384, .hashalg_flag = TPM2_ALG_SHA384_FLAG, .hash_buffersize = SHA384_BUFSIZE, .name = "SHA384", + .hashfunc = sha384, }, { .hashalg = TPM2_ALG_SHA512, .hashalg_flag = TPM2_ALG_SHA512_FLAG, .hash_buffersize = SHA512_BUFSIZE, .name = "SHA512", + .hashfunc = sha512, }, { .hashalg = TPM2_ALG_SM3_256, .hashalg_flag = TPM2_ALG_SM3_256_FLAG, @@ -259,6 +264,21 @@ return NULL; } +static void tpm2_hash_data(u16 hashAlg, const u8 *data, u32 data_len, u8 *hash) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) { + if (hash_parameters[i].hashalg == hashAlg) { + if (hash_parameters[i].hashfunc) { + hash_parameters[i].hashfunc(data, data_len, hash); + } else { + memset(hash, 0xff, hash_parameters[i].hash_buffersize); + } + } + } +} + // Add an entry at the start of the log describing digest formats static int tpm20_write_EfiSpecIdEventStruct(void) @@ -274,7 +294,7 @@ .hdr.platformClass = TPM_TCPA_ACPI_CLASS_CLIENT, .hdr.specVersionMinor = 0, .hdr.specVersionMajor = 2, - .hdr.specErrata = 0, + .hdr.specErrata = 2, .hdr.uintnSize = 2, }; @@ -342,14 +362,16 @@ * hash when writing it in the area of the sha1 hash. * * le: the log entry to build the digest in - * sha1: the sha1 hash value to use + * hashdata: the data to hash + * hashdata_len: the length of the hashdata * bigEndian: whether to build in big endian format for the TPM or * little endian for the log * * Returns the digest size; -1 on fatal error */ static int -tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) +tpm20_build_digest(struct tpm_log_entry *le, + const u8 *hashdata, u32 hashdata_len, int bigEndian) { if (!tpm20_pcr_selection) return -1; @@ -391,8 +413,8 @@ else v->hashAlg = be16_to_cpu(sel->hashAlg); - memset(v->hash, 0, hsize); - memcpy(v->hash, sha1, hsize > SHA1_BUFSIZE ? SHA1_BUFSIZE : hsize); + tpm2_hash_data(be16_to_cpu(sel->hashAlg), hashdata, hashdata_len, + v->hash); dest += sizeof(*v) + hsize; sel = nsel; @@ -415,7 +437,15 @@ } static int -tpm12_build_digest(struct tpm_log_entry *le, const u8 *sha1) +tpm12_build_digest(struct tpm_log_entry *le, + const u8 *hashdata, u32 hashdata_len) +{ + sha1(hashdata, hashdata_len, le->hdr.digest); + return SHA1_BUFSIZE; +} + +static int +tpm12_build_digest_direct(struct tpm_log_entry *le, const u8 *sha1) { // On TPM 1.2 the digest contains just the SHA1 hash memcpy(le->hdr.digest, sha1, SHA1_BUFSIZE); @@ -423,13 +453,14 @@ } static int -tpm_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) +tpm_build_digest(struct tpm_log_entry *le, const u8 *hashdata, u32 hashdata_len + , int bigEndian) { switch (TPM_version) { case TPM_VERSION_1_2: - return tpm12_build_digest(le, sha1); + return tpm12_build_digest(le, hashdata, hashdata_len); case TPM_VERSION_2: - return tpm20_build_digest(le, sha1, bigEndian); + return tpm20_build_digest(le, hashdata, hashdata_len, bigEndian); } return -1; } @@ -952,6 +983,7 @@ case TPM_VERSION_2: tpm20_hierarchycontrol(TPM2_RH_ENDORSEMENT, TPM2_NO); tpm20_hierarchycontrol(TPM2_RH_OWNER, TPM2_NO); + tpm20_hierarchycontrol(TPM2_RH_PLATFORM, TPM2_NO); break; } @@ -978,14 +1010,11 @@ if (!tpm_is_working()) return; - u8 hash[SHA1_BUFSIZE]; - sha1(hashdata, hashdata_length, hash); - struct tpm_log_entry le = { .hdr.pcrindex = pcrindex, .hdr.eventtype = event_type, }; - int digest_len = tpm_build_digest(&le, hash, 1); + int digest_len = tpm_build_digest(&le, hashdata, hashdata_length, 1); if (digest_len < 0) return; int ret = tpm_extend(&le, digest_len); @@ -993,7 +1022,7 @@ tpm_set_failure(); return; } - tpm_build_digest(&le, hash, 0); + tpm_build_digest(&le, hashdata, hashdata_length, 0); tpm_log_event(&le.hdr, digest_len, event, event_length); } @@ -1016,7 +1045,8 @@ u32 pcrIndex; for (pcrIndex = 0; pcrIndex <= 7; pcrIndex++) tpm_add_measurement_to_log(pcrIndex, EV_SEPARATOR, - NULL, 0, + (const char *)evt_separator, + sizeof(evt_separator), evt_separator, sizeof(evt_separator)); } @@ -1406,7 +1436,7 @@ .hdr.pcrindex = pcpes->pcrindex, .hdr.eventtype = pcpes->eventtype, }; - int digest_len = tpm_build_digest(&le, pcpes->digest, 1); + int digest_len = tpm12_build_digest_direct(&le, pcpes->digest); if (digest_len < 0) return TCG_GENERAL_ERROR; if (extend) { @@ -1414,7 +1444,7 @@ if (ret) return TCG_TCG_COMMAND_ERROR; } - tpm_build_digest(&le, pcpes->digest, 0); + tpm12_build_digest_direct(&le, pcpes->digest); int ret = tpm_log_event(&le.hdr, digest_len , pcpes->event, pcpes->eventdatasize); if (ret) diff -Nru seabios-1.14.0/src/x86.h seabios-1.15.0/src/x86.h --- seabios-1.14.0/src/x86.h 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/src/x86.h 2021-12-03 01:43:20.000000000 +0000 @@ -140,6 +140,13 @@ return res; } +static inline u32 ror(u32 val, u16 ror) { + u32 res; + asm volatile("rorl %%cl, %%eax" + : "=a" (res) : "a" (val), "c" (ror)); + return res; +} + static inline void outb(u8 value, u16 port) { __asm__ __volatile__("outb %b0, %w1" : : "a"(value), "Nd"(port)); } diff -Nru seabios-1.14.0/.version seabios-1.15.0/.version --- seabios-1.14.0/.version 2020-08-10 15:34:22.000000000 +0000 +++ seabios-1.15.0/.version 2021-12-03 02:29:16.000000000 +0000 @@ -1 +1 @@ -1.14.0 +1.15.0 diff -Nru seabios-1.14.0/vgasrc/vgalayout.lds.S seabios-1.15.0/vgasrc/vgalayout.lds.S --- seabios-1.14.0/vgasrc/vgalayout.lds.S 2020-08-10 14:53:07.000000000 +0000 +++ seabios-1.15.0/vgasrc/vgalayout.lds.S 2021-12-03 01:43:20.000000000 +0000 @@ -19,5 +19,12 @@ // Discard regular data sections to force a link error if // 16bit code attempts to access data not marked with VAR16. - /DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) } + /DISCARD/ : { + *(.text*) + *(.rodata*) + *(.data*) + *(.bss*) + *(COMMON) + *(.note*) + } }