From 49319f1bc9f34b15f061742a8d4f8d3acfdafd42 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 1 Mar 2020 11:58:47 +0000 Subject: [bios] Define macros for constructing partition table entries Signed-off-by: Michael Brown --- src/arch/x86/prefix/usbdisk.S | 47 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 10 deletions(-) (limited to 'src/arch') diff --git a/src/arch/x86/prefix/usbdisk.S b/src/arch/x86/prefix/usbdisk.S index 9676406e2..830f3774c 100644 --- a/src/arch/x86/prefix/usbdisk.S +++ b/src/arch/x86/prefix/usbdisk.S @@ -9,26 +9,53 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) #include "mbr.S" /* Partition table: 64 heads, 32 sectors/track (ZIP-drive compatible) */ +#define HEADS 64 +#define SECTORS 32 +#define CYLADDR(cyl) ((((cyl) * HEADS + (((cyl) == 0) & 1)) * SECTORS) * 512) + +#define LOGSTART 0 +#define LOGCOUNT 1 +#define BOOTSTART 1 +#define BOOTCOUNT 2 + + /* Construct a C/H/S address */ + .macro chs cylinder, head, sector + .byte \head + .byte (((\cylinder & 0x300) >> 2) | \sector) + .byte (\cylinder & 0x0ff) + .endm + + /* Construct a linear address */ + .macro linear cylinders, heads, sectors + .long ((((\cylinders * HEADS) + \heads) * SECTORS) + \sectors - 1) + .endm + + /* Construct a partition table entry */ + .macro partition bootflag, type, start, count + .byte \bootflag + chs \start, ((\start == 0) & 1), 1 + .byte \type + chs (\start + \count - 1), (HEADS - 1), SECTORS + linear \start, ((\start == 0) & 1), 1 + linear \count, 0, (1 - (((\start == 0) & 1) * SECTORS)) + .endm + + /* Partition table */ .org 446 .space 16 .space 16 /* Partition 3: log partition (for CONSOLE_INT13) */ - .byte 0x00, 0x01, 0x01, 0x00 - .byte 0xe0, 0x3f, 0x20, 0x00 - .long 0x00000020 - .long 0x000007e0 + partition 0x00, 0xe0, LOGSTART, LOGCOUNT /* Partition 4: boot partition */ - .byte 0x80, 0x00, 0x01, 0x01 - .byte 0xeb, 0x3f, 0x20, 0x02 - .long 0x00000800 - .long 0x00001000 + partition 0x80, 0xeb, BOOTSTART, BOOTCOUNT + /* Disk signature */ .org 510 .byte 0x55, 0xaa /* Skip to start of log partition */ - .org 32 * 512 + .org CYLADDR(LOGSTART) .ascii "iPXE LOG\n\n" /* Skip to start of boot partition */ - .org 2048 * 512 + .org CYLADDR(BOOTSTART) -- cgit v1.2.3-55-g7522 From efc1ae5abac01a77c5816884612c9daf0c344e8a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 1 Mar 2020 12:56:28 +0000 Subject: [int13con] Create log partition only when CONSOLE_INT13 is enabled Reduce the size of the USB disk image in the common case that CONSOLE_INT13 is not enabled. Originally-implemented-by: Romain Guyard Signed-off-by: Michael Brown --- src/arch/x86/prefix/usbdisk.S | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/arch') diff --git a/src/arch/x86/prefix/usbdisk.S b/src/arch/x86/prefix/usbdisk.S index 830f3774c..977de6dd6 100644 --- a/src/arch/x86/prefix/usbdisk.S +++ b/src/arch/x86/prefix/usbdisk.S @@ -1,5 +1,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) +#include + .text .arch i386 .section ".prefix", "awx", @progbits @@ -13,10 +15,17 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) #define SECTORS 32 #define CYLADDR(cyl) ((((cyl) * HEADS + (((cyl) == 0) & 1)) * SECTORS) * 512) +#ifdef CONSOLE_INT13 +#define LOGPART 1 #define LOGSTART 0 #define LOGCOUNT 1 #define BOOTSTART 1 #define BOOTCOUNT 2 +#else /* CONSOLE_INT13 */ +#define LOGPART 0 +#define BOOTSTART 0 +#define BOOTCOUNT 2 +#endif /* CONSOLE_INT13 */ /* Construct a C/H/S address */ .macro chs cylinder, head, sector @@ -44,8 +53,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) .org 446 .space 16 .space 16 + /* Partition 3: log partition (for CONSOLE_INT13) */ + .if LOGPART partition 0x00, 0xe0, LOGSTART, LOGCOUNT + .else + .space 16 + .endif + /* Partition 4: boot partition */ partition 0x80, 0xeb, BOOTSTART, BOOTCOUNT @@ -54,8 +69,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) .byte 0x55, 0xaa /* Skip to start of log partition */ + .if LOGPART .org CYLADDR(LOGSTART) .ascii "iPXE LOG\n\n" + .endif /* Skip to start of boot partition */ .org CYLADDR(BOOTSTART) -- cgit v1.2.3-55-g7522 From decee20ec84977ae1d1a7f54fa91e73017f6731d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 26 Jun 2020 21:21:31 +0100 Subject: [build] Disable position-independent code for ARM64 EFI builds Some versions of gcc (observed with the cross-compiling gcc 9.3.0 in Ubuntu 20.04) default to enabling -fPIE. Experimentation shows that this results in the emission of R_AARCH64_ADR_GOT_PAGE relocation records for __stack_chk_guard. These relocation types are not supported by elf2efi.c. Fix by explicitly disabling position-independent code for ARM64 EFI builds. Debugged-by: Antony Messerli Signed-off-by: Michael Brown --- src/arch/arm64/Makefile.efi | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/arch') diff --git a/src/arch/arm64/Makefile.efi b/src/arch/arm64/Makefile.efi index 998a64d03..eb04c0e2f 100644 --- a/src/arch/arm64/Makefile.efi +++ b/src/arch/arm64/Makefile.efi @@ -1,5 +1,9 @@ # -*- makefile -*- : Force emacs to use Makefile mode +# Avoid untranslatable relocations +# +CFLAGS += -fno-pic + # Specify EFI image builder # ELF2EFI = $(ELF2EFI64) -- cgit v1.2.3-55-g7522 From d2fb317fee9635008b8298add7d6f1d5534cec59 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 7 Jul 2020 00:09:40 +0100 Subject: [crypto] Avoid temporarily setting direction flag in bigint_is_geq() The UEFI specification states that the calling convention for IA-32 and x64 includes "Direction flag in EFLAGS is clear". This specification covers only the calling convention used at the point of calling functions annotated with EFIAPI. The specification explicitly states that other functions (such as private functions or static library calls) are not required to follow the UEFI calling conventions. The reference EDK2 implementation follows this specification. In particular, the EDK2 interrupt handlers will clear the direction flag before calling any EFIAPI functions, and will restore the direction flag when returning from the interrupt handler. Some EDK2 private library functions (most notably InternalMemCopyMem) may set the direction flag temporarily in order to make efficient use of CPU string operations. The current implementation of iPXE's bigint_is_geq() for i386 and x86_64 will similarly set the direction flag temporarily in order to make efficient use of CPU string operations. On some UEFI implementations (observed with a Getac RX10 tablet), a timer interrupt that happens to occur while the direction flag is set will reboot the machine. This very strongly indicates that the UEFI timer interrupt handler is failing to clear the direction flag before performing an affected operation (such as copying a block of memory). Work around such buggy UEFI implementations by rewriting bigint_is_geq() to avoid the use of string operations and so obviate the requirement to temporarily set the direction flag. Signed-off-by: Michael Brown --- src/arch/x86/include/bits/bigint.h | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'src/arch') diff --git a/src/arch/x86/include/bits/bigint.h b/src/arch/x86/include/bits/bigint.h index c9bb6ea45..4f1bc87ff 100644 --- a/src/arch/x86/include/bits/bigint.h +++ b/src/arch/x86/include/bits/bigint.h @@ -167,28 +167,19 @@ bigint_is_zero_raw ( const uint32_t *value0, unsigned int size ) { static inline __attribute__ (( always_inline, pure )) int bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0, unsigned int size ) { - const bigint_t ( size ) __attribute__ (( may_alias )) *value = - ( ( const void * ) value0 ); - const bigint_t ( size ) __attribute__ (( may_alias )) *reference = - ( ( const void * ) reference0 ); - void *discard_S; - void *discard_D; long discard_c; + long discard_tmp; int result; - __asm__ __volatile__ ( "std\n\t" - "\n1:\n\t" - "lodsl\n\t" - "scasl\n\t" + __asm__ __volatile__ ( "\n1:\n\t" + "movl -4(%3, %1, 4), %k2\n\t" + "cmpl -4(%4, %1, 4), %k2\n\t" "loope 1b\n\t" "setae %b0\n\t" - "cld\n\t" - : "=q" ( result ), "=&S" ( discard_S ), - "=&D" ( discard_D ), "=&c" ( discard_c ) - : "0" ( 0 ), "1" ( &value->element[ size - 1 ] ), - "2" ( &reference->element[ size - 1 ] ), - "3" ( size ) - : "eax" ); + : "=q" ( result ), "=&c" ( discard_c ), + "=&r" ( discard_tmp ) + : "r" ( value0 ), "r" ( reference0 ), + "0" ( 0 ), "1" ( size ) ); return result; } -- cgit v1.2.3-55-g7522 From 98d49e460a27f74212aab2d6b5eef1143c7a8e37 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 7 Jul 2020 13:49:17 +0100 Subject: [efi] Avoid setting direction flag on EFI platforms The only remaining use case in iPXE for the CPU direction flag is in __memcpy_reverse() where it is set to allow the use of "rep movsb" to perform the memory copy. This matches the equivalent functionality in the EDK2 codebase, which has functions such as InternalMemCopyMem that also temporarily set the direction flag in order to use "rep movsb". As noted in commit d2fb317 ("[crypto] Avoid temporarily setting direction flag in bigint_is_geq()"), some UEFI implementations are known to have buggy interrupt handlers that may reboot the machine if a timer interrupt happens to occur while the direction flag is set. Work around these buggy UEFI implementations by using the (unoptimised) generic_memcpy_reverse() on i386 or x86_64 UEFI platforms. Signed-off-by: Michael Brown --- src/arch/x86/core/x86_string.c | 14 ++++++++++++++ src/config/defaults/efi.h | 1 + 2 files changed, 15 insertions(+) (limited to 'src/arch') diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c index 7d5e4a5f1..1a1e79dac 100644 --- a/src/arch/x86/core/x86_string.c +++ b/src/arch/x86/core/x86_string.c @@ -30,6 +30,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include +#include + +/* Use generic_memcpy_reverse() if we cannot safely set the direction flag */ +#ifdef UNSAFE_STD +#define USE_GENERIC_MEMCPY_REVERSE 1 +#else +#define USE_GENERIC_MEMCPY_REVERSE 0 +#endif /** * Copy memory area @@ -77,6 +85,12 @@ void * __attribute__ (( noinline )) __memcpy_reverse ( void *dest, const void *esi = ( src + len - 1 ); int discard_ecx; + /* Use unoptimised version if we are not permitted to modify + * the direction flag. + */ + if ( USE_GENERIC_MEMCPY_REVERSE ) + return generic_memcpy_reverse ( dest, src, len ); + /* Assume memmove() is not performance-critical, and perform a * bytewise copy for simplicity. */ diff --git a/src/config/defaults/efi.h b/src/config/defaults/efi.h index 53a7a7b4b..e707dfa6a 100644 --- a/src/config/defaults/efi.h +++ b/src/config/defaults/efi.h @@ -46,6 +46,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define IOAPI_X86 #define NAP_EFIX86 #define CPUID_CMD /* x86 CPU feature detection command */ +#define UNSAFE_STD /* Avoid setting direction flag */ #endif #if defined ( __arm__ ) || defined ( __aarch64__ ) -- cgit v1.2.3-55-g7522 From 45a0ca6de221f8886a9bfb02f0d34af4fc2f1c5d Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Tue, 14 Jan 2020 23:31:03 -0800 Subject: [pcbios] Fix "out of memory" detection when expanding bottom area This caused iPXE to reject images even when enough memory was available. Signed-off-by: David Decotigny Signed-off-by: Michael Brown --- src/arch/x86/interface/pcbios/memtop_umalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/arch') diff --git a/src/arch/x86/interface/pcbios/memtop_umalloc.c b/src/arch/x86/interface/pcbios/memtop_umalloc.c index f1ab73e29..d7b82189a 100644 --- a/src/arch/x86/interface/pcbios/memtop_umalloc.c +++ b/src/arch/x86/interface/pcbios/memtop_umalloc.c @@ -190,7 +190,7 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) { /* Expand/shrink block if possible */ if ( ptr == bottom ) { /* Update block */ - if ( new_size > ( heap_size - extmem.size ) ) { + if ( new_size > ( heap_size + extmem.size ) ) { DBG ( "EXTMEM out of space\n" ); return UNULL; } -- cgit v1.2.3-55-g7522 From 6ec33b8d6cc607579fcc90f551146831890d2070 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Tue, 14 Jan 2020 23:42:05 -0800 Subject: [pcbios] Take alignment into account when checking for available space Signed-off-by: David Decotigny Signed-off-by: Michael Brown --- src/arch/x86/interface/pcbios/memtop_umalloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/arch') diff --git a/src/arch/x86/interface/pcbios/memtop_umalloc.c b/src/arch/x86/interface/pcbios/memtop_umalloc.c index d7b82189a..1d3f40a1c 100644 --- a/src/arch/x86/interface/pcbios/memtop_umalloc.c +++ b/src/arch/x86/interface/pcbios/memtop_umalloc.c @@ -190,14 +190,14 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) { /* Expand/shrink block if possible */ if ( ptr == bottom ) { /* Update block */ - if ( new_size > ( heap_size + extmem.size ) ) { - DBG ( "EXTMEM out of space\n" ); - return UNULL; - } new = userptr_add ( ptr, - ( new_size - extmem.size ) ); align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) ); new_size += align; new = userptr_add ( new, -align ); + if ( new_size > ( heap_size + extmem.size ) ) { + DBG ( "EXTMEM out of space\n" ); + return UNULL; + } DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n", user_to_phys ( ptr, 0 ), user_to_phys ( ptr, extmem.size ), -- cgit v1.2.3-55-g7522 From 70b1a641c543cc6d87965df93d1b48eed4e15297 Mon Sep 17 00:00:00 2001 From: Dentcho Ludmilov Bankov Date: Sat, 2 Feb 2019 00:20:21 +0200 Subject: [comboot] Fix stack pointer retrieval after COM32 binary returns This change fixes the offset used when retrieving the iPXE stack pointer after a COM32 binary returns. The iPXE stack pointer is saved at the top of the available memory then the the top of the stack for the COM32 binary is set just below it. However seven more items are pushed on the COM32 stack before the entry point is invoked so when the COM32 binary returns the location of the iPXE stack pointer is 28 (and not 24) bytes above the current stack pointer. Signed-off-by: Michael Brown --- src/arch/x86/image/com32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/arch') diff --git a/src/arch/x86/image/com32.c b/src/arch/x86/image/com32.c index 016652877..6f0e66041 100644 --- a/src/arch/x86/image/com32.c +++ b/src/arch/x86/image/com32.c @@ -110,7 +110,7 @@ static int com32_exec_loop ( struct image *image ) { /* Disable interrupts */ "cli\n\t" /* Restore stack pointer */ - "movl 24(%%esp), %%esp\n\t" + "movl 28(%%esp), %%esp\n\t" /* Restore registers */ "popal\n\t" ) : -- cgit v1.2.3-55-g7522