![Nigel Croxon](/assets/img/avatar_default.png)
Subject: [PATCH 2/2] Replace ARM arithmetic support routines with EDK2 versions. Replace the incomplete GPL licensed ARM arithmetic support routines with the ones from the EDK2 project. These cover long long multiplication and long long logical shift as well. Also remove the special case for small dividends in DivU64x32: we can simply let the compiler handle this, and emit calls to the support routines where appropriate. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Nigel Croxon <nigel.croxon@hpe.com>
141 lines
4.2 KiB
C
141 lines
4.2 KiB
C
|
|
#include <stdint.h>
|
|
|
|
/*
|
|
* This prevents GCC from emitting GOT based relocations, and use R_ARM_REL32
|
|
* relative relocations instead, which are more suitable for static binaries.
|
|
*/
|
|
#pragma GCC visibility push (hidden)
|
|
|
|
//
|
|
// Basic EFI types of various widths
|
|
//
|
|
|
|
#ifndef __WCHAR_TYPE__
|
|
# define __WCHAR_TYPE__ short
|
|
#endif
|
|
|
|
typedef uint64_t UINT64;
|
|
typedef int64_t INT64;
|
|
|
|
typedef uint32_t UINT32;
|
|
typedef int32_t INT32;
|
|
|
|
typedef uint16_t UINT16;
|
|
typedef int16_t INT16;
|
|
typedef uint8_t UINT8;
|
|
typedef int8_t INT8;
|
|
typedef __WCHAR_TYPE__ WCHAR;
|
|
|
|
#undef VOID
|
|
#define VOID void
|
|
|
|
typedef int32_t INTN;
|
|
typedef uint32_t UINTN;
|
|
|
|
#define EFIERR(a) (0x80000000 | a)
|
|
#define EFI_ERROR_MASK 0x80000000
|
|
#define EFIERR_OEM(a) (0xc0000000 | a)
|
|
|
|
#define BAD_POINTER 0xFBFBFBFB
|
|
#define MAX_ADDRESS 0xFFFFFFFF
|
|
|
|
#define BREAKPOINT() while (TRUE);
|
|
|
|
//
|
|
// Pointers must be aligned to these address to function
|
|
//
|
|
|
|
#define MIN_ALIGNMENT_SIZE 4
|
|
|
|
#define ALIGN_VARIABLE(Value ,Adjustment) \
|
|
(UINTN)Adjustment = 0; \
|
|
if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
|
|
(UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
|
|
Value = (UINTN)Value + (UINTN)Adjustment
|
|
|
|
|
|
//
|
|
// Define macros to build data structure signatures from characters.
|
|
//
|
|
|
|
#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
|
|
#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
|
|
#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
|
|
|
|
//
|
|
// EFIAPI - prototype calling convention for EFI function pointers
|
|
// BOOTSERVICE - prototype for implementation of a boot service interface
|
|
// RUNTIMESERVICE - prototype for implementation of a runtime service interface
|
|
// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
|
|
// RUNTIME_CODE - pragma macro for declaring runtime code
|
|
//
|
|
|
|
#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
|
|
#define EFIAPI // Substitute expresion to force C calling convention
|
|
#endif
|
|
|
|
#define BOOTSERVICE
|
|
#define RUNTIMESERVICE
|
|
#define RUNTIMEFUNCTION
|
|
|
|
|
|
#define RUNTIME_CODE(a) alloc_text("rtcode", a)
|
|
#define BEGIN_RUNTIME_DATA() data_seg("rtdata")
|
|
#define END_RUNTIME_DATA() data_seg("")
|
|
|
|
#define VOLATILE volatile
|
|
|
|
#define MEMORY_FENCE __sync_synchronize
|
|
|
|
//
|
|
// When build similiar to FW, then link everything together as
|
|
// one big module.
|
|
//
|
|
|
|
#define EFI_DRIVER_ENTRY_POINT(InitFunction) \
|
|
UINTN \
|
|
InitializeDriver ( \
|
|
VOID *ImageHandle, \
|
|
VOID *SystemTable \
|
|
) \
|
|
{ \
|
|
return InitFunction(ImageHandle, \
|
|
SystemTable); \
|
|
} \
|
|
\
|
|
EFI_STATUS efi_main( \
|
|
EFI_HANDLE image, \
|
|
EFI_SYSTEM_TABLE *systab \
|
|
) __attribute__((weak, \
|
|
alias ("InitializeDriver")));
|
|
|
|
#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \
|
|
(_if)->LoadInternal(type, name, entry)
|
|
|
|
|
|
//
|
|
// Some compilers don't support the forward reference construct:
|
|
// typedef struct XXXXX
|
|
//
|
|
// The following macro provide a workaround for such cases.
|
|
|
|
#define INTERFACE_DECL(x) struct x
|
|
|
|
#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__)
|
|
#define EFI_FUNCTION
|
|
|
|
static inline UINT64 DivU64x32(UINT64 Dividend, UINTN Divisor, UINTN *Remainder)
|
|
{
|
|
/*
|
|
* GCC turns a division into a multiplication and shift with precalculated
|
|
* constants if the divisor is constant and the dividend fits into a 32 bit
|
|
* variable. Otherwise, it will turn this into calls into the 32-bit div
|
|
* library functions.
|
|
*/
|
|
if (Remainder)
|
|
*Remainder = Dividend % Divisor;
|
|
Dividend = Dividend / Divisor;
|
|
return Dividend;
|
|
}
|