From 13c1abe10abd1c24307a6777b6cedfc5b46b088d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 12 May 2021 10:09:33 +0100 Subject: [prefix] Specify i486 architecture for LZMA decompressor The decompressor uses the i486 "bswap" instruction, but does not require any instructions that exist only on i586 or above. Update the ".arch" directive to reflect the requirements of the code as implemented. Reported-by: Martin Habets Signed-off-by: Michael Brown --- src/arch/x86/prefix/unlzma.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/arch') diff --git a/src/arch/x86/prefix/unlzma.S b/src/arch/x86/prefix/unlzma.S index 956eeb24c..979f699ee 100644 --- a/src/arch/x86/prefix/unlzma.S +++ b/src/arch/x86/prefix/unlzma.S @@ -44,7 +44,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ .text - .arch i586 + .arch i486 .section ".prefix.lib", "ax", @progbits #ifdef CODE16 -- cgit v1.2.3-55-g7522 From 05fcf1a2f0809b8d87ca5affea1f1bfe0996235b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 12 May 2021 10:24:00 +0100 Subject: [rng] Check for TSC support before using RTC entropy source Signed-off-by: Michael Brown --- src/arch/x86/include/ipxe/cpuid.h | 3 +++ src/arch/x86/interface/pcbios/rtc_entropy.c | 11 +++++++++++ 2 files changed, 14 insertions(+) (limited to 'src/arch') diff --git a/src/arch/x86/include/ipxe/cpuid.h b/src/arch/x86/include/ipxe/cpuid.h index b5403bd9d..3983dfb89 100644 --- a/src/arch/x86/include/ipxe/cpuid.h +++ b/src/arch/x86/include/ipxe/cpuid.h @@ -42,6 +42,9 @@ struct x86_features { /** Hypervisor is present */ #define CPUID_FEATURES_INTEL_ECX_HYPERVISOR 0x80000000UL +/** TSC is present */ +#define CPUID_FEATURES_INTEL_EDX_TSC 0x00000010UL + /** FXSAVE and FXRSTOR are supported */ #define CPUID_FEATURES_INTEL_EDX_FXSR 0x01000000UL diff --git a/src/arch/x86/interface/pcbios/rtc_entropy.c b/src/arch/x86/interface/pcbios/rtc_entropy.c index e9e6baa59..e0c175685 100644 --- a/src/arch/x86/interface/pcbios/rtc_entropy.c +++ b/src/arch/x86/interface/pcbios/rtc_entropy.c @@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include /** Maximum time to wait for an RTC interrupt, in milliseconds */ @@ -174,8 +175,17 @@ static int rtc_entropy_check ( void ) { * @ret rc Return status code */ static int rtc_entropy_enable ( void ) { + struct x86_features features; int rc; + /* Check that TSC is supported */ + x86_features ( &features ); + if ( ! ( features.intel.edx & CPUID_FEATURES_INTEL_EDX_TSC ) ) { + DBGC ( &rtc_flag, "RTC has no TSC\n" ); + rc = -ENOTSUP; + goto err_no_tsc; + } + /* Hook ISR and enable RTC interrupts */ rtc_hook_isr(); enable_irq ( RTC_IRQ ); @@ -191,6 +201,7 @@ static int rtc_entropy_enable ( void ) { rtc_disable_int(); disable_irq ( RTC_IRQ ); rtc_unhook_isr(); + err_no_tsc: return rc; } -- cgit v1.2.3-55-g7522 From a6a8bb1a9a58becb82dfacc7bc27cf645d0e216c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 12 May 2021 10:55:17 +0100 Subject: [undi] Read TSC only when profiling Avoid using the "rdtsc" instruction unless profiling is enabled. This allows the non-debug build of the UNDI driver to be used on a CPU such as a 486 that does not support the TSC. Reported-by: Nikolai Zhubr Signed-off-by: Michael Brown --- src/arch/x86/drivers/net/undinet.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/arch') diff --git a/src/arch/x86/drivers/net/undinet.c b/src/arch/x86/drivers/net/undinet.c index 9b7d6d849..43cb18bfe 100644 --- a/src/arch/x86/drivers/net/undinet.c +++ b/src/arch/x86/drivers/net/undinet.c @@ -104,6 +104,13 @@ static union u_PXENV_ANY __bss16 ( undinet_params ); SEGOFF16_t __bss16 ( undinet_entry_point ); #define undinet_entry_point __use_data16 ( undinet_entry_point ) +/* Read TSC in real mode only when profiling */ +#if PROFILING +#define RDTSC_IF_PROFILING "rdtsc\n\t" +#else +#define RDTSC_IF_PROFILING "" +#endif + /** IRQ profiler */ static struct profiler undinet_irq_profiler __profiler = { .name = "undinet.irq" }; @@ -288,14 +295,14 @@ static int undinet_call ( struct undi_nic *undinic, unsigned int function, */ profile_start ( &profiler->total ); __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */ - "rdtsc\n\t" + RDTSC_IF_PROFILING "pushl %%eax\n\t" "pushw %%es\n\t" "pushw %%di\n\t" "pushw %%bx\n\t" "lcall *undinet_entry_point\n\t" "movw %%ax, %%bx\n\t" - "rdtsc\n\t" + RDTSC_IF_PROFILING "addw $6, %%sp\n\t" "popl %%edx\n\t" "popl %%ebp\n\t" /* gcc bug */ ) -- cgit v1.2.3-55-g7522 From bfca3db41e9af78e56e7a9b7f30121df83b6af0a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 17 May 2021 14:57:48 +0100 Subject: [cpio] Split out bzImage initrd CPIO header construction iPXE will construct CPIO headers for images that have a non-empty command line, thereby allowing raw images (without CPIO headers) to be injected into a dynamically constructed initrd. This feature is currently implemented within the BIOS-only bzImage format support. Split out the CPIO header construction logic to allow for reuse in other contexts such as in a UEFI build. Signed-off-by: Michael Brown --- src/arch/x86/image/bzimage.c | 52 ++------------------------ src/arch/x86/image/initrd.c | 1 + src/arch/x86/include/initrd.h | 7 ---- src/core/cpio.c | 85 +++++++++++++++++++++++++++++++++++++++++++ src/include/ipxe/cpio.h | 21 +++++++++++ 5 files changed, 110 insertions(+), 56 deletions(-) (limited to 'src/arch') diff --git a/src/arch/x86/image/bzimage.c b/src/arch/x86/image/bzimage.c index 51498bf95..a782127a1 100644 --- a/src/arch/x86/image/bzimage.c +++ b/src/arch/x86/image/bzimage.c @@ -326,32 +326,6 @@ static void bzimage_set_cmdline ( struct image *image, DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline ); } -/** - * Parse standalone image command line for cpio parameters - * - * @v image bzImage file - * @v cpio CPIO header - * @v cmdline Command line - */ -static void bzimage_parse_cpio_cmdline ( struct image *image, - struct cpio_header *cpio, - const char *cmdline ) { - char *arg; - char *end; - unsigned int mode; - - /* Look for "mode=" */ - if ( ( arg = strstr ( cmdline, "mode=" ) ) ) { - arg += 5; - mode = strtoul ( arg, &end, 8 /* Octal for file mode */ ); - if ( *end && ( *end != ' ' ) ) { - DBGC ( image, "bzImage %p strange \"mode=\"" - "terminator '%c'\n", image, *end ); - } - cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) ); - } -} - /** * Align initrd length * @@ -374,11 +348,9 @@ static inline size_t bzimage_align ( size_t len ) { static size_t bzimage_load_initrd ( struct image *image, struct image *initrd, userptr_t address ) { - char *filename = initrd->cmdline; - char *cmdline; + const char *filename = cpio_name ( initrd ); struct cpio_header cpio; size_t offset; - size_t name_len; size_t pad_len; /* Do not include kernel image itself as an initrd */ @@ -386,25 +358,7 @@ static size_t bzimage_load_initrd ( struct image *image, return 0; /* Create cpio header for non-prebuilt images */ - if ( filename && filename[0] ) { - cmdline = strchr ( filename, ' ' ); - name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) ) - : strlen ( filename ) ) + 1 /* NUL */ ); - memset ( &cpio, '0', sizeof ( cpio ) ); - memcpy ( cpio.c_magic, CPIO_MAGIC, sizeof ( cpio.c_magic ) ); - cpio_set_field ( cpio.c_mode, 0100644 ); - cpio_set_field ( cpio.c_nlink, 1 ); - cpio_set_field ( cpio.c_filesize, initrd->len ); - cpio_set_field ( cpio.c_namesize, name_len ); - if ( cmdline ) { - bzimage_parse_cpio_cmdline ( image, &cpio, - ( cmdline + 1 /* ' ' */ )); - } - offset = ( ( sizeof ( cpio ) + name_len + 0x03 ) & ~0x03 ); - } else { - offset = 0; - name_len = 0; - } + offset = cpio_header ( initrd, &cpio ); /* Copy in initrd image body (and cpio header if applicable) */ if ( address ) { @@ -413,7 +367,7 @@ static size_t bzimage_load_initrd ( struct image *image, memset_user ( address, 0, 0, offset ); copy_to_user ( address, 0, &cpio, sizeof ( cpio ) ); copy_to_user ( address, sizeof ( cpio ), filename, - ( name_len - 1 /* NUL (or space) */ ) ); + cpio_name_len ( initrd ) ); } DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)" "%s%s\n", image, initrd, user_to_phys ( address, 0 ), diff --git a/src/arch/x86/image/initrd.c b/src/arch/x86/image/initrd.c index 49b959a91..d7b1f5773 100644 --- a/src/arch/x86/image/initrd.c +++ b/src/arch/x86/image/initrd.c @@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include /** @file * diff --git a/src/arch/x86/include/initrd.h b/src/arch/x86/include/initrd.h index ddb3e5a45..2fb9d3d3a 100644 --- a/src/arch/x86/include/initrd.h +++ b/src/arch/x86/include/initrd.h @@ -11,13 +11,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include -/** Minimum alignment for initrds - * - * Some versions of Linux complain about initrds that are not - * page-aligned. - */ -#define INITRD_ALIGN 4096 - /** Minimum free space required to reshuffle initrds * * Chosen to avoid absurdly long reshuffling times diff --git a/src/core/cpio.c b/src/core/cpio.c index 080c72daf..27aee7581 100644 --- a/src/core/cpio.c +++ b/src/core/cpio.c @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ #include +#include #include #include @@ -45,3 +46,87 @@ void cpio_set_field ( char *field, unsigned long value ) { snprintf ( buf, sizeof ( buf ), "%08lx", value ); memcpy ( field, buf, 8 ); } + +/** + * Get CPIO image filename + * + * @v image Image + * @ret len CPIO filename length (0 for no filename) + */ +size_t cpio_name_len ( struct image *image ) { + const char *name = cpio_name ( image ); + char *sep; + size_t len; + + /* Check for existence of CPIO filename */ + if ( ! name ) + return 0; + + /* Locate separator (if any) */ + sep = strchr ( name, ' ' ); + len = ( sep ? ( ( size_t ) ( sep - name ) ) : strlen ( name ) ); + + return len; +} + +/** + * Parse CPIO image parameters + * + * @v image Image + * @v cpio CPIO header to fill in + */ +static void cpio_parse_cmdline ( struct image *image, + struct cpio_header *cpio ) { + const char *cmdline; + char *arg; + char *end; + unsigned int mode; + + /* Skip image filename */ + cmdline = ( cpio_name ( image ) + cpio_name_len ( image ) ); + + /* Look for "mode=" */ + if ( ( arg = strstr ( cmdline, "mode=" ) ) ) { + arg += 5; + mode = strtoul ( arg, &end, 8 /* Octal for file mode */ ); + if ( *end && ( *end != ' ' ) ) { + DBGC ( image, "CPIO %p strange \"mode=\" " + "terminator '%c'\n", image, *end ); + } + cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) ); + } +} + +/** + * Construct CPIO header for image, if applicable + * + * @v image Image + * @v cpio CPIO header to fill in + * @ret len Length of magic CPIO header (including filename) + */ +size_t cpio_header ( struct image *image, struct cpio_header *cpio ) { + size_t name_len; + size_t len; + + /* Get filename length */ + name_len = cpio_name_len ( image ); + + /* Images with no filename are assumed to already be CPIO archives */ + if ( ! name_len ) + return 0; + + /* Construct CPIO header */ + memset ( cpio, '0', sizeof ( *cpio ) ); + memcpy ( cpio->c_magic, CPIO_MAGIC, sizeof ( cpio->c_magic ) ); + cpio_set_field ( cpio->c_mode, 0100644 ); + cpio_set_field ( cpio->c_nlink, 1 ); + cpio_set_field ( cpio->c_filesize, image->len ); + cpio_set_field ( cpio->c_namesize, ( name_len + 1 /* NUL */ ) ); + cpio_parse_cmdline ( image, cpio ); + + /* Calculate total length */ + len = ( ( sizeof ( *cpio ) + name_len + 1 /* NUL */ + CPIO_ALIGN - 1 ) + & ~( CPIO_ALIGN - 1 ) ); + + return len; +} diff --git a/src/include/ipxe/cpio.h b/src/include/ipxe/cpio.h index 0637c531d..9c5e22d5a 100644 --- a/src/include/ipxe/cpio.h +++ b/src/include/ipxe/cpio.h @@ -9,6 +9,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +#include + /** A CPIO archive header * * All field are hexadecimal ASCII numbers padded with '0' on the @@ -48,6 +50,25 @@ struct cpio_header { /** CPIO magic */ #define CPIO_MAGIC "070701" +/** CPIO header length alignment */ +#define CPIO_ALIGN 4 + +/** Alignment for CPIO archives within an initrd */ +#define INITRD_ALIGN 4096 + +/** + * Get CPIO image name + * + * @v image Image + * @ret name Image name (not NUL terminated) + */ +static inline __attribute__ (( always_inline )) const char * +cpio_name ( struct image *image ) { + return image->cmdline; +} + extern void cpio_set_field ( char *field, unsigned long value ); +extern size_t cpio_name_len ( struct image *image ); +extern size_t cpio_header ( struct image *image, struct cpio_header *cpio ); #endif /* _IPXE_CPIO_H */ -- cgit v1.2.3-55-g7522 From f3f568e382a5f19824b3bfc6081cde39eee661e8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 3 Jun 2021 13:34:14 +0100 Subject: [crypto] Add memory output constraints for big-integer inline assembly The ARM versions of the big-integer inline assembly functions include constraints to indicate that the output value is modified by the assembly code. These constraints are not present in the equivalent code for the x86 versions. As of GCC 11, this results in the compiler reporting that the output values may be uninitialized. Fix by including the relevant memory output constraints. Reported-by: Christian Hesse Signed-off-by: Michael Brown --- src/arch/x86/core/x86_bigint.c | 11 ++++---- src/arch/x86/include/bits/bigint.h | 54 ++++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 22 deletions(-) (limited to 'src/arch') diff --git a/src/arch/x86/core/x86_bigint.c b/src/arch/x86/core/x86_bigint.c index 6413b2fa8..9a25bdad5 100644 --- a/src/arch/x86/core/x86_bigint.c +++ b/src/arch/x86/core/x86_bigint.c @@ -75,17 +75,18 @@ void bigint_multiply_raw ( const uint32_t *multiplicand0, * * a < 2^{n}, b < 2^{n} => ab < 2^{2n} */ - __asm__ __volatile__ ( "mull %4\n\t" - "addl %%eax, (%5,%2,4)\n\t" - "adcl %%edx, 4(%5,%2,4)\n\t" + __asm__ __volatile__ ( "mull %5\n\t" + "addl %%eax, (%6,%2,4)\n\t" + "adcl %%edx, 4(%6,%2,4)\n\t" "\n1:\n\t" - "adcl $0, 8(%5,%2,4)\n\t" + "adcl $0, 8(%6,%2,4)\n\t" "inc %2\n\t" /* Does not affect CF */ "jc 1b\n\t" : "=&a" ( discard_a ), "=&d" ( discard_d ), - "=&r" ( index ) + "=&r" ( index ), + "+m" ( *result ) : "0" ( multiplicand_element ), "g" ( multiplier_element ), "r" ( result_elements ), diff --git a/src/arch/x86/include/bits/bigint.h b/src/arch/x86/include/bits/bigint.h index 4f1bc87ff..7443d6fdc 100644 --- a/src/arch/x86/include/bits/bigint.h +++ b/src/arch/x86/include/bits/bigint.h @@ -25,19 +25,22 @@ typedef uint32_t bigint_element_t; static inline __attribute__ (( always_inline )) void bigint_init_raw ( uint32_t *value0, unsigned int size, const void *data, size_t len ) { - long pad_len = ( sizeof ( bigint_t ( size ) ) - len ); + bigint_t ( size ) __attribute__ (( may_alias )) *value = + ( ( void * ) value0 ); + long pad_len = ( sizeof ( *value ) - len ); void *discard_D; long discard_c; /* Copy raw data in reverse order, padding with zeros */ __asm__ __volatile__ ( "\n1:\n\t" - "movb -1(%2,%1), %%al\n\t" + "movb -1(%3,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" - "mov %3, %1\n\t" + "mov %4, %1\n\t" "rep stosb\n\t" - : "=&D" ( discard_D ), "=&c" ( discard_c ) + : "=&D" ( discard_D ), "=&c" ( discard_c ), + "+m" ( *value ) : "r" ( data ), "g" ( pad_len ), "0" ( value0 ), "1" ( len ) : "eax" ); @@ -53,6 +56,8 @@ bigint_init_raw ( uint32_t *value0, unsigned int size, static inline __attribute__ (( always_inline )) void bigint_add_raw ( const uint32_t *addend0, uint32_t *value0, unsigned int size ) { + bigint_t ( size ) __attribute__ (( may_alias )) *value = + ( ( void * ) value0 ); long index; void *discard_S; long discard_c; @@ -60,11 +65,11 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0, __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */ "\n1:\n\t" "lodsl\n\t" - "adcl %%eax, (%3,%0,4)\n\t" + "adcl %%eax, (%4,%0,4)\n\t" "inc %0\n\t" /* Does not affect CF */ "loop 1b\n\t" : "=&r" ( index ), "=&S" ( discard_S ), - "=&c" ( discard_c ) + "=&c" ( discard_c ), "+m" ( *value ) : "r" ( value0 ), "1" ( addend0 ), "2" ( size ) : "eax" ); } @@ -79,6 +84,8 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0, static inline __attribute__ (( always_inline )) void bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0, unsigned int size ) { + bigint_t ( size ) __attribute__ (( may_alias )) *value = + ( ( void * ) value0 ); long index; void *discard_S; long discard_c; @@ -86,11 +93,11 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0, __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */ "\n1:\n\t" "lodsl\n\t" - "sbbl %%eax, (%3,%0,4)\n\t" + "sbbl %%eax, (%4,%0,4)\n\t" "inc %0\n\t" /* Does not affect CF */ "loop 1b\n\t" : "=&r" ( index ), "=&S" ( discard_S ), - "=&c" ( discard_c ) + "=&c" ( discard_c ), "+m" ( *value ) : "r" ( value0 ), "1" ( subtrahend0 ), "2" ( size ) : "eax" ); @@ -104,15 +111,18 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0, */ static inline __attribute__ (( always_inline )) void bigint_rol_raw ( uint32_t *value0, unsigned int size ) { + bigint_t ( size ) __attribute__ (( may_alias )) *value = + ( ( void * ) value0 ); long index; long discard_c; __asm__ __volatile__ ( "xor %0, %0\n\t" /* Zero %0 and clear CF */ "\n1:\n\t" - "rcll $1, (%2,%0,4)\n\t" + "rcll $1, (%3,%0,4)\n\t" "inc %0\n\t" /* Does not affect CF */ "loop 1b\n\t" - : "=&r" ( index ), "=&c" ( discard_c ) + : "=&r" ( index ), "=&c" ( discard_c ), + "+m" ( *value ) : "r" ( value0 ), "1" ( size ) ); } @@ -124,13 +134,15 @@ bigint_rol_raw ( uint32_t *value0, unsigned int size ) { */ static inline __attribute__ (( always_inline )) void bigint_ror_raw ( uint32_t *value0, unsigned int size ) { + bigint_t ( size ) __attribute__ (( may_alias )) *value = + ( ( void * ) value0 ); long discard_c; __asm__ __volatile__ ( "clc\n\t" "\n1:\n\t" - "rcrl $1, -4(%1,%0,4)\n\t" + "rcrl $1, -4(%2,%0,4)\n\t" "loop 1b\n\t" - : "=&c" ( discard_c ) + : "=&c" ( discard_c ), "+m" ( *value ) : "r" ( value0 ), "0" ( size ) ); } @@ -239,6 +251,8 @@ bigint_max_set_bit_raw ( const uint32_t *value0, unsigned int size ) { static inline __attribute__ (( always_inline )) void bigint_grow_raw ( const uint32_t *source0, unsigned int source_size, uint32_t *dest0, unsigned int dest_size ) { + bigint_t ( dest_size ) __attribute__ (( may_alias )) *dest = + ( ( void * ) dest0 ); long pad_size = ( dest_size - source_size ); void *discard_D; void *discard_S; @@ -246,10 +260,10 @@ bigint_grow_raw ( const uint32_t *source0, unsigned int source_size, __asm__ __volatile__ ( "rep movsl\n\t" "xorl %%eax, %%eax\n\t" - "mov %3, %2\n\t" + "mov %4, %2\n\t" "rep stosl\n\t" : "=&D" ( discard_D ), "=&S" ( discard_S ), - "=&c" ( discard_c ) + "=&c" ( discard_c ), "+m" ( *dest ) : "g" ( pad_size ), "0" ( dest0 ), "1" ( source0 ), "2" ( source_size ) : "eax" ); @@ -266,13 +280,15 @@ bigint_grow_raw ( const uint32_t *source0, unsigned int source_size, static inline __attribute__ (( always_inline )) void bigint_shrink_raw ( const uint32_t *source0, unsigned int source_size __unused, uint32_t *dest0, unsigned int dest_size ) { + bigint_t ( dest_size ) __attribute__ (( may_alias )) *dest = + ( ( void * ) dest0 ); void *discard_D; void *discard_S; long discard_c; __asm__ __volatile__ ( "rep movsl\n\t" : "=&D" ( discard_D ), "=&S" ( discard_S ), - "=&c" ( discard_c ) + "=&c" ( discard_c ), "+m" ( *dest ) : "0" ( dest0 ), "1" ( source0 ), "2" ( dest_size ) : "eax" ); @@ -289,15 +305,19 @@ bigint_shrink_raw ( const uint32_t *source0, unsigned int source_size __unused, static inline __attribute__ (( always_inline )) void bigint_done_raw ( const uint32_t *value0, unsigned int size __unused, void *out, size_t len ) { + struct { + uint8_t bytes[len]; + } __attribute__ (( may_alias )) *out_bytes = out; void *discard_D; long discard_c; /* Copy raw data in reverse order */ __asm__ __volatile__ ( "\n1:\n\t" - "movb -1(%2,%1), %%al\n\t" + "movb -1(%3,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" - : "=&D" ( discard_D ), "=&c" ( discard_c ) + : "=&D" ( discard_D ), "=&c" ( discard_c ), + "+m" ( *out_bytes ) : "r" ( value0 ), "0" ( out ), "1" ( len ) : "eax" ); } -- cgit v1.2.3-55-g7522